Skip to content

Commit ef1306b

Browse files
authored
Move TA config parsing to configmap manifest builder (#3243)
This is in preparation for the Target Allocator CRD. For that CRD, the Collector instance may be specified via a label or ownership relation. Therefore, we need to pull the necessary data from the Collector instance during TA config generation. It's more convenient to do this in all cases, which is what this change does.
1 parent d4780a6 commit ef1306b

File tree

4 files changed

+467
-239
lines changed

4 files changed

+467
-239
lines changed

internal/manifests/collector/targetallocator.go

-57
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@
1515
package collector
1616

1717
import (
18-
"github.com/mitchellh/mapstructure"
1918
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2019

2120
"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
2221
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
2322
"github.com/open-telemetry/opentelemetry-operator/internal/manifests"
24-
"github.com/open-telemetry/opentelemetry-operator/internal/manifests/targetallocator/adapters"
2523
)
2624

2725
// TargetAllocator builds the TargetAllocator CR for the given instance.
@@ -32,19 +30,6 @@ func TargetAllocator(params manifests.Params) (*v1alpha1.TargetAllocator, error)
3230
return nil, nil
3331
}
3432

35-
configStr, err := params.OtelCol.Spec.Config.Yaml()
36-
if err != nil {
37-
return nil, err
38-
}
39-
scrapeConfigs, err := getScrapeConfigs(configStr)
40-
if err != nil {
41-
return nil, err
42-
}
43-
globalConfig, err := getGlobalConfig(params.OtelCol.Spec.Config)
44-
if err != nil {
45-
return nil, err
46-
}
47-
4833
return &v1alpha1.TargetAllocator{
4934
ObjectMeta: metav1.ObjectMeta{
5035
Name: params.OtelCol.Name,
@@ -70,50 +55,8 @@ func TargetAllocator(params manifests.Params) (*v1alpha1.TargetAllocator, error)
7055
},
7156
AllocationStrategy: taSpec.AllocationStrategy,
7257
FilterStrategy: taSpec.FilterStrategy,
73-
ScrapeConfigs: scrapeConfigs,
74-
GlobalConfig: globalConfig,
7558
PrometheusCR: taSpec.PrometheusCR,
7659
Observability: taSpec.Observability,
7760
},
7861
}, nil
7962
}
80-
81-
func getGlobalConfig(otelConfig v1beta1.Config) (v1beta1.AnyConfig, error) {
82-
// TODO: Eventually we should figure out a way to pull this in to the main specification for the TA
83-
type promReceiverConfig struct {
84-
Prometheus struct {
85-
Config struct {
86-
Global map[string]interface{} `mapstructure:"global"`
87-
} `mapstructure:"config"`
88-
} `mapstructure:"prometheus"`
89-
}
90-
decodedConfig := &promReceiverConfig{}
91-
if err := mapstructure.Decode(otelConfig.Receivers.Object, decodedConfig); err != nil {
92-
return v1beta1.AnyConfig{}, err
93-
}
94-
return v1beta1.AnyConfig{
95-
Object: decodedConfig.Prometheus.Config.Global,
96-
}, nil
97-
}
98-
99-
func getScrapeConfigs(otelcolConfig string) ([]v1beta1.AnyConfig, error) {
100-
// Collector supports environment variable substitution, but the TA does not.
101-
// TA Scrape Configs should have a single "$", as it does not support env var substitution
102-
prometheusReceiverConfig, err := adapters.UnescapeDollarSignsInPromConfig(otelcolConfig)
103-
if err != nil {
104-
return nil, err
105-
}
106-
107-
scrapeConfigs, err := adapters.GetScrapeConfigsFromPromConfig(prometheusReceiverConfig)
108-
if err != nil {
109-
return nil, err
110-
}
111-
112-
v1beta1scrapeConfigs := make([]v1beta1.AnyConfig, len(scrapeConfigs))
113-
114-
for i, config := range scrapeConfigs {
115-
v1beta1scrapeConfigs[i] = v1beta1.AnyConfig{Object: config}
116-
}
117-
118-
return v1beta1scrapeConfigs, nil
119-
}

internal/manifests/collector/targetallocator_test.go

+1-176
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
package collector
1616

