Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/v2/register_test.go
5333 views
1
package integrations
2
3
import (
4
"testing"
5
"time"
6
7
"github.com/go-kit/log"
8
v1 "github.com/grafana/agent/pkg/integrations"
9
"github.com/grafana/agent/pkg/integrations/v2/common"
10
"github.com/stretchr/testify/require"
11
"gopkg.in/yaml.v2"
12
)
13
14
func TestIntegrationRegistration(t *testing.T) {
15
setRegistered(t, map[Config]Type{
16
&testIntegrationA{}: TypeEither,
17
&testIntegrationB{}: TypeEither,
18
})
19
20
// This test checks for a few things:
21
//
22
// 1. Registered integrations will be parseable
23
// 2. Registered integrations that are not present will not be unmarshaled to
24
// the list of configs
25
// 3. Registered integrations that have defaults may still be parsed
26
// 4. Strict parsing should still work as expected.
27
28
var cfgToParse = `
29
name: John Doe
30
duration: 500ms
31
test:
32
text: Hello, world!
33
`
34
35
var fullCfg testFullConfig
36
err := yaml.UnmarshalStrict([]byte(cfgToParse), &fullCfg)
37
require.NoError(t, err)
38
39
expect := testFullConfig{
40
Name: "John Doe",
41
Duration: 500 * time.Millisecond,
42
Default: 12345,
43
Configs: []Config{
44
&testIntegrationA{Text: "Hello, world!", Truth: true},
45
},
46
}
47
require.Equal(t, expect, fullCfg)
48
}
49
50
func TestIntegrationRegistration_Multiple(t *testing.T) {
51
setRegistered(t, map[Config]Type{
52
&testIntegrationA{}: TypeEither,
53
&testIntegrationB{}: TypeEither,
54
})
55
56
var cfgToParse = `
57
name: John Doe
58
duration: 500ms
59
test_configs:
60
- text: Hello, world!
61
- text: Hello again!`
62
63
var fullCfg testFullConfig
64
err := yaml.UnmarshalStrict([]byte(cfgToParse), &fullCfg)
65
require.NoError(t, err)
66
67
expect := testFullConfig{
68
Name: "John Doe",
69
Duration: 500 * time.Millisecond,
70
Default: 12345,
71
Configs: []Config{
72
&testIntegrationA{Text: "Hello, world!", Truth: true},
73
&testIntegrationA{Text: "Hello again!", Truth: true},
74
},
75
}
76
require.Equal(t, expect, fullCfg)
77
}
78
79
func TestIntegrationRegistration_Mixed(t *testing.T) {
80
setRegistered(t, map[Config]Type{
81
&testIntegrationA{}: TypeEither,
82
&testIntegrationB{}: TypeEither,
83
})
84
85
var cfgToParse = `
86
name: John Doe
87
duration: 500ms
88
test:
89
text: Hello, world!
90
test_configs:
91
- text: Hello again!`
92
93
var fullCfg testFullConfig
94
err := yaml.UnmarshalStrict([]byte(cfgToParse), &fullCfg)
95
require.NoError(t, err)
96
97
expect := testFullConfig{
98
Name: "John Doe",
99
Duration: 500 * time.Millisecond,
100
Default: 12345,
101
Configs: []Config{
102
&testIntegrationA{Text: "Hello, world!", Truth: true},
103
&testIntegrationA{Text: "Hello again!", Truth: true},
104
},
105
}
106
require.Equal(t, expect, fullCfg)
107
}
108
109
func TestIntegrationRegistration_Legacy(t *testing.T) {
110
setRegistered(t, nil)
111
112
RegisterLegacy(&legacyConfig{}, TypeSingleton, func(in v1.Config, mc common.MetricsConfig) UpgradedConfig {
113
return &legacyShim{Data: in, Common: mc}
114
})
115
116
var cfgToParse = `
117
name: John Doe
118
duration: 500ms
119
legacy:
120
text: hello`
121
122
var fullCfg testFullConfig
123
err := yaml.UnmarshalStrict([]byte(cfgToParse), &fullCfg)
124
require.NoError(t, err)
125
126
require.Len(t, fullCfg.Configs, 1)
127
require.IsType(t, &legacyShim{}, fullCfg.Configs[0])
128
129
shim := fullCfg.Configs[0].(*legacyShim)
130
require.IsType(t, &legacyConfig{}, shim.Data)
131
132
v1Config := shim.Data.(*legacyConfig)
133
require.Equal(t, "hello", v1Config.Text)
134
}
135
136
func TestIntegrationRegistration_Legacy_Multiplex(t *testing.T) {
137
setRegistered(t, nil)
138
139
RegisterLegacy(&legacyConfig{}, TypeMultiplex, func(in v1.Config, mc common.MetricsConfig) UpgradedConfig {
140
return &legacyShim{Data: in, Common: mc}
141
})
142
143
var cfgToParse = `
144
name: John Doe
145
duration: 500ms
146
legacy_configs:
147
- text: hello
148
- text: world`
149
150
var fullCfg testFullConfig
151
err := yaml.UnmarshalStrict([]byte(cfgToParse), &fullCfg)
152
require.NoError(t, err)
153
154
require.Len(t, fullCfg.Configs, 2)
155
require.IsType(t, &legacyShim{}, fullCfg.Configs[0])
156
require.IsType(t, &legacyShim{}, fullCfg.Configs[1])
157
158
shim := fullCfg.Configs[0].(*legacyShim)
159
require.IsType(t, &legacyConfig{}, shim.Data)
160
require.Equal(t, "hello", shim.Data.(*legacyConfig).Text)
161
162
shim = fullCfg.Configs[1].(*legacyShim)
163
require.IsType(t, &legacyConfig{}, shim.Data)
164
require.Equal(t, "world", shim.Data.(*legacyConfig).Text)
165
}
166
167
func TestIntegrationRegistration_Marshal_MultipleSingleton(t *testing.T) {
168
setRegistered(t, map[Config]Type{
169
&testIntegrationA{}: TypeSingleton,
170
&testIntegrationB{}: TypeSingleton,
171
})
172
173
// Generate an invalid config, which has two instances of a Singleton
174
// integration.
175
input := testFullConfig{
176
Name: "John Doe",
177
Duration: 500 * time.Millisecond,
178
Default: 12345,
179
Configs: []Config{
180
&testIntegrationA{Text: "Hello, world!", Truth: true},
181
&testIntegrationA{Text: "Hello again!", Truth: true},
182
},
183
}
184
185
_, err := yaml.Marshal(&input)
186
require.EqualError(t, err, `integration "test" may not be defined more than once`)
187
}
188
189
type legacyConfig struct {
190
Text string `yaml:"text"`
191
}
192
193
func (lc *legacyConfig) Name() string { return "legacy" }
194
func (lc *legacyConfig) InstanceKey(agentKey string) (string, error) { return agentKey, nil }
195
func (lc *legacyConfig) NewIntegration(l log.Logger) (v1.Integration, error) { return nil, nil }
196
197
type legacyShim struct {
198
Data v1.Config
199
Common common.MetricsConfig
200
}
201
202
func (s *legacyShim) LegacyConfig() (v1.Config, common.MetricsConfig) { return s.Data, s.Common }
203
func (s *legacyShim) Name() string { return s.Data.Name() }
204
func (s *legacyShim) ApplyDefaults(g Globals) error {
205
s.Common.ApplyDefaults(g.SubsystemOpts.Metrics.Autoscrape)
206
return nil
207
}
208
func (s *legacyShim) Identifier(g Globals) (string, error) { return g.AgentIdentifier, nil }
209
func (s *legacyShim) NewIntegration(log.Logger, Globals) (Integration, error) {
210
return NoOpIntegration, nil
211
}
212
213
type testIntegrationA struct {
214
Text string `yaml:"text"`
215
Truth bool `yaml:"truth"`
216
}
217
218
func (i *testIntegrationA) Name() string { return "test" }
219
func (i *testIntegrationA) ApplyDefaults(Globals) error { return nil }
220
func (i *testIntegrationA) Identifier(Globals) (string, error) { return "integrationA", nil }
221
func (i *testIntegrationA) NewIntegration(log.Logger, Globals) (Integration, error) {
222
return NoOpIntegration, nil
223
}
224
225
func (i *testIntegrationA) UnmarshalYAML(unmarshal func(interface{}) error) error {
226
i.Truth = true
227
type plain testIntegrationA
228
return unmarshal((*plain)(i))
229
}
230
231
type testIntegrationB struct {
232
Text string `yaml:"text"`
233
}
234
235
func (*testIntegrationB) Name() string { return "shouldnotbefound" }
236
func (*testIntegrationB) ApplyDefaults(Globals) error { return nil }
237
func (*testIntegrationB) Identifier(Globals) (string, error) { return "integrationB", nil }
238
func (*testIntegrationB) NewIntegration(log.Logger, Globals) (Integration, error) {
239
return NoOpIntegration, nil
240
}
241
242
type testFullConfig struct {
243
// Some random fields that will also be exposed
244
Name string `yaml:"name"`
245
Duration time.Duration `yaml:"duration"`
246
Default int `yaml:"default"`
247
248
Configs Configs `yaml:"-"`
249
}
250
251
func (c *testFullConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
252
// This default value should not change.
253
c.Default = 12345
254
return UnmarshalYAML(c, unmarshal)
255
}
256
257
func (c testFullConfig) MarshalYAML() (interface{}, error) {
258
return MarshalYAML(c)
259
}
260
261