Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/redis_exporter/redis_exporter_test.go
5395 views
1
package redis_exporter //nolint:golint
2
3
import (
4
"bytes"
5
"fmt"
6
"io"
7
"net/http"
8
"net/http/httptest"
9
"testing"
10
11
"github.com/grafana/agent/pkg/config"
12
13
"github.com/go-kit/log"
14
"github.com/gorilla/mux"
15
"github.com/prometheus/prometheus/model/textparse"
16
"github.com/stretchr/testify/require"
17
)
18
19
const addr string = "localhost:6379"
20
const redisExporterFile string = "./redis_exporter.go"
21
const redisPasswordMapFile string = "./testdata/password_map_file.json"
22
23
func TestRedisCases(t *testing.T) {
24
tt := []struct {
25
name string
26
cfg Config
27
expectedMetrics []string
28
expectConstructorError bool
29
}{
30
// Test that default config results in some metrics that can be parsed by
31
// prometheus.
32
{
33
name: "Default config",
34
cfg: (func() Config {
35
c := DefaultConfig
36
c.RedisAddr = addr
37
return c
38
})(),
39
expectedMetrics: []string{},
40
},
41
// Test that exporter metrics are included when configured to do so.
42
{
43
name: "Include exporter metrics",
44
cfg: (func() Config {
45
c := DefaultConfig
46
c.RedisAddr = addr
47
c.IncludeExporterMetrics = true
48
return c
49
})(),
50
expectedMetrics: []string{
51
"promhttp_metric_handler_requests_total",
52
"promhttp_metric_handler_requests_in_flight",
53
},
54
},
55
// Test that some valid pre-constructor config logic doesn't cause errors.
56
{
57
name: "Lua script read OK",
58
cfg: (func() Config {
59
c := DefaultConfig
60
c.RedisAddr = addr
61
c.ScriptPath = redisExporterFile // file content is irrelevant
62
return c
63
})(),
64
},
65
// Test that multiple lua scripts in a csv doesn't cause errors.
66
{
67
name: "Multiple Lua scripts read OK",
68
cfg: (func() Config {
69
c := DefaultConfig
70
c.RedisAddr = addr
71
c.ScriptPath = fmt.Sprintf("%s,%s", redisExporterFile, redisPasswordMapFile) // file contents are irrelevant
72
return c
73
})(),
74
},
75
// Test that some invalid pre-constructor config logic causes an error.
76
{
77
name: "Lua script read fail",
78
cfg: (func() Config {
79
c := DefaultConfig
80
c.RedisAddr = addr
81
c.ScriptPath = "/does/not/exist"
82
return c
83
})(),
84
expectConstructorError: true,
85
},
86
// Test exporter complains when no address given via env or config.
87
{
88
name: "no address given",
89
cfg: Config{}, // no address in here
90
expectConstructorError: true,
91
},
92
// Test exporter constructs ok when password file is defined and exists
93
{
94
name: "valid password file",
95
cfg: (func() Config {
96
c := DefaultConfig
97
c.RedisAddr = addr
98
c.RedisPasswordFile = redisExporterFile // contents not important
99
return c
100
})(),
101
},
102
// Test exporter construction fails when password file is defined and doesn't
103
// exist
104
{
105
name: "invalid password file",
106
cfg: (func() Config {
107
c := DefaultConfig
108
c.RedisAddr = addr
109
c.RedisPasswordFile = "/does/not/exist"
110
return c
111
})(),
112
expectConstructorError: true,
113
},
114
// Test exporter constructs ok when password map file is defined, exists, and is valid
115
{
116
name: "valid password map file",
117
cfg: (func() Config {
118
c := DefaultConfig
119
c.RedisAddr = addr
120
c.RedisPasswordMapFile = redisPasswordMapFile
121
return c
122
})(),
123
},
124
// Test exporter fails to construct when the password map file is not valid json
125
{
126
name: "invalid password map file",
127
cfg: (func() Config {
128
c := DefaultConfig
129
c.RedisAddr = addr
130
c.RedisPasswordMapFile = redisExporterFile
131
return c
132
})(),
133
expectConstructorError: true,
134
},
135
// Test exporter construction fails when both redis_password_file and redis_password_map_file
136
// are specified
137
{
138
name: "too many password files",
139
cfg: (func() Config {
140
c := DefaultConfig
141
c.RedisAddr = addr
142
c.RedisPasswordFile = redisExporterFile // contents not important
143
c.RedisPasswordMapFile = redisExporterFile // contents not important
144
return c
145
})(),
146
expectConstructorError: true,
147
},
148
}
149
150
logger := log.NewNopLogger()
151
152
for _, test := range tt {
153
t.Run(test.name, func(t *testing.T) {
154
integration, err := New(logger, &test.cfg)
155
156
if test.expectConstructorError {
157
require.Error(t, err, "expected failure when setting up redis_exporter")
158
return
159
}
160
require.NoError(t, err, "failed to setup redis_exporter")
161
162
r := mux.NewRouter()
163
handler, err := integration.MetricsHandler()
164
require.NoError(t, err)
165
r.Handle("/metrics", handler)
166
require.NoError(t, err)
167
168
srv := httptest.NewServer(r)
169
defer srv.Close()
170
171
res, err := http.Get(srv.URL + "/metrics")
172
require.NoError(t, err)
173
174
body, err := io.ReadAll(res.Body)
175
require.NoError(t, err)
176
177
foundMetricNames := map[string]bool{}
178
for _, name := range test.expectedMetrics {
179
foundMetricNames[name] = false
180
}
181
182
p := textparse.NewPromParser(body)
183
for {
184
entry, err := p.Next()
185
if err == io.EOF {
186
break
187
}
188
require.NoError(t, err)
189
190
if entry == textparse.EntryHelp {
191
matchMetricNames(foundMetricNames, p)
192
}
193
}
194
195
for metric, exists := range foundMetricNames {
196
require.True(t, exists, "could not find metric %s", metric)
197
}
198
})
199
}
200
}
201
202
func TestConfig_SecretRedisPassword(t *testing.T) {
203
stringCfg := `
204
prometheus:
205
wal_directory: /tmp/agent
206
integrations:
207
redis_exporter:
208
enabled: true
209
redis_password: secret_password
210
`
211
config.CheckSecret(t, stringCfg, "secret_password")
212
}
213
214
func matchMetricNames(names map[string]bool, p textparse.Parser) {
215
for name := range names {
216
metricName, _ := p.Help()
217
if bytes.Equal([]byte(name), metricName) {
218
names[name] = true
219
}
220
}
221
}
222
223