1717
import (
18-
"fmt"
1918
"testing"
2019
"time"
2120

2221
"github.com/stretchr/testify/assert"
23-
"github.com/stretchr/testify/require"
2422
v1 "k8s.io/api/core/v1"
2523
"k8s.io/apimachinery/pkg/api/resource"
2624
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -89,10 +87,7 @@ func TestTargetAllocator(t *testing.T) {
8987
},
9088
want: &v1alpha1.TargetAllocator{
9189
ObjectMeta: objectMetadata,
92-
Spec: v1alpha1.TargetAllocatorSpec{
93-
ScrapeConfigs: []v1beta1.AnyConfig{},
94-
GlobalConfig: v1beta1.AnyConfig{},
95-
},
90+
Spec: v1alpha1.TargetAllocatorSpec{},
9691
},
9792
},
9893
{
@@ -291,7 +286,6 @@ func TestTargetAllocator(t *testing.T) {
291286
MatchLabels: map[string]string{"servicemonitorkey": "servicemonitorkey"},
292287
},
293288
},
294-
ScrapeConfigs: []v1beta1.AnyConfig{},
295289
Observability: v1beta1.ObservabilitySpec{
296290
Metrics: v1beta1.MetricsConfigSpec{
297291
EnableMetrics: true,
@@ -314,172 +308,3 @@ func TestTargetAllocator(t *testing.T) {
314308
})
315309
}
316310
}
317-
318-
func TestGetScrapeConfigs(t *testing.T) {
319-
testCases := []struct {
320-
name string
321-
input v1beta1.Config
322-
want []v1beta1.AnyConfig
323-
wantErr error
324-
}{
325-
{
326-
name: "empty scrape configs list",
327-
input: v1beta1.Config{
328-
Receivers: v1beta1.AnyConfig{
329-
Object: map[string]interface{}{
330-
"prometheus": map[string]any{
331-
"config": map[string]any{
332-
"scrape_configs": []any{},
333-
},
334-
},
335-
},
336-
},
337-
},
338-
want: []v1beta1.AnyConfig{},
339-
},
340-
{
341-
name: "no scrape configs key",
342-
input: v1beta1.Config{
343-
Receivers: v1beta1.AnyConfig{
344-
Object: map[string]interface{}{
345-
"prometheus": map[string]any{
346-
"config": map[string]any{},
347-
},
348-
},
349-
},
350-
},
351-
wantErr: fmt.Errorf("no scrape_configs available as part of the configuration"),
352-
},
353-
{
354-
name: "one scrape config",
355-
input: v1beta1.Config{
356-
Receivers: v1beta1.AnyConfig{
357-
Object: map[string]interface{}{
358-
"prometheus": map[string]any{
359-
"config": map[string]any{
360-
"scrape_configs": []any{
361-
map[string]any{
362-
"job": "somejob",
363-
},
364-
},
365-
},
366-
},
367-
},
368-
},
369-
},
370-
want: []v1beta1.AnyConfig{
371-
{Object: map[string]interface{}{"job": "somejob"}},
372-
},
373-
},
374-
{
375-
name: "regex substitution",
376-
input: v1beta1.Config{
377-
Receivers: v1beta1.AnyConfig{
378-
Object: map[string]interface{}{
379-
"prometheus": map[string]any{
380-
"config": map[string]any{
381-
"scrape_configs": []any{
382-
map[string]any{
383-
"job": "somejob",
384-
"metric_relabel_configs": []map[string]any{
385-
{
386-
"action": "labelmap",
387-
"regex": "label_(.+)",
388-
"replacement": "$$1",
389-
},
390-
},
391-
},
392-
},
393-
},
394-
},
395-
},
396-
},
397-
},
398-
want: []v1beta1.AnyConfig{
399-
{Object: map[string]interface{}{
400-
"job": "somejob",
401-
"metric_relabel_configs": []any{
402-
map[any]any{
403-
"action": "labelmap",
404-
"regex": "label_(.+)",
405-
"replacement": "$1",
406-
},
407-
},
408-
}},
409-
},
410-
},
411-
}
412-
413-
for _, testCase := range testCases {
414-
testCase := testCase
415-
t.Run(testCase.name, func(t *testing.T) {
416-
configStr, err := testCase.input.Yaml()
417-
require.NoError(t, err)
418-
actual, err := getScrapeConfigs(configStr)
419-
assert.Equal(t, testCase.wantErr, err)
420-
assert.Equal(t, testCase.want, actual)
421-
})
422-
}
423-
}
424-
425-
func Test_getGlobalConfig(t *testing.T) {
426-
type args struct {
427-
otelConfig v1beta1.Config
428-
}
429-
tests := []struct {
430-
name string
431-
args args
432-
want v1beta1.AnyConfig
433-
wantErr error
434-
}{
435-
{
436-
name: "Valid Global Config",
437-
args: args{
438-
otelConfig: v1beta1.Config{
439-
Receivers: v1beta1.AnyConfig{
440-
Object: map[string]interface{}{
441-
"prometheus": map[string]interface{}{
442-
"config": map[string]interface{}{
443-
"global": map[string]interface{}{
444-
"scrape_interval": "15s",
445-
"scrape_protocols": []string{"PrometheusProto", "OpenMetricsText1.0.0", "OpenMetricsText0.0.1", "PrometheusText0.0.4"},
446-
},
447-
},
448-
},
449-
},
450-
},
451-
},
452-
},
453-
want: v1beta1.AnyConfig{
454-
Object: map[string]interface{}{
455-
"scrape_interval": "15s",
456-
"scrape_protocols": []string{"PrometheusProto", "OpenMetricsText1.0.0", "OpenMetricsText0.0.1", "PrometheusText0.0.4"},
457-
},
458-
},
459-
wantErr: nil,
460-
},
461-
{
462-
name: "Invalid Global Config - Missing Global",
463-
args: args{
464-
otelConfig: v1beta1.Config{
465-
Receivers: v1beta1.AnyConfig{
466-
Object: map[string]interface{}{
467-
"prometheus": map[string]interface{}{
468-
"config": map[string]interface{}{},
469-
},
470-
},
471-
},
472-
},
473-
},
474-
want: v1beta1.AnyConfig{},
475-
wantErr: nil,
476-
},
477-
}
478-
for _, tt := range tests {
479-
t.Run(tt.name, func(t *testing.T) {
480-
got, err := getGlobalConfig(tt.args.otelConfig)
481-
assert.Equal(t, tt.wantErr, err)
482-
assert.Equal(t, tt.want, got)
483-
})
484-
}
485-
}

0 commit comments

Comments
 (0)