config_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package prometheusreceiver
  4. import (
  5. "context"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. "time"
  10. promConfig "github.com/prometheus/common/config"
  11. promModel "github.com/prometheus/common/model"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "go.opentelemetry.io/collector/component"
  15. "go.opentelemetry.io/collector/confmap/confmaptest"
  16. "go.opentelemetry.io/collector/receiver/receivertest"
  17. "go.uber.org/zap"
  18. "go.uber.org/zap/zaptest/observer"
  19. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal/metadata"
  20. )
  21. func TestLoadConfig(t *testing.T) {
  22. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
  23. require.NoError(t, err)
  24. factory := NewFactory()
  25. cfg := factory.CreateDefaultConfig()
  26. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  27. require.NoError(t, err)
  28. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  29. r0 := cfg.(*Config)
  30. assert.Equal(t, r0, factory.CreateDefaultConfig())
  31. sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "customname").String())
  32. require.NoError(t, err)
  33. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  34. r1 := cfg.(*Config)
  35. assert.Equal(t, r1.PrometheusConfig.ScrapeConfigs[0].JobName, "demo")
  36. assert.Equal(t, time.Duration(r1.PrometheusConfig.ScrapeConfigs[0].ScrapeInterval), 5*time.Second)
  37. assert.Equal(t, r1.UseStartTimeMetric, true)
  38. assert.Equal(t, r1.TrimMetricSuffixes, true)
  39. assert.Equal(t, r1.EnableProtobufNegotiation, true)
  40. assert.Equal(t, r1.StartTimeMetricRegex, "^(.+_)*process_start_time_seconds$")
  41. assert.True(t, r1.ReportExtraScrapeMetrics)
  42. assert.Equal(t, "http://my-targetallocator-service", r1.TargetAllocator.Endpoint)
  43. assert.Equal(t, 30*time.Second, r1.TargetAllocator.Interval)
  44. assert.Equal(t, "collector-1", r1.TargetAllocator.CollectorID)
  45. assert.Equal(t, promModel.Duration(60*time.Second), r1.TargetAllocator.HTTPSDConfig.RefreshInterval)
  46. assert.Equal(t, "prometheus", r1.TargetAllocator.HTTPSDConfig.HTTPClientConfig.BasicAuth.Username)
  47. assert.Equal(t, promConfig.Secret("changeme"), r1.TargetAllocator.HTTPSDConfig.HTTPClientConfig.BasicAuth.Password)
  48. }
  49. func TestLoadTargetAllocatorConfig(t *testing.T) {
  50. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config_target_allocator.yaml"))
  51. require.NoError(t, err)
  52. factory := NewFactory()
  53. cfg := factory.CreateDefaultConfig()
  54. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  55. require.NoError(t, err)
  56. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  57. r0 := cfg.(*Config)
  58. assert.NotNil(t, r0.PrometheusConfig)
  59. assert.Equal(t, "http://localhost:8080", r0.TargetAllocator.Endpoint)
  60. assert.Equal(t, 30*time.Second, r0.TargetAllocator.Interval)
  61. assert.Equal(t, "collector-1", r0.TargetAllocator.CollectorID)
  62. sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "withScrape").String())
  63. require.NoError(t, err)
  64. cfg = factory.CreateDefaultConfig()
  65. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  66. r1 := cfg.(*Config)
  67. assert.NotNil(t, r0.PrometheusConfig)
  68. assert.Equal(t, "http://localhost:8080", r0.TargetAllocator.Endpoint)
  69. assert.Equal(t, 30*time.Second, r0.TargetAllocator.Interval)
  70. assert.Equal(t, "collector-1", r0.TargetAllocator.CollectorID)
  71. assert.Equal(t, 1, len(r1.PrometheusConfig.ScrapeConfigs))
  72. assert.Equal(t, "demo", r1.PrometheusConfig.ScrapeConfigs[0].JobName)
  73. assert.Equal(t, promModel.Duration(5*time.Second), r1.PrometheusConfig.ScrapeConfigs[0].ScrapeInterval)
  74. sub, err = cm.Sub(component.NewIDWithName(metadata.Type, "withOnlyScrape").String())
  75. require.NoError(t, err)
  76. cfg = factory.CreateDefaultConfig()
  77. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  78. r2 := cfg.(*Config)
  79. assert.Equal(t, 1, len(r2.PrometheusConfig.ScrapeConfigs))
  80. assert.Equal(t, "demo", r2.PrometheusConfig.ScrapeConfigs[0].JobName)
  81. assert.Equal(t, promModel.Duration(5*time.Second), r2.PrometheusConfig.ScrapeConfigs[0].ScrapeInterval)
  82. }
  83. func TestLoadConfigFailsOnUnknownSection(t *testing.T) {
  84. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-section.yaml"))
  85. require.NoError(t, err)
  86. factory := NewFactory()
  87. cfg := factory.CreateDefaultConfig()
  88. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  89. require.NoError(t, err)
  90. require.Error(t, component.UnmarshalConfig(sub, cfg))
  91. }
  92. // As one of the config parameters is consuming prometheus
  93. // configuration as a subkey, ensure that invalid configuration
  94. // within the subkey will also raise an error.
  95. func TestLoadConfigFailsOnUnknownPrometheusSection(t *testing.T) {
  96. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-section.yaml"))
  97. require.NoError(t, err)
  98. factory := NewFactory()
  99. cfg := factory.CreateDefaultConfig()
  100. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  101. require.NoError(t, err)
  102. require.Error(t, component.UnmarshalConfig(sub, cfg))
  103. }
  104. // Renaming emits a warning
  105. func TestConfigWarningsOnRenameDisallowed(t *testing.T) {
  106. // Construct the config that should emit a warning
  107. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "warning-config-prometheus-relabel.yaml"))
  108. require.NoError(t, err)
  109. factory := NewFactory()
  110. cfg := factory.CreateDefaultConfig()
  111. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  112. require.NoError(t, err)
  113. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  114. // Use a fake logger
  115. creationSet := receivertest.NewNopCreateSettings()
  116. observedZapCore, observedLogs := observer.New(zap.WarnLevel)
  117. creationSet.Logger = zap.New(observedZapCore)
  118. _, err = createMetricsReceiver(context.Background(), creationSet, cfg, nil)
  119. require.NoError(t, err)
  120. // We should have received a warning
  121. assert.Equal(t, 1, observedLogs.Len())
  122. }
  123. func TestRejectUnsupportedPrometheusFeatures(t *testing.T) {
  124. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-unsupported-features.yaml"))
  125. require.NoError(t, err)
  126. factory := NewFactory()
  127. cfg := factory.CreateDefaultConfig()
  128. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  129. require.NoError(t, err)
  130. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  131. err = component.ValidateConfig(cfg)
  132. require.NotNil(t, err, "Expected a non-nil error")
  133. wantErrMsg := `unsupported features:
  134. alert_config.alertmanagers
  135. alert_config.relabel_configs
  136. remote_read
  137. remote_write
  138. rule_files`
  139. gotErrMsg := strings.ReplaceAll(err.Error(), "\t", strings.Repeat(" ", 8))
  140. require.Equal(t, wantErrMsg, gotErrMsg)
  141. }
  142. func TestNonExistentAuthCredentialsFile(t *testing.T) {
  143. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-non-existent-auth-credentials-file.yaml"))
  144. require.NoError(t, err)
  145. factory := NewFactory()
  146. cfg := factory.CreateDefaultConfig()
  147. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  148. require.NoError(t, err)
  149. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  150. err = component.ValidateConfig(cfg)
  151. require.NotNil(t, err, "Expected a non-nil error")
  152. wantErrMsg := `error checking authorization credentials file "/nonexistentauthcredentialsfile"`
  153. gotErrMsg := err.Error()
  154. require.True(t, strings.HasPrefix(gotErrMsg, wantErrMsg))
  155. }
  156. func TestTLSConfigNonExistentCertFile(t *testing.T) {
  157. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-non-existent-cert-file.yaml"))
  158. require.NoError(t, err)
  159. factory := NewFactory()
  160. cfg := factory.CreateDefaultConfig()
  161. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  162. require.NoError(t, err)
  163. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  164. err = component.ValidateConfig(cfg)
  165. require.NotNil(t, err, "Expected a non-nil error")
  166. wantErrMsg := `error checking client cert file "/nonexistentcertfile"`
  167. gotErrMsg := err.Error()
  168. require.True(t, strings.HasPrefix(gotErrMsg, wantErrMsg))
  169. }
  170. func TestTLSConfigNonExistentKeyFile(t *testing.T) {
  171. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-non-existent-key-file.yaml"))
  172. require.NoError(t, err)
  173. factory := NewFactory()
  174. cfg := factory.CreateDefaultConfig()
  175. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  176. require.NoError(t, err)
  177. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  178. err = component.ValidateConfig(cfg)
  179. require.NotNil(t, err, "Expected a non-nil error")
  180. wantErrMsg := `error checking client key file "/nonexistentkeyfile"`
  181. gotErrMsg := err.Error()
  182. require.True(t, strings.HasPrefix(gotErrMsg, wantErrMsg))
  183. }
  184. func TestTLSConfigCertFileWithoutKeyFile(t *testing.T) {
  185. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-cert-file-without-key-file.yaml"))
  186. require.NoError(t, err)
  187. factory := NewFactory()
  188. cfg := factory.CreateDefaultConfig()
  189. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  190. require.NoError(t, err)
  191. err = component.UnmarshalConfig(sub, cfg)
  192. if assert.Error(t, err) {
  193. assert.Contains(t, err.Error(), "exactly one of key or key_file must be configured when a client certificate is configured")
  194. }
  195. }
  196. func TestTLSConfigKeyFileWithoutCertFile(t *testing.T) {
  197. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-key-file-without-cert-file.yaml"))
  198. require.NoError(t, err)
  199. factory := NewFactory()
  200. cfg := factory.CreateDefaultConfig()
  201. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  202. require.NoError(t, err)
  203. err = component.UnmarshalConfig(sub, cfg)
  204. if assert.Error(t, err) {
  205. assert.Contains(t, err.Error(), "exactly one of cert or cert_file must be configured when a client key is configured")
  206. }
  207. }
  208. func TestKubernetesSDConfigWithoutKeyFile(t *testing.T) {
  209. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-kubernetes-sd-config.yaml"))
  210. require.NoError(t, err)
  211. factory := NewFactory()
  212. cfg := factory.CreateDefaultConfig()
  213. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  214. require.NoError(t, err)
  215. err = component.UnmarshalConfig(sub, cfg)
  216. if assert.Error(t, err) {
  217. assert.Contains(t, err.Error(), "exactly one of key or key_file must be configured when a client certificate is configured")
  218. }
  219. }
  220. func TestFileSDConfigJsonNilTargetGroup(t *testing.T) {
  221. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-file-sd-config-json.yaml"))
  222. require.NoError(t, err)
  223. factory := NewFactory()
  224. cfg := factory.CreateDefaultConfig()
  225. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  226. require.NoError(t, err)
  227. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  228. err = component.ValidateConfig(cfg)
  229. require.NoError(t, err)
  230. }
  231. func TestFileSDConfigYamlNilTargetGroup(t *testing.T) {
  232. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "invalid-config-prometheus-file-sd-config-yaml.yaml"))
  233. require.NoError(t, err)
  234. factory := NewFactory()
  235. cfg := factory.CreateDefaultConfig()
  236. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  237. require.NoError(t, err)
  238. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  239. err = component.ValidateConfig(cfg)
  240. require.NoError(t, err)
  241. }
  242. func TestFileSDConfigWithoutSDFile(t *testing.T) {
  243. cm, err := confmaptest.LoadConf(filepath.Join("testdata", "non-existent-prometheus-sd-file-config.yaml"))
  244. require.NoError(t, err)
  245. factory := NewFactory()
  246. cfg := factory.CreateDefaultConfig()
  247. sub, err := cm.Sub(component.NewIDWithName(metadata.Type, "").String())
  248. require.NoError(t, err)
  249. require.NoError(t, component.UnmarshalConfig(sub, cfg))
  250. err = component.ValidateConfig(cfg)
  251. require.NoError(t, err)
  252. }