Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/azure_exporter/config_test.go
5371 views
1
package azure_exporter_test
2
3
import (
4
"fmt"
5
"reflect"
6
"testing"
7
8
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
9
"github.com/stretchr/testify/require"
10
"github.com/webdevops/azure-metrics-exporter/metrics"
11
12
"github.com/grafana/agent/pkg/integrations/azure_exporter"
13
)
14
15
func TestConfig_ToScrapeSettings(t *testing.T) {
16
baseConfig := azure_exporter.Config{
17
Subscriptions: []string{"subscriptionA"},
18
ResourceType: "resourceType",
19
ResourceGraphQueryFilter: "filter_me",
20
Metrics: []string{"MetricA"},
21
MetricAggregations: []string{"MiNimUm"},
22
Timespan: "timespan_me",
23
IncludedResourceTags: []string{"tag_me"},
24
MetricNamespace: "namespace_me",
25
MetricNameTemplate: "name_template_me",
26
MetricHelpTemplate: "help_template_me",
27
AzureCloudEnvironment: "azurecloud",
28
}
29
baseSettings := metrics.RequestMetricSettings{
30
Subscriptions: []string{"subscriptionA"},
31
ResourceType: "resourceType",
32
Filter: "filter_me",
33
Timespan: "timespan_me",
34
Interval: to.Ptr("timespan_me"),
35
Metrics: []string{"MetricA"},
36
MetricNamespace: "namespace_me",
37
Aggregations: []string{"MiNimUm"},
38
MetricTemplate: "name_template_me",
39
HelpTemplate: "help_template_me",
40
TagLabels: []string{"tag_me"},
41
//Should not be set
42
Name: "",
43
MetricTop: nil,
44
MetricFilter: "",
45
MetricOrderBy: "",
46
Cache: nil,
47
}
48
49
baseConfigValid := t.Run("maps expected fields", func(t *testing.T) {
50
settings, err := baseConfig.ToScrapeSettings()
51
require.NoError(t, err)
52
require.Equal(t, &baseSettings, settings)
53
})
54
if !baseConfigValid {
55
return
56
}
57
58
tests := []struct {
59
name string
60
configModifier func(azure_exporter.Config) azure_exporter.Config
61
toExpectedSettings func(metrics.RequestMetricSettings) metrics.RequestMetricSettings
62
}{
63
{
64
name: "can set a metric filter for a single dimension",
65
configModifier: func(config azure_exporter.Config) azure_exporter.Config {
66
config.IncludedDimensions = []string{"dimension1"}
67
return config
68
},
69
toExpectedSettings: func(settings metrics.RequestMetricSettings) metrics.RequestMetricSettings {
70
settings.MetricFilter = "dimension1 eq '*'"
71
settings.MetricTop = to.Ptr[int32](100_000_000)
72
return settings
73
},
74
},
75
{
76
name: "can set a metric filter for a multiple dimensions",
77
configModifier: func(config azure_exporter.Config) azure_exporter.Config {
78
config.IncludedDimensions = []string{"dimension1", "dimension2", "dimension3"}
79
return config
80
},
81
toExpectedSettings: func(settings metrics.RequestMetricSettings) metrics.RequestMetricSettings {
82
settings.MetricFilter = "dimension1 eq '*' and dimension2 eq '*' and dimension3 eq '*'"
83
settings.MetricTop = to.Ptr[int32](100_000_000)
84
return settings
85
},
86
},
87
{
88
name: "sets config timespan to setting interval and timespan",
89
configModifier: func(config azure_exporter.Config) azure_exporter.Config {
90
config.Timespan = "timespan-value"
91
return config
92
},
93
toExpectedSettings: func(settings metrics.RequestMetricSettings) metrics.RequestMetricSettings {
94
settings.Timespan = "timespan-value"
95
settings.Interval = to.Ptr[string]("timespan-value")
96
return settings
97
},
98
},
99
}
100
for _, tt := range tests {
101
t.Run(tt.name, func(t *testing.T) {
102
fullConfig := tt.configModifier(baseConfig)
103
expectedSettings := tt.toExpectedSettings(baseSettings)
104
settings, err := fullConfig.ToScrapeSettings()
105
require.NoError(t, err)
106
require.Equal(t, &expectedSettings, settings)
107
})
108
}
109
}
110
111
func TestConfig_Validate(t *testing.T) {
112
baseConfig := azure_exporter.Config{
113
Subscriptions: []string{"subscriptionA"},
114
ResourceType: "resourceType",
115
Metrics: []string{"MetricA"},
116
AzureCloudEnvironment: "azurecloud",
117
}
118
119
baseConfigValid := t.Run("Base Config is Valid", func(t *testing.T) {
120
err := baseConfig.Validate()
121
require.NoError(t, err, "Base config was not valid but needs to be for these tests")
122
})
123
if !baseConfigValid {
124
return
125
}
126
127
tests := []struct {
128
name string
129
toInvalidConfig func(azure_exporter.Config) azure_exporter.Config
130
}{
131
{
132
name: "nil Subscriptions",
133
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
134
config.Subscriptions = nil
135
return config
136
},
137
},
138
{
139
name: "empty Subscriptions",
140
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
141
config.Subscriptions = []string{}
142
return config
143
},
144
},
145
{
146
name: "empty ResourceType",
147
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
148
config.ResourceType = ""
149
return config
150
},
151
},
152
{
153
name: "nil metrics",
154
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
155
config.Metrics = nil
156
return config
157
},
158
},
159
{
160
name: "empty metrics",
161
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
162
config.Metrics = []string{}
163
return config
164
},
165
},
166
{
167
name: "invalid aggregation",
168
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
169
config.MetricAggregations = []string{"I'm Invalid"}
170
return config
171
},
172
},
173
{
174
name: "invalid azure_cloud_environment",
175
toInvalidConfig: func(config azure_exporter.Config) azure_exporter.Config {
176
config.AzureCloudEnvironment = "Not Real"
177
return config
178
},
179
},
180
}
181
for _, tt := range tests {
182
t.Run(tt.name, func(t *testing.T) {
183
invalidConfig := tt.toInvalidConfig(baseConfig)
184
err := invalidConfig.Validate()
185
require.Error(t, err)
186
})
187
}
188
}
189
190
func TestMergeConfigWithQueryParams_MapsAllExpectedFieldsByYamlNameFromConfig(t *testing.T) {
191
// We want to be sure all expected fields are mappable by the yaml name and reflect allows us to do that programmatically
192
thing := reflect.TypeOf(azure_exporter.Config{})
193
var mappableFields []reflect.StructField
194
for i := 0; i < thing.NumField(); i++ {
195
field := thing.Field(i)
196
//Not available to be mapped via query param
197
if field.Name == "AzureCloudEnvironment" {
198
continue
199
}
200
201
mappableFields = append(mappableFields, field)
202
}
203
204
for _, mappableField := range mappableFields {
205
yamlFieldName := mappableField.Tag.Get("yaml")
206
t.Run(fmt.Sprintf("Can map %s from query param", yamlFieldName), func(t *testing.T) {
207
urlParams := map[string][]string{}
208
var fieldValue any
209
210
switch mappableField.Type.String() {
211
case "string":
212
value := "fake string 1"
213
urlParams[yamlFieldName] = []string{value}
214
fieldValue = value
215
case "[]string":
216
value := []string{"fake string 1", "fake string 2"}
217
fieldValue = value
218
urlParams[yamlFieldName] = value
219
default:
220
t.Fatalf("Attempting to map %s, discovered unexpected type %s", mappableField.Name, mappableField.Type.String())
221
}
222
223
expectedConfig := &azure_exporter.Config{}
224
reflect.ValueOf(expectedConfig).Elem().FieldByName(mappableField.Name).Set(reflect.ValueOf(fieldValue))
225
226
actualConfig := azure_exporter.MergeConfigWithQueryParams(azure_exporter.Config{}, urlParams)
227
require.Equal(t, *expectedConfig, actualConfig)
228
})
229
}
230
}
231
232