Skip to content

Commit 48ecaf1

Browse files
Fix prometheusreceiver TA/scrape_config validation logic (#30181)
This PR is a fork from #30135 where the author did not respond to the comments. I applied all suggestions because as a maintainer is my responsibility to ensure we fix bugs and merge PRs. Thanks @Aneurysm9 for the first commit. --------- Signed-off-by: Anthony J Mirabella <[email protected]> Signed-off-by: Bogdan Drutu <[email protected]> Co-authored-by: Anthony J Mirabella <[email protected]>
1 parent 1b0a44e commit 48ecaf1

File tree

4 files changed

+69
-10
lines changed

4 files changed

+69
-10
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
change_type: 'bug_fix'
2+
component: 'prometheusreceiver'
3+
note: Fix configuration validation to allow specification of Target Allocator configuration without providing scrape configurations
4+
issues: [30135]
5+
subtext:
6+
change_logs: []

receiver/prometheusreceiver/config.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@ func checkTLSConfig(tlsConfig commonconfig.TLSConfig) error {
9595
// Validate checks the receiver configuration is valid.
9696
func (cfg *Config) Validate() error {
9797
promConfig := cfg.PrometheusConfig
98-
if promConfig != nil {
99-
err := cfg.validatePromConfig(promConfig)
100-
if err != nil {
101-
return err
102-
}
98+
if (promConfig == nil || len(promConfig.ScrapeConfigs) == 0) && cfg.TargetAllocator == nil {
99+
return errors.New("no Prometheus scrape_configs or target_allocator set")
100+
}
101+
102+
err := validatePromConfig(promConfig)
103+
if err != nil {
104+
return err
103105
}
104106

105107
if cfg.TargetAllocator != nil {
@@ -111,11 +113,10 @@ func (cfg *Config) Validate() error {
111113
return nil
112114
}
113115

114-
func (cfg *Config) validatePromConfig(promConfig *promconfig.Config) error {
115-
if len(promConfig.ScrapeConfigs) == 0 && cfg.TargetAllocator == nil {
116-
return errors.New("no Prometheus scrape_configs or target_allocator set")
116+
func validatePromConfig(promConfig *promconfig.Config) error {
117+
if promConfig == nil {
118+
return nil
117119
}
118-
119120
// Reject features that Prometheus supports but that the receiver doesn't support:
120121
// See:
121122
// * https://github.com/open-telemetry/opentelemetry-collector/issues/3863
@@ -142,7 +143,7 @@ func (cfg *Config) validatePromConfig(promConfig *promconfig.Config) error {
142143
return fmt.Errorf("unsupported features:\n\t%s", strings.Join(unsupportedFeatures, "\n\t"))
143144
}
144145

145-
for _, sc := range cfg.PrometheusConfig.ScrapeConfigs {
146+
for _, sc := range promConfig.ScrapeConfigs {
146147
if sc.HTTPClientConfig.Authorization != nil {
147148
if err := checkFile(sc.HTTPClientConfig.Authorization.CredentialsFile); err != nil {
148149
return fmt.Errorf("error checking authorization credentials file %q: %w", sc.HTTPClientConfig.Authorization.CredentialsFile, err)

receiver/prometheusreceiver/config_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func TestLoadTargetAllocatorConfig(t *testing.T) {
6666
sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
6767
require.NoError(t, err)
6868
require.NoError(t, component.UnmarshalConfig(sub, cfg))
69+
require.NoError(t, component.ValidateConfig(cfg))
6970

7071
r0 := cfg.(*Config)
7172
assert.NotNil(t, r0.PrometheusConfig)
@@ -77,6 +78,7 @@ func TestLoadTargetAllocatorConfig(t *testing.T) {
7778
require.NoError(t, err)
7879
cfg = factory.CreateDefaultConfig()
7980
require.NoError(t, component.UnmarshalConfig(sub, cfg))
81+
require.NoError(t, component.ValidateConfig(cfg))
8082

8183
r1 := cfg.(*Config)
8284
assert.NotNil(t, r0.PrometheusConfig)
@@ -92,6 +94,7 @@ func TestLoadTargetAllocatorConfig(t *testing.T) {
9294
require.NoError(t, err)
9395
cfg = factory.CreateDefaultConfig()
9496
require.NoError(t, component.UnmarshalConfig(sub, cfg))
97+
require.NoError(t, component.ValidateConfig(cfg))
9598

9699
r2 := cfg.(*Config)
97100
assert.Equal(t, 1, len(r2.PrometheusConfig.ScrapeConfigs))
@@ -110,6 +113,36 @@ func TestLoadConfigFailsOnUnknownSection(t *testing.T) {
110113
require.Error(t, component.UnmarshalConfig(sub, cfg))
111114
}
112115

116+
func TestLoadConfigFailsOnNoPrometheusOrTAConfig(t *testing.T) {
117+
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-non-existent-scrape-config.yaml"))
118+
require.NoError(t, err)
119+
factory := NewFactory()
120+
121+
cfg := factory.CreateDefaultConfig()
122+
sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
123+
require.NoError(t, err)
124+
require.NoError(t, component.UnmarshalConfig(sub, cfg))
125+
require.ErrorContains(t, component.ValidateConfig(cfg), "no Prometheus scrape_configs or target_allocator set")
126+
127+
cfg = factory.CreateDefaultConfig()
128+
sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "withConfigAndTA").String())
129+
require.NoError(t, err)
130+
require.NoError(t, component.UnmarshalConfig(sub, cfg))
131+
require.NoError(t, component.ValidateConfig(cfg))
132+
133+
cfg = factory.CreateDefaultConfig()
134+
sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "withOnlyTA").String())
135+
require.NoError(t, err)
136+
require.NoError(t, component.UnmarshalConfig(sub, cfg))
137+
require.NoError(t, component.ValidateConfig(cfg))
138+
139+
cfg = factory.CreateDefaultConfig()
140+
sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "withOnlyScrape").String())
141+
require.NoError(t, err)
142+
require.NoError(t, component.UnmarshalConfig(sub, cfg))
143+
require.NoError(t, component.ValidateConfig(cfg))
144+
}
145+
113146
// As one of the config parameters is consuming prometheus
114147
// configuration as a subkey, ensure that invalid configuration
115148
// within the subkey will also raise an error.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
prometheus:
2+
prometheus/withConfigAndTA:
3+
target_allocator:
4+
endpoint: http://localhost:8080
5+
interval: 30s
6+
collector_id: collector-1
7+
config:
8+
global:
9+
scrape_interval: 30s
10+
prometheus/withOnlyTA:
11+
target_allocator:
12+
endpoint: http://localhost:8080
13+
interval: 30s
14+
collector_id: collector-1
15+
prometheus/withOnlyScrape:
16+
config:
17+
scrape_configs:
18+
- job_name: 'demo'
19+
scrape_interval: 5s

0 commit comments

Comments
 (0)