diff --git a/README.md b/README.md index cd6714da400..0ea9f70f2b9 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,4 @@ common issues and frequently asked questions (FAQ). ## Acknowledgements -prometheus-operator organization logo was created and contributed by [Bianca Cheng Costanzo](https://github.com/bia). - -Rebuild Image: Wed Sep 7 14:48:45 EDT 2022 +prometheus-operator organization logo was created and contributed by [Bianca Cheng Costanzo](https://github.com/bia). \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index fe527267240..fc3a4a093b4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,5 @@ -# Security Response +# Security -If you've found a security issue that you'd like to disclose confidentially please contact Red Hat's Product Security team. -Details at https://access.redhat.com/security/team/contact - -Build Date: Tue Jan 16 06:21:45 EST 2024 +If you find a security vulnerability related to the Prometheus Operator, please +do not report it by opening a GitHub issue, but instead please send an e-mail to +the maintainers of the project found in the [MAINTAINERS.md](MAINTAINERS.md) file. \ No newline at end of file diff --git a/cmd/po-lint/main.go b/cmd/po-lint/main.go deleted file mode 100644 index 91497ea9cf5..00000000000 --- a/cmd/po-lint/main.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2019 The prometheus-operator Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "log" - "os" - - "github.com/prometheus/prometheus/model/rulefmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/yaml" - - "github.com/prometheus-operator/prometheus-operator/pkg/admission" - v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - v1alpha1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1alpha1" - "github.com/prometheus-operator/prometheus-operator/pkg/versionutil" -) - -func main() { - versionutil.RegisterParseFlags() - if versionutil.ShouldPrintVersion() { - versionutil.Print(os.Stdout, "po-lint") - os.Exit(0) - } - log.SetFlags(0) - - files := os.Args[1:] - - for _, filename := range files { - log.SetPrefix(fmt.Sprintf("%s: ", filename)) - content, err := os.ReadFile(filename) - if err != nil { - log.Fatal(err) - } - - var meta metav1.TypeMeta - - err = yaml.Unmarshal(content, &meta) - if err != nil { - log.Fatal(err) - } - - switch meta.Kind { - case v1.AlertmanagersKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var alertmanager v1.Alertmanager - err = decoder.Decode(&alertmanager) - if err != nil { - log.Fatalf("alertmanager is invalid: %v", err) - } - case v1.PrometheusesKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var prometheus v1.Prometheus - err = decoder.Decode(&prometheus) - if err != nil { - log.Fatalf("prometheus is invalid: %v", err) - } - case v1.PrometheusRuleKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var rule v1.PrometheusRule - err = decoder.Decode(&rule) - if err != nil { - log.Fatalf("prometheus rule is invalid: %v", err) - } - err = validateRules(content) - if err != nil { - log.Fatalf("prometheus rule validation failed: %v", err) - } - case v1.ServiceMonitorsKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var serviceMonitor v1.ServiceMonitor - err = decoder.Decode(&serviceMonitor) - if err != nil { - log.Fatalf("serviceMonitor is invalid: %v", err) - } - case v1.PodMonitorsKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var podMonitor v1.PodMonitor - err = decoder.Decode(&podMonitor) - if err != nil { - log.Fatalf("podMonitor is invalid: %v", err) - } - case v1.ProbesKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var probe v1.Probe - if err := decoder.Decode(&probe); err != nil { - log.Fatalf("probe is invalid: %v", err) - } - case v1.ThanosRulerKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var thanosRuler v1.ThanosRuler - err = decoder.Decode(&thanosRuler) - if err != nil { - log.Fatalf("thanosRuler is invalid: %v", err) - } - case v1alpha1.AlertmanagerConfigKind: - j, err := yaml.YAMLToJSON(content) - if err != nil { - log.Fatalf("unable to convert YAML to JSON: %v", err) - } - - decoder := json.NewDecoder(bytes.NewBuffer(j)) - decoder.DisallowUnknownFields() - - var alertmanagerConfig v1alpha1.AlertmanagerConfig - err = decoder.Decode(&alertmanagerConfig) - if err != nil { - log.Fatalf("alertmanagerConfig is invalid: %v", err) - } - default: - log.Print("MetaType is unknown to linter. Not in Alertmanager, Prometheus, PrometheusRule, ServiceMonitor, PodMonitor, Probe, ThanosRuler, AlertmanagerConfig") - } - } -} - -func validateRules(content []byte) error { - rule := &admission.PrometheusRules{} - err := yaml.Unmarshal(content, rule) - if err != nil { - return fmt.Errorf("unable load prometheus rule: %w", err) - } - rules, errorsArray := rulefmt.Parse(rule.Spec.Raw) - if len(errorsArray) != 0 { - for _, err := range errorsArray { - log.Println(err) - } - return errors.New("rules are not valid") - } - if len(rules.Groups) == 0 { - return errors.New("no group found") - } - for _, group := range rules.Groups { - if len(group.Rules) == 0 { - return fmt.Errorf("no rules found in group: %s: %w", group.Name, err) - } - } - return nil -} diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml index 7e3711891a8..00c1008b3e0 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml @@ -1943,12 +1943,6 @@ spec: type: string type: description: Type of responder. - enum: - - team - - teams - - user - - escalation - - schedule minLength: 1 type: string username: diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml index e08d69d42d5..1aa1dd4061f 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml @@ -3325,7 +3325,6 @@ spec: - hostnames - ip type: object - x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - ip diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml index 0df1b1834f3..a3dc1c266e0 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml @@ -3859,7 +3859,6 @@ spec: - hostnames - ip type: object - x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - ip @@ -12338,52 +12337,6 @@ spec: description: Shards is the most recently observed number of shards. format: int32 type: integer - selector: - description: The selector used to match the pods targeted by this - Prometheus resource. - type: string - shardStatuses: - description: The list has one entry per shard. Each entry provides - a summary of the shard status. - items: - properties: - availableReplicas: - description: Total number of available pods (ready for at least - minReadySeconds) targeted by this shard. - format: int32 - type: integer - replicas: - description: Total number of pods targeted by this shard. - format: int32 - type: integer - shardID: - description: Identifier of the shard. - type: string - unavailableReplicas: - description: Total number of unavailable pods targeted by this - shard. - format: int32 - type: integer - updatedReplicas: - description: Total number of non-terminated pods targeted by - this shard that have the desired spec. - format: int32 - type: integer - required: - - availableReplicas - - replicas - - shardID - - unavailableReplicas - - updatedReplicas - type: object - type: array - x-kubernetes-list-map-keys: - - shardID - x-kubernetes-list-type: map - shards: - description: Shards is the most recently observed number of shards. - format: int32 - type: integer unavailableReplicas: description: Total number of unavailable pods targeted by this Prometheus deployment. diff --git a/jsonnet/prometheus-operator/alertmanagers-crd.json b/jsonnet/prometheus-operator/alertmanagers-crd.json index c4724c5d379..988789cf59b 100644 --- a/jsonnet/prometheus-operator/alertmanagers-crd.json +++ b/jsonnet/prometheus-operator/alertmanagers-crd.json @@ -4925,15 +4925,6 @@ "type": "object", "x-kubernetes-map-type": "granular" }, - "allocatedResourceStatuses": { - "additionalProperties": { - "description": "When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it.", - "type": "string" - }, - "description": "allocatedResourceStatuses stores status of resource being resized for the given PVC. Key names follow standard Kubernetes label syntax. Valid values are either: * Un-prefixed keys: - storage - the capacity of the volume. * Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\" Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered reserved and hence may not be used. \n ClaimResourceStatus can be in any of following states: - ControllerResizeInProgress: State set when resize controller starts resizing the volume in control-plane. - ControllerResizeFailed: State set when resize has failed in resize controller with a terminal error. - NodeResizePending: State set when resize controller has finished resizing the volume but further resizing of volume is needed on the node. - NodeResizeInProgress: State set when kubelet starts resizing the volume. - NodeResizeFailed: State set when resizing has failed in kubelet with a terminal error. Transient errors don't set NodeResizeFailed. For example: if expanding a PVC for more capacity - this field can be one of the following states: - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\" When this field is not set, it means that no resize operation is in progress for the given PVC. \n A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus should ignore the update for the purpose it was designed. For example - a controller that only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid resources associated with PVC. \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.", - "type": "object", - "x-kubernetes-map-type": "granular" - }, "allocatedResources": { "additionalProperties": { "anyOf": [ @@ -6952,4 +6943,4 @@ } ] } -} +} \ No newline at end of file diff --git a/jsonnet/prometheus-operator/prometheuses-crd.json b/jsonnet/prometheus-operator/prometheuses-crd.json index 8817b0611b0..831635d4c93 100644 --- a/jsonnet/prometheus-operator/prometheuses-crd.json +++ b/jsonnet/prometheus-operator/prometheuses-crd.json @@ -3016,10 +3016,6 @@ "description": "Enable Prometheus to be used as a receiver for the Prometheus remote\nwrite protocol.\n\n\nWARNING: This is not considered an efficient way of ingesting samples.\nUse it with caution for specific low-volume use cases.\nIt is not suitable for replacing the ingestion via scraping and turning\nPrometheus into a push-based metrics collection system.\nFor more information see https://prometheus.io/docs/prometheus/latest/querying/api/#remote-write-receiver\n\n\nIt requires Prometheus >= v2.33.0.", "type": "boolean" }, - "enableRemoteWriteReceiver": { - "description": "Enable Prometheus to be used as a receiver for the Prometheus remote write protocol. \n WARNING: This is not considered an efficient way of ingesting samples. Use it with caution for specific low-volume use cases. It is not suitable for replacing the ingestion via scraping and turning Prometheus into a push-based metrics collection system. For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#remote-write-receiver \n It requires Prometheus >= v2.33.0.", - "type": "boolean" - }, "enforcedBodySizeLimit": { "description": "When defined, enforcedBodySizeLimit specifies a global limit on the size\nof uncompressed response body that will be accepted by Prometheus.\nTargets responding with a body larger than this many bytes will cause\nthe scrape to fail.\n\n\nIt requires Prometheus >= v2.28.0.\n\n\nWhen both `enforcedBodySizeLimit` and `bodySizeLimit` are defined and greater than zero, the following rules apply:\n* Scrape objects without a defined bodySizeLimit value will inherit the global bodySizeLimit value (Prometheus >= 2.45.0) or the enforcedBodySizeLimit value (Prometheus < v2.45.0).\n If Prometheus version is >= 2.45.0 and the `enforcedBodySizeLimit` is greater than the `bodySizeLimit`, the `bodySizeLimit` will be set to `enforcedBodySizeLimit`.\n* Scrape objects with a bodySizeLimit value less than or equal to enforcedBodySizeLimit keep their specific value.\n* Scrape objects with a bodySizeLimit value greater than enforcedBodySizeLimit are set to enforcedBodySizeLimit.", "pattern": "(^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$", @@ -7317,15 +7313,6 @@ "type": "object", "x-kubernetes-map-type": "granular" }, - "allocatedResourceStatuses": { - "additionalProperties": { - "description": "When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it.", - "type": "string" - }, - "description": "allocatedResourceStatuses stores status of resource being resized for the given PVC. Key names follow standard Kubernetes label syntax. Valid values are either: * Un-prefixed keys: - storage - the capacity of the volume. * Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\" Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered reserved and hence may not be used. \n ClaimResourceStatus can be in any of following states: - ControllerResizeInProgress: State set when resize controller starts resizing the volume in control-plane. - ControllerResizeFailed: State set when resize has failed in resize controller with a terminal error. - NodeResizePending: State set when resize controller has finished resizing the volume but further resizing of volume is needed on the node. - NodeResizeInProgress: State set when kubelet starts resizing the volume. - NodeResizeFailed: State set when resizing has failed in kubelet with a terminal error. Transient errors don't set NodeResizeFailed. For example: if expanding a PVC for more capacity - this field can be one of the following states: - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\" When this field is not set, it means that no resize operation is in progress for the given PVC. \n A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus should ignore the update for the purpose it was designed. For example - a controller that only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid resources associated with PVC. \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.", - "type": "object", - "x-kubernetes-map-type": "granular" - }, "allocatedResources": { "additionalProperties": { "anyOf": [ @@ -10013,59 +10000,6 @@ "format": "int32", "type": "integer" }, - "selector": { - "description": "The selector used to match the pods targeted by this Prometheus resource.", - "type": "string" - }, - "shardStatuses": { - "description": "The list has one entry per shard. Each entry provides a summary of the shard status.", - "items": { - "properties": { - "availableReplicas": { - "description": "Total number of available pods (ready for at least minReadySeconds) targeted by this shard.", - "format": "int32", - "type": "integer" - }, - "replicas": { - "description": "Total number of pods targeted by this shard.", - "format": "int32", - "type": "integer" - }, - "shardID": { - "description": "Identifier of the shard.", - "type": "string" - }, - "unavailableReplicas": { - "description": "Total number of unavailable pods targeted by this shard.", - "format": "int32", - "type": "integer" - }, - "updatedReplicas": { - "description": "Total number of non-terminated pods targeted by this shard that have the desired spec.", - "format": "int32", - "type": "integer" - } - }, - "required": [ - "availableReplicas", - "replicas", - "shardID", - "unavailableReplicas", - "updatedReplicas" - ], - "type": "object" - }, - "type": "array", - "x-kubernetes-list-map-keys": [ - "shardID" - ], - "x-kubernetes-list-type": "map" - }, - "shards": { - "description": "Shards is the most recently observed number of shards.", - "format": "int32", - "type": "integer" - }, "unavailableReplicas": { "description": "Total number of unavailable pods targeted by this Prometheus deployment.", "format": "int32", @@ -10106,4 +10040,4 @@ } ] } -} +} \ No newline at end of file diff --git a/jsonnet/prometheus-operator/thanosrulers-crd.json b/jsonnet/prometheus-operator/thanosrulers-crd.json index 83a6119bc5c..fc8eccdd04c 100644 --- a/jsonnet/prometheus-operator/thanosrulers-crd.json +++ b/jsonnet/prometheus-operator/thanosrulers-crd.json @@ -4609,15 +4609,6 @@ "type": "object", "x-kubernetes-map-type": "granular" }, - "allocatedResourceStatuses": { - "additionalProperties": { - "description": "When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource that it does not recognizes, then it should ignore that update and let other controllers handle it.", - "type": "string" - }, - "description": "allocatedResourceStatuses stores status of resource being resized for the given PVC. Key names follow standard Kubernetes label syntax. Valid values are either: * Un-prefixed keys: - storage - the capacity of the volume. * Custom resources must use implementation-defined prefixed names such as \"example.com/my-custom-resource\" Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered reserved and hence may not be used. \n ClaimResourceStatus can be in any of following states: - ControllerResizeInProgress: State set when resize controller starts resizing the volume in control-plane. - ControllerResizeFailed: State set when resize has failed in resize controller with a terminal error. - NodeResizePending: State set when resize controller has finished resizing the volume but further resizing of volume is needed on the node. - NodeResizeInProgress: State set when kubelet starts resizing the volume. - NodeResizeFailed: State set when resizing has failed in kubelet with a terminal error. Transient errors don't set NodeResizeFailed. For example: if expanding a PVC for more capacity - this field can be one of the following states: - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] = \"NodeResizeFailed\" When this field is not set, it means that no resize operation is in progress for the given PVC. \n A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus should ignore the update for the purpose it was designed. For example - a controller that only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid resources associated with PVC. \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.", - "type": "object", - "x-kubernetes-map-type": "granular" - }, "allocatedResources": { "additionalProperties": { "anyOf": [ @@ -6649,4 +6640,4 @@ } ] } -} +} \ No newline at end of file diff --git a/pkg/alertmanager/statefulset_test.go b/pkg/alertmanager/statefulset_test.go index afa5481c538..f7bfd954b61 100644 --- a/pkg/alertmanager/statefulset_test.go +++ b/pkg/alertmanager/statefulset_test.go @@ -366,96 +366,6 @@ func TestListenTLS(t *testing.T) { } } -func TestListenTLS(t *testing.T) { - sset, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Web: &monitoringv1.AlertmanagerWebSpec{ - WebConfigFileFields: monitoringv1.WebConfigFileFields{ - TLSConfig: &monitoringv1.WebTLSConfig{ - KeySecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "some-secret", - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "some-configmap", - }, - }, - }, - }, - }, - }, - }, - }, defaultTestConfig, "", &operator.ShardedSecret{}) - if err != nil { - t.Fatalf("Unexpected error while making StatefulSet: %v", err) - } - - expectedProbeHandler := func(probePath string) v1.ProbeHandler { - return v1.ProbeHandler{ - HTTPGet: &v1.HTTPGetAction{ - Path: probePath, - Port: intstr.FromString("web"), - Scheme: "HTTPS", - }, - } - } - - actualLivenessProbe := sset.Spec.Template.Spec.Containers[0].LivenessProbe - expectedLivenessProbe := &v1.Probe{ - ProbeHandler: expectedProbeHandler("/-/healthy"), - TimeoutSeconds: 3, - FailureThreshold: 10, - } - if !reflect.DeepEqual(actualLivenessProbe, expectedLivenessProbe) { - t.Fatalf("Liveness probe doesn't match expected. \n\nExpected: %+v\n\nGot: %+v", expectedLivenessProbe, actualLivenessProbe) - } - - actualReadinessProbe := sset.Spec.Template.Spec.Containers[0].ReadinessProbe - expectedReadinessProbe := &v1.Probe{ - ProbeHandler: expectedProbeHandler("/-/ready"), - InitialDelaySeconds: 3, - TimeoutSeconds: 3, - PeriodSeconds: 5, - FailureThreshold: 10, - } - if !reflect.DeepEqual(actualReadinessProbe, expectedReadinessProbe) { - t.Fatalf("Readiness probe doesn't match expected. \n\nExpected: %+v\n\nGot: %+v", expectedReadinessProbe, actualReadinessProbe) - } - - expectedConfigReloaderReloadURL := "--reload-url=https://localhost:9093/-/reload" - reloadURLFound := false - for _, arg := range sset.Spec.Template.Spec.Containers[1].Args { - fmt.Println(arg) - - if arg == expectedConfigReloaderReloadURL { - reloadURLFound = true - } - } - if !reloadURLFound { - t.Fatalf("expected to find arg %s in config reloader", expectedConfigReloaderReloadURL) - } - - expectedArgsConfigReloader := []string{ - "--listen-address=:8080", - "--web-config-file=/etc/alertmanager/web_config/web-config.yaml", - "--reload-url=https://localhost:9093/-/reload", - "--config-file=/etc/alertmanager/config/alertmanager.yaml.gz", - "--config-envsubst-file=/etc/alertmanager/config_out/alertmanager.env.yaml", - "--watched-dir=/etc/alertmanager/config", - } - - for _, c := range sset.Spec.Template.Spec.Containers { - if c.Name == "config-reloader" { - if !reflect.DeepEqual(c.Args, expectedArgsConfigReloader) { - t.Fatalf("expected container args are %s, but found %s", expectedArgsConfigReloader, c.Args) - } - } - } -} - // below Alertmanager v0.13.0 all flags are with single dash. func TestMakeStatefulSetSpecSingleDoubleDashedArgs(t *testing.T) { tests := []struct { @@ -601,109 +511,6 @@ func TestMakeStatefulSetSpecWebConcurrency(t *testing.T) { } } -func TestMakeStatefulSetSpecWebTimeout(t *testing.T) { - - tt := []struct { - scenario string - version string - web *monitoringv1.AlertmanagerWebSpec - expectTimeoutArg bool - }{{ - scenario: "no timeout by default", - version: operator.DefaultAlertmanagerVersion, - web: nil, - expectTimeoutArg: false, - }, { - scenario: "no timeout for old version", - version: "0.16.9", - web: &monitoringv1.AlertmanagerWebSpec{ - Timeout: toPtr(uint32(50)), - }, - expectTimeoutArg: false, - }, { - scenario: "timeout arg set if specified", - version: operator.DefaultAlertmanagerVersion, - web: &monitoringv1.AlertmanagerWebSpec{ - Timeout: toPtr(uint32(50)), - }, - expectTimeoutArg: true, - }} - - for _, ts := range tt { - ts := ts - t.Run(ts.scenario, func(t *testing.T) { - a := monitoringv1.Alertmanager{} - a.Spec.Replicas = toPtr(int32(1)) - - a.Spec.Version = ts.version - a.Spec.Web = ts.web - - ss, err := makeStatefulSetSpec(nil, &a, defaultTestConfig, &operator.ShardedSecret{}) - if err != nil { - t.Fatal(err) - } - - args := ss.Template.Spec.Containers[0].Args - if got := slices.ContainsFunc(args, containsString("-web.timeout")); got != ts.expectTimeoutArg { - t.Fatalf("expected alertmanager args %v web.timeout to be %v but is %v", args, ts.expectTimeoutArg, got) - } - - }) - } -} - -func TestMakeStatefulSetSpecWebConcurrency(t *testing.T) { - - tt := []struct { - scenario string - version string - web *monitoringv1.AlertmanagerWebSpec - expectGetConcurrencyArg bool - }{{ - scenario: "no get-concurrency by default", - version: operator.DefaultAlertmanagerVersion, - web: nil, - expectGetConcurrencyArg: false, - }, { - scenario: "no get-concurrency for old version", - version: "0.16.9", - web: &monitoringv1.AlertmanagerWebSpec{ - GetConcurrency: toPtr(uint32(50)), - }, - expectGetConcurrencyArg: false, - }, { - scenario: "get-concurrency arg set if specified", - version: operator.DefaultAlertmanagerVersion, - - web: &monitoringv1.AlertmanagerWebSpec{ - GetConcurrency: toPtr(uint32(50)), - }, - expectGetConcurrencyArg: true, - }} - - for _, ts := range tt { - ts := ts - t.Run(ts.scenario, func(t *testing.T) { - a := monitoringv1.Alertmanager{} - a.Spec.Replicas = toPtr(int32(1)) - - a.Spec.Version = ts.version - a.Spec.Web = ts.web - - ss, err := makeStatefulSetSpec(nil, &a, defaultTestConfig, &operator.ShardedSecret{}) - if err != nil { - t.Fatal(err) - } - - args := ss.Template.Spec.Containers[0].Args - if got := slices.ContainsFunc(args, containsString("-web.get-concurrency")); got != ts.expectGetConcurrencyArg { - t.Fatalf("expected alertmanager args %v web.get-concurrency to be %v but is %v", args, ts.expectGetConcurrencyArg, got) - } - - }) - } -} - func TestMakeStatefulSetSpecPeersWithoutClusterDomain(t *testing.T) { replicas := int32(1) a := monitoringv1.Alertmanager{ @@ -849,53 +656,6 @@ func TestMakeStatefulSetSpecNotificationTemplates(t *testing.T) { } } -func TestMakeStatefulSetSpecNotificationTemplates(t *testing.T) { - replicas := int32(1) - a := monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Replicas: &replicas, - AlertmanagerConfiguration: &monitoringv1.AlertmanagerConfiguration{ - Templates: []monitoringv1.SecretOrConfigMap{ - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template1", - }, - Key: "template1.tmpl", - }, - }, - }, - }, - }, - } - statefulSet, err := makeStatefulSetSpec(nil, &a, defaultTestConfig, &operator.ShardedSecret{}) - if err != nil { - t.Fatal(err) - } - - var foundVM, foundV bool - for _, vm := range statefulSet.Template.Spec.Containers[0].VolumeMounts { - if vm.Name == "notification-templates" && vm.MountPath == alertmanagerTemplatesDir { - foundVM = true - break - } - } - for _, v := range statefulSet.Template.Spec.Volumes { - if v.Name == "notification-templates" && v.Projected != nil { - for _, s := range v.Projected.Sources { - if s.Secret != nil && s.Secret.Name == "template1" { - foundV = true - break - } - } - } - } - - if !(foundVM && foundV) { - t.Fatal("Notification templates were not found.") - } -} - func TestAdditionalSecretsMounted(t *testing.T) { secrets := []string{"secret1", "secret2"} sset, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{ @@ -1510,368 +1270,3 @@ func TestEnableFeatures(t *testing.T) { }) } } - -func TestPodTemplateConfig(t *testing.T) { - nodeSelector := map[string]string{ - "foo": "bar", - } - affinity := v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{}, - PodAffinity: &v1.PodAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{ - { - PodAffinityTerm: v1.PodAffinityTerm{ - Namespaces: []string{"foo"}, - }, - Weight: 100, - }, - }, - }, - PodAntiAffinity: &v1.PodAntiAffinity{}, - } - - tolerations := []v1.Toleration{ - { - Key: "key", - }, - } - userid := int64(1234) - securityContext := v1.PodSecurityContext{ - RunAsUser: &userid, - } - priorityClassName := "foo" - serviceAccountName := "alertmanager-sa" - hostAliases := []monitoringv1.HostAlias{ - { - Hostnames: []string{"foo.com"}, - IP: "1.1.1.1", - }, - } - imagePullSecrets := []v1.LocalObjectReference{ - { - Name: "registry-secret", - }, - } - imagePullPolicy := v1.PullAlways - - sset, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{ - ObjectMeta: metav1.ObjectMeta{}, - Spec: monitoringv1.AlertmanagerSpec{ - NodeSelector: nodeSelector, - Affinity: &affinity, - Tolerations: tolerations, - SecurityContext: &securityContext, - PriorityClassName: priorityClassName, - ServiceAccountName: serviceAccountName, - HostAliases: hostAliases, - ImagePullSecrets: imagePullSecrets, - ImagePullPolicy: imagePullPolicy, - }, - }, defaultTestConfig, "", &operator.ShardedSecret{}) - if err != nil { - t.Fatalf("Unexpected error while making StatefulSet: %v", err) - } - - if !reflect.DeepEqual(sset.Spec.Template.Spec.NodeSelector, nodeSelector) { - t.Fatalf("expected node selector to match, want %v, got %v", nodeSelector, sset.Spec.Template.Spec.NodeSelector) - } - if !reflect.DeepEqual(*sset.Spec.Template.Spec.Affinity, affinity) { - t.Fatalf("expected affinity to match, want %v, got %v", affinity, *sset.Spec.Template.Spec.Affinity) - } - if !reflect.DeepEqual(sset.Spec.Template.Spec.Tolerations, tolerations) { - t.Fatalf("expected tolerations to match, want %v, got %v", tolerations, sset.Spec.Template.Spec.Tolerations) - } - if !reflect.DeepEqual(*sset.Spec.Template.Spec.SecurityContext, securityContext) { - t.Fatalf("expected security context to match, want %v, got %v", securityContext, *sset.Spec.Template.Spec.SecurityContext) - } - if sset.Spec.Template.Spec.PriorityClassName != priorityClassName { - t.Fatalf("expected priority class name to match, want %s, got %s", priorityClassName, sset.Spec.Template.Spec.PriorityClassName) - } - if sset.Spec.Template.Spec.ServiceAccountName != serviceAccountName { - t.Fatalf("expected service account name to match, want %s, got %s", serviceAccountName, sset.Spec.Template.Spec.ServiceAccountName) - } - if len(sset.Spec.Template.Spec.HostAliases) != len(hostAliases) { - t.Fatalf("expected length of host aliases to match, want %d, got %d", len(hostAliases), len(sset.Spec.Template.Spec.HostAliases)) - } - if !reflect.DeepEqual(sset.Spec.Template.Spec.ImagePullSecrets, imagePullSecrets) { - t.Fatalf("expected image pull secrets to match, want %s, got %s", imagePullSecrets, sset.Spec.Template.Spec.ImagePullSecrets) - } - for _, initContainer := range sset.Spec.Template.Spec.InitContainers { - if !reflect.DeepEqual(initContainer.ImagePullPolicy, imagePullPolicy) { - t.Fatalf("expected imagePullPolicy to match, want %s, got %s", imagePullPolicy, sset.Spec.Template.Spec.Containers[0].ImagePullPolicy) - } - } - for _, container := range sset.Spec.Template.Spec.Containers { - if !reflect.DeepEqual(container.ImagePullPolicy, imagePullPolicy) { - t.Fatalf("expected imagePullPolicy to match, want %s, got %s", imagePullPolicy, sset.Spec.Template.Spec.Containers[0].ImagePullPolicy) - } - } -} - -func TestConfigReloader(t *testing.T) { - baseSet, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{}, defaultTestConfig, "", &operator.ShardedSecret{}) - require.NoError(t, err) - - expectedArgsConfigReloader := []string{ - "--listen-address=:8080", - "--reload-url=http://localhost:9093/-/reload", - "--config-file=/etc/alertmanager/config/alertmanager.yaml.gz", - "--config-envsubst-file=/etc/alertmanager/config_out/alertmanager.env.yaml", - "--watched-dir=/etc/alertmanager/config", - } - - for _, c := range baseSet.Spec.Template.Spec.Containers { - if c.Name == "config-reloader" { - if !reflect.DeepEqual(c.Args, expectedArgsConfigReloader) { - t.Fatalf("expectd container args are %s, but found %s", expectedArgsConfigReloader, c.Args) - } - } - } - - expectedArgsInitConfigReloader := []string{ - "--watch-interval=0", - "--listen-address=:8080", - "--config-file=/etc/alertmanager/config/alertmanager.yaml.gz", - "--config-envsubst-file=/etc/alertmanager/config_out/alertmanager.env.yaml", - } - - for _, c := range baseSet.Spec.Template.Spec.Containers { - if c.Name == "init-config-reloader" { - if !reflect.DeepEqual(c.Args, expectedArgsConfigReloader) { - t.Fatalf("expectd init container args are %s, but found %s", expectedArgsInitConfigReloader, c.Args) - } - } - } - -} - -func TestAutomountServiceAccountToken(t *testing.T) { - for i := range []int{0, 1} { - automountServiceAccountToken := (i == 0) - sset, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - AutomountServiceAccountToken: &automountServiceAccountToken, - }, - }, defaultTestConfig, "", &operator.ShardedSecret{}) - if err != nil { - t.Fatalf("Unexpected error while making StatefulSet: %v", err) - } - if *sset.Spec.Template.Spec.AutomountServiceAccountToken != automountServiceAccountToken { - t.Fatal("AutomountServiceAccountToken not found") - } - } -} - -func TestClusterLabel(t *testing.T) { - tt := []struct { - scenario string - version string - expectedClusterLabelArg bool - customClusterLabel string - }{{ - scenario: "--cluster.label set by default for version >= v0.26.0", - version: "0.26.0", - expectedClusterLabelArg: true, - }, { - scenario: "--cluster.label set if specified explicitly", - version: "0.26.0", - expectedClusterLabelArg: true, - customClusterLabel: "custom.cluster", - }, { - scenario: "no --cluster.label set for older versions", - version: "0.25.0", - expectedClusterLabelArg: false, - }} - - for _, ts := range tt { - t.Run(ts.scenario, func(t *testing.T) { - a := monitoringv1.Alertmanager{ - ObjectMeta: metav1.ObjectMeta{ - Name: "alertmanager", - Namespace: "monitoring", - }, - Spec: monitoringv1.AlertmanagerSpec{ - Replicas: toPtr(int32(1)), - Version: ts.version, - }, - } - - if ts.customClusterLabel != "" { - a.Spec.ClusterLabel = &ts.customClusterLabel - } - - ss, err := makeStatefulSetSpec(nil, &a, defaultTestConfig, &operator.ShardedSecret{}) - require.NoError(t, err) - - args := ss.Template.Spec.Containers[0].Args - if ts.expectedClusterLabelArg { - if ts.customClusterLabel != "" { - require.Contains(t, args, fmt.Sprintf("--cluster.label=%s", ts.customClusterLabel)) - return - } - require.Contains(t, args, "--cluster.label=monitoring/alertmanager") - return - } - require.NotContains(t, args, "--cluster.label") - }) - } -} - -func TestMakeStatefulSetSpecTemplatesUniqueness(t *testing.T) { - replicas := int32(1) - tt := []struct { - a monitoringv1.Alertmanager - expectedSourceCount int - }{ - { - a: monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Replicas: &replicas, - AlertmanagerConfiguration: &monitoringv1.AlertmanagerConfiguration{ - Templates: []monitoringv1.SecretOrConfigMap{ - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template1", - }, - Key: "template1.tmpl", - }, - }, - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template2", - }, - Key: "template1.tmpl", - }, - }, - }, - }, - }, - }, - expectedSourceCount: 1, - }, - { - a: monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Replicas: &replicas, - AlertmanagerConfiguration: &monitoringv1.AlertmanagerConfiguration{ - Templates: []monitoringv1.SecretOrConfigMap{ - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template1", - }, - Key: "template1.tmpl", - }, - }, - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template2", - }, - Key: "template2.tmpl", - }, - }, - }, - }, - }, - }, - expectedSourceCount: 2, - }, - { - a: monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Replicas: &replicas, - AlertmanagerConfiguration: &monitoringv1.AlertmanagerConfiguration{ - Templates: []monitoringv1.SecretOrConfigMap{ - { - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "template1", - }, - Key: "template1.tmpl", - }, - }, - }, - }, - }, - }, - expectedSourceCount: 1, - }, - } - - for _, test := range tt { - statefulSpec, err := makeStatefulSetSpec(log.NewNopLogger(), &test.a, defaultTestConfig, &operator.ShardedSecret{}) - if err != nil { - t.Fatal(err) - } - volumes := statefulSpec.Template.Spec.Volumes - for _, volume := range volumes { - if volume.Name == "notification-templates" { - if len(volume.VolumeSource.Projected.Sources) != test.expectedSourceCount { - t.Fatalf("expected %d sources, got %d", test.expectedSourceCount, len(volume.VolumeSource.Projected.Sources)) - } - } - } - } -} - -func containsString(sub string) func(string) bool { - return func(x string) bool { - return strings.Contains(x, sub) - } -} - -func toPtr[T any](t T) *T { - return &t -} - -func TestEnableFeatures(t *testing.T) { - tt := []struct { - name string - version string - features []string - expectedFeatures []string - }{ - { - name: "EnableFeaturesUnsupportedVersion", - version: "v0.26.0", - features: []string{"classic-mode"}, - expectedFeatures: []string{}, - }, - { - name: "EnableFeaturesWithOneFeature", - version: "v0.27.0", - features: []string{"classic-mode"}, - expectedFeatures: []string{"classic-mode"}, - }, - { - name: "EnableFeaturesWithMultipleFeatures", - version: "v0.27.0", - features: []string{"classic-mode", "receiver-name-in-metrics"}, - expectedFeatures: []string{"classic-mode", "receiver-name-in-metrics"}, - }, - } - - for _, test := range tt { - t.Run(test.name, func(t *testing.T) { - statefulSpec, err := makeStatefulSetSpec(nil, &monitoringv1.Alertmanager{ - Spec: monitoringv1.AlertmanagerSpec{ - Version: test.version, - Replicas: toPtr(int32(1)), - EnableFeatures: test.features, - }, - }, defaultTestConfig, &operator.ShardedSecret{}) - require.NoError(t, err) - - expectedFeatures := make([]string, 0) - for _, flag := range statefulSpec.Template.Spec.Containers[0].Args { - if strings.HasPrefix(flag, "--enable-feature=") { - expectedFeatures = append(expectedFeatures, strings.Split(strings.TrimPrefix(flag, "--enable-feature="), ",")...) - } - } - require.ElementsMatch(t, test.expectedFeatures, expectedFeatures) - }) - } -} diff --git a/pkg/apis/monitoring/v1alpha1/alertmanager_config_types.go b/pkg/apis/monitoring/v1alpha1/alertmanager_config_types.go index 07aac2b14e6..de1f852ca14 100644 --- a/pkg/apis/monitoring/v1alpha1/alertmanager_config_types.go +++ b/pkg/apis/monitoring/v1alpha1/alertmanager_config_types.go @@ -566,7 +566,6 @@ type OpsGenieConfigResponder struct { Username string `json:"username,omitempty"` // Type of responder. // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:Enum=team;teams;user;escalation;schedule Type string `json:"type"` } diff --git a/pkg/k8sutil/merge_test.go b/pkg/k8sutil/merge_test.go index 1af4c97ce16..7a36f448563 100644 --- a/pkg/k8sutil/merge_test.go +++ b/pkg/k8sutil/merge_test.go @@ -156,44 +156,3 @@ func TestMergePatchContainersOrderPreserved(t *testing.T) { require.Equal(t, "", diff, "patch result did not match. diff:\n%s", diff) } } - -func TestMergePatchContainersOrderPreserved(t *testing.T) { - build := func(name, image string) v1.Container { - return v1.Container{ - Name: name, - Image: image, - } - } - - for i := 0; i < 10; i++ { - result, err := MergePatchContainers( - []v1.Container{ - build("c1", "image:base"), - build("c2", "image:base"), - }, - []v1.Container{ - build("c1", "image:A"), - build("c3", "image:B"), - build("c4", "image:C"), - build("c5", "image:D"), - build("c6", "image:E"), - }, - ) - require.NoError(t, err) - - diff := pretty.Compare( - result, - []v1.Container{ - build("c1", "image:A"), - build("c2", "image:base"), - build("c3", "image:B"), - build("c4", "image:C"), - build("c5", "image:D"), - build("c6", "image:E"), - }, - ) - if diff != "" { - t.Fatalf("patch result did not match. diff:\n%s", diff) - } - } -} diff --git a/pkg/listwatch/listwatch_test.go b/pkg/listwatch/listwatch_test.go index 38bbf5004a1..ee9a913c948 100644 --- a/pkg/listwatch/listwatch_test.go +++ b/pkg/listwatch/listwatch_test.go @@ -191,142 +191,3 @@ func TestOnlyTweak(t *testing.T) { }) } } - -func TestDenyTweak(t *testing.T) { - for _, tc := range []struct { - options metav1.ListOptions - field string - valueSet map[string]struct{} - - exp string - }{ - { - field: "metadata.name", - valueSet: map[string]struct{}{}, - exp: "", - }, - { - options: metav1.ListOptions{ - FieldSelector: "metadata.namespace=foo", - }, - field: "metadata.name", - valueSet: map[string]struct{}{}, - exp: "metadata.namespace=foo", - }, - { - field: "metadata.name", - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "metadata.name!=bar,metadata.name!=foo", - }, - { - options: metav1.ListOptions{ - FieldSelector: "metadata.namespace=foo", - }, - field: "metadata.name", - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "metadata.name!=bar,metadata.name!=foo,metadata.namespace=foo", - }, - } { - t.Run("", func(t *testing.T) { - options := tc.options - DenyTweak(&options, tc.field, tc.valueSet) - require.Equal(t, tc.exp, options.FieldSelector) - }) - } -} - -func TestOnlyTweak(t *testing.T) { - for _, tc := range []struct { - options metav1.ListOptions - label string - filter FilterType - valueSet map[string]struct{} - - exp string - }{ - { - label: "kubernetes.io/metadata.name", - filter: IncludeFilterType, - valueSet: map[string]struct{}{}, - exp: "", - }, - { - options: metav1.ListOptions{ - LabelSelector: "foo=bar", - }, - label: "kubernetes.io/metadata.name", - filter: IncludeFilterType, - valueSet: map[string]struct{}{}, - exp: "foo=bar", - }, - { - label: "kubernetes.io/metadata.name", - filter: IncludeFilterType, - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "kubernetes.io/metadata.name in (bar,foo)", - }, - { - options: metav1.ListOptions{ - LabelSelector: "foo=bar", - }, - label: "kubernetes.io/metadata.name", - filter: IncludeFilterType, - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "kubernetes.io/metadata.name in (bar,foo),foo=bar", - }, - { - label: "kubernetes.io/metadata.name", - filter: ExcludeFilterType, - valueSet: map[string]struct{}{}, - exp: "", - }, - { - options: metav1.ListOptions{ - LabelSelector: "foo=bar", - }, - label: "kubernetes.io/metadata.name", - filter: ExcludeFilterType, - valueSet: map[string]struct{}{}, - exp: "foo=bar", - }, - { - label: "kubernetes.io/metadata.name", - filter: ExcludeFilterType, - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "kubernetes.io/metadata.name notin (bar,foo)", - }, - { - options: metav1.ListOptions{ - LabelSelector: "foo=bar", - }, - label: "kubernetes.io/metadata.name", - filter: ExcludeFilterType, - valueSet: map[string]struct{}{ - "foo": {}, - "bar": {}, - }, - exp: "kubernetes.io/metadata.name notin (bar,foo),foo=bar", - }, - } { - t.Run("", func(t *testing.T) { - options := tc.options - TweakByLabel(&options, tc.label, tc.filter, tc.valueSet) - require.Equal(t, tc.exp, options.LabelSelector) - }) - } -} diff --git a/pkg/operator/sharded_secret_test.go b/pkg/operator/sharded_secret_test.go index 9058225a586..fc550cca822 100644 --- a/pkg/operator/sharded_secret_test.go +++ b/pkg/operator/sharded_secret_test.go @@ -15,8 +15,6 @@ package operator import ( - "bytes" - "strings" "testing" v1 "k8s.io/api/core/v1" diff --git a/pkg/prometheus/promcfg.go b/pkg/prometheus/promcfg.go index fdc2cd7d218..1906f6397aa 100644 --- a/pkg/prometheus/promcfg.go +++ b/pkg/prometheus/promcfg.go @@ -1797,11 +1797,6 @@ func (cg *ConfigGenerator) generateK8SSDConfig( k8sSDConfig = addTLStoYaml(k8sSDConfig, namespace, apiserverConfig.TLSConfig) } - if attachMetadataConfig != nil { - k8sSDConfig = cg.WithMinimumVersion(attachMetadataConfig.MinimumVersion).AppendMapItem(k8sSDConfig, "attach_metadata", yaml.MapSlice{ - {Key: "node", Value: attachMetadataConfig.AttachMetadata.Node}, - }) - } if attachMetadataConfig != nil { k8sSDConfig = cg.WithMinimumVersion(attachMetadataConfig.MinimumVersion).AppendMapItem(k8sSDConfig, "attach_metadata", yaml.MapSlice{ {Key: "node", Value: attachMetadataConfig.AttachMetadata.Node}, @@ -2012,14 +2007,6 @@ func (cg *ConfigGenerator) generateRemoteReadConfig( cfg = cg.WithMinimumVersion("2.34.0").AppendMapItem(cfg, "filter_external_labels", spec.FilterExternalLabels) } - if spec.FollowRedirects != nil { - cfg = cg.WithMinimumVersion("2.26.0").AppendMapItem(cfg, "follow_redirects", spec.FollowRedirects) - } - - if spec.FilterExternalLabels != nil { - cfg = cg.WithMinimumVersion("2.34.0").AppendMapItem(cfg, "filter_external_labels", spec.FilterExternalLabels) - } - cfgs = append(cfgs, cfg) } diff --git a/pkg/prometheus/promcfg_test.go b/pkg/prometheus/promcfg_test.go index 96618abe3df..c04e4f5e40b 100644 --- a/pkg/prometheus/promcfg_test.go +++ b/pkg/prometheus/promcfg_test.go @@ -10457,3876 +10457,3 @@ func TestGenerateAlertmanagerConfig(t *testing.T) { }) } } - -func TestPodMonitorEndpointFollowRedirects(t *testing.T) { - for _, tc := range []struct { - version string - golden string - followRedirects bool - }{ - { - version: "v2.25.0", - followRedirects: false, - golden: "PodMonitorEndpointFollowRedirects_FollowRedirectsFalse_v2.25.0.golden", - }, - { - version: "v2.25.0", - followRedirects: true, - golden: "PodMonitorEndpointFollowRedirects_FollowRedirectsTrue_v2.25.0.golden", - }, - { - version: "v2.28.0", - followRedirects: true, - golden: "PodMonitorEndpointFollowRedirects_FollowRedirectsTrue_v2.28.0.golden", - }, - { - version: "v2.28.0", - followRedirects: false, - golden: "PodMonitorEndpointFollowRedirects_FollowRedirectsFalse_v2.28.0.golden", - }, - } { - t.Run(fmt.Sprintf("%s TestServiceMonitorEndpointFollowRedirects(%t)", tc.version, tc.followRedirects), func(t *testing.T) { - p := defaultPrometheus() - p.Spec.CommonPrometheusFields.Version = tc.version - - podMonitor := monitoringv1.PodMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "testpodmonitor1", - Namespace: "pod-monitor-ns", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.PodMonitorSpec{ - PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{ - { - Port: "web", - Interval: "30s", - FollowRedirects: ptr.To(tc.followRedirects), - }, - }, - }, - } - - cg := mustNewConfigGenerator(t, p) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{ - "testpodmonitor1": &podMonitor, - }, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestServiceMonitorEndpointEnableHttp2(t *testing.T) { - for _, tc := range []struct { - version string - golden string - enableHTTP2 bool - }{ - { - version: "v2.34.0", - enableHTTP2: false, - golden: "ServiceMonitorEndpointEnableHttp2_EnableHTTP2False_v2.34.0.golden", - }, - { - version: "v2.34.0", - enableHTTP2: true, - golden: "ServiceMonitorEndpointEnableHttp2_EnableHTTP2True_v2.34.0.golden", - }, - { - version: "v2.35.0", - enableHTTP2: true, - golden: "ServiceMonitorEndpointEnableHttp2_EnableHTTP2True_v2.35.0.golden", - }, - { - version: "v2.35.0", - enableHTTP2: false, - golden: "ServiceMonitorEndpointEnableHttp2_EnableHTTP2False_v2.35.0.golden", - }, - } { - t.Run(fmt.Sprintf("%s TestServiceMonitorEndpointEnableHttp2(%t)", tc.version, tc.enableHTTP2), func(t *testing.T) { - p := defaultPrometheus() - p.Spec.CommonPrometheusFields.Version = tc.version - - serviceMonitor := monitoringv1.ServiceMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "testservicemonitor1", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.ServiceMonitorSpec{ - Endpoints: []monitoringv1.Endpoint{ - { - Port: "web", - Interval: "30s", - EnableHttp2: ptr.To(tc.enableHTTP2), - }, - }, - }, - } - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{ - "testservicemonitor1": &serviceMonitor, - }, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestPodMonitorPhaseFilter(t *testing.T) { - p := defaultPrometheus() - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{ - "testpodmonitor1": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testpodmonitor1", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.PodMonitorSpec{ - PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{ - { - FilterRunning: ptr.To(false), - Port: "test", - }, - }, - }, - }, - }, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "PodMonitorPhaseFilter.golden") -} - -func TestPodMonitorEndpointEnableHttp2(t *testing.T) { - for _, tc := range []struct { - version string - golden string - enableHTTP2 bool - }{ - { - version: "v2.34.0", - enableHTTP2: false, - golden: "PodMonitorEndpointEnableHttp2_EnableHTTP2False_v2.34.0.golden", - }, - { - version: "v2.34.0", - enableHTTP2: true, - golden: "PodMonitorEndpointEnableHttp2_EnableHTTP2True_v2.34.0.golden", - }, - { - version: "v2.35.0", - enableHTTP2: true, - golden: "PodMonitorEndpointEnableHttp2_EnableHTTP2True_v2.35.0.golden", - }, - { - version: "v2.35.0", - enableHTTP2: false, - golden: "PodMonitorEndpointEnableHttp2_EnableHTTP2False_v2.35.0.golden", - }, - } { - t.Run(fmt.Sprintf("%s TestServiceMonitorEndpointEnableHttp2(%t)", tc.version, tc.enableHTTP2), func(t *testing.T) { - p := defaultPrometheus() - p.Spec.CommonPrometheusFields.Version = tc.version - - podMonitor := monitoringv1.PodMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "testpodmonitor1", - Namespace: "pod-monitor-ns", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.PodMonitorSpec{ - PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{ - { - Port: "web", - Interval: "30s", - EnableHttp2: ptr.To(tc.enableHTTP2), - }, - }, - }, - } - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{ - "testpodmonitor1": &podMonitor, - }, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestStorageSettingMaxExemplars(t *testing.T) { - for _, tc := range []struct { - Scenario string - Version string - Exemplars *monitoringv1.Exemplars - Golden string - }{ - { - Scenario: "Exemplars maxSize is set to 5000000", - Exemplars: &monitoringv1.Exemplars{ - MaxSize: ptr.To(int64(5000000)), - }, - Golden: "StorageSettingMaxExemplars_MaxSize5000000.golden", - }, - { - Scenario: "max_exemplars is not set if version is less than v2.29.0", - Version: "v2.28.0", - Exemplars: &monitoringv1.Exemplars{ - MaxSize: ptr.To(int64(5000000)), - }, - Golden: "StorageSettingMaxExemplars_MaxSizeNotSet_v2.29.0.golden", - }, - { - Scenario: "Exemplars maxSize is not set", - Golden: "StorageSettingMaxExemplars_MaxSizeNotSetAtAll.golden", - }, - } { - t.Run(fmt.Sprintf("case %s", tc.Scenario), func(t *testing.T) { - p := defaultPrometheus() - if tc.Version != "" { - p.Spec.CommonPrometheusFields.Version = tc.Version - } - if tc.Exemplars != nil { - p.Spec.Exemplars = tc.Exemplars - } - cg := mustNewConfigGenerator(t, p) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.Golden) - }) - } -} - -func TestTSDBConfig(t *testing.T) { - for _, tc := range []struct { - name string - p *monitoringv1.Prometheus - version string - tsdb *monitoringv1.TSDBSpec - golden string - }{ - { - name: "no TSDB config", - golden: "no_TSDB_config.golden", - }, - { - name: "TSDB config < v2.39.0", - version: "v2.38.0", - tsdb: &monitoringv1.TSDBSpec{ - OutOfOrderTimeWindow: monitoringv1.Duration("10m"), - }, - golden: "TSDB_config_less_than_v2.39.0.golden", - }, - { - - name: "TSDB config >= v2.39.0", - tsdb: &monitoringv1.TSDBSpec{ - OutOfOrderTimeWindow: monitoringv1.Duration("10m"), - }, - golden: "TSDB_config_greater_than_or_equal_to_v2.39.0.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - p := defaultPrometheus() - if tc.version != "" { - p.Spec.CommonPrometheusFields.Version = tc.version - } - if tc.tsdb != nil { - p.Spec.TSDB = *tc.tsdb - } - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestGenerateRelabelConfig(t *testing.T) { - p := defaultPrometheus() - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{ - "test": { - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "default", - }, - Spec: monitoringv1.ServiceMonitorSpec{ - Selector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Endpoints: []monitoringv1.Endpoint{ - { - Port: "https-metrics", - Interval: "30s", - MetricRelabelConfigs: []*monitoringv1.RelabelConfig{ - { - Action: "Drop", - Regex: "container_fs*", - SourceLabels: []monitoringv1.LabelName{"__name__"}, - }, - }, - RelabelConfigs: []*monitoringv1.RelabelConfig{ - { - Action: "Uppercase", - SourceLabels: []monitoringv1.LabelName{"instance"}, - TargetLabel: "instance", - }, - { - Action: "Replace", - Regex: "(.+)(?::d+)", - Replacement: "$1:9537", - SourceLabels: []monitoringv1.LabelName{"__address__"}, - TargetLabel: "__address__", - }, - { - Action: "Replace", - Replacement: "crio", - TargetLabel: "job", - }, - }, - }, - }, - }, - }, - }, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "GenerateRelabelConfig.golden") -} - -// When adding new test cases the developer should specify a name, a Probe Spec -// (pbSpec) and an expectedConfig. (Optional) It's also possible to specify a -// function that modifies the default Prometheus CR used if necessary for the test -// case. -func TestProbeSpecConfig(t *testing.T) { - for _, tc := range []struct { - name string - patchProm func(*monitoringv1.Prometheus) - pbSpec monitoringv1.ProbeSpec - golden string - }{ - { - name: "empty_probe", - golden: "ProbeSpecConfig_empty_probe.golden", - pbSpec: monitoringv1.ProbeSpec{}, - }, - { - name: "prober_spec", - golden: "ProbeSpecConfig_prober_spec.golden", - pbSpec: monitoringv1.ProbeSpec{ - ProberSpec: monitoringv1.ProberSpec{ - Scheme: "http", - URL: "example.com", - Path: "/probe", - ProxyURL: "socks://myproxy:9095", - }, - }, - }, - { - name: "targets_static_config", - golden: "ProbeSpecConfig_targets_static_config.golden", - pbSpec: monitoringv1.ProbeSpec{ - Targets: monitoringv1.ProbeTargets{ - StaticConfig: &monitoringv1.ProbeTargetStaticConfig{ - Targets: []string{ - "prometheus.io", - "promcon.io", - }, - Labels: map[string]string{ - "static": "label", - }, - RelabelConfigs: []*monitoringv1.RelabelConfig{ - { - TargetLabel: "foo", - Replacement: "bar", - Action: "replace", - }, - }, - }, - }}, - }, - { - name: "module_config", - golden: "ProbeSpecConfig_module_config.golden", - pbSpec: monitoringv1.ProbeSpec{ - Module: "http_2xx", - }, - }, - } { - t.Run(tc.name, func(t *testing.T) { - pbs := map[string]*monitoringv1.Probe{ - "probe1": { - ObjectMeta: metav1.ObjectMeta{ - Name: "probe1", - Namespace: "default", - }, - Spec: tc.pbSpec, - }, - } - - p := defaultPrometheus() - if tc.patchProm != nil { - tc.patchProm(p) - } - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - pbs, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - - } -} - -// When adding new test cases the developer should specify a name, a ScrapeConfig Spec -// (scSpec) and an expected config in golden file (.golden file in testdata folder). (Optional) It's also possible to specify a -// function (patchProm) that modifies the default Prometheus CR used if necessary for the test -// case. -func TestScrapeConfigSpecConfig(t *testing.T) { - refreshInterval := monitoringv1.Duration("5m") - for _, tc := range []struct { - name string - version string - patchProm func(*monitoringv1.Prometheus) - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "empty_scrape_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{}, - golden: "ScrapeConfigSpecConfig_Empty.golden", - }, - { - name: "shard_config", - patchProm: func(p *monitoringv1.Prometheus) { - p.Spec.Shards = ptr.To(int32(2)) - }, - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - StaticConfigs: []monitoringv1alpha1.StaticConfig{ - { - Targets: []monitoringv1alpha1.Target{"http://localhost:9100"}, - Labels: map[monitoringv1.LabelName]string{ - "label1": "value1", - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_Sharded.golden", - }, - { - name: "already_sharded_config", - patchProm: func(p *monitoringv1.Prometheus) { - p.Spec.Shards = ptr.To(int32(2)) - }, - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - StaticConfigs: []monitoringv1alpha1.StaticConfig{ - { - Targets: []monitoringv1alpha1.Target{"http://localhost:9100"}, - Labels: map[monitoringv1.LabelName]string{ - "label1": "value1_sharded", - }, - }, - }, - RelabelConfigs: []*monitoringv1.RelabelConfig{ - { - SourceLabels: []monitoringv1.LabelName{"__address__"}, - TargetLabel: "__tmp_hash", - Modulus: 999, - Action: "hashmod", - }, - { - SourceLabels: []monitoringv1.LabelName{"__tmp_hash"}, - Regex: "$(SHARD)", - Action: "keep", - }, - }, - }, - golden: "ScrapeConfigSpecConfig_Already_Sharded.golden", - }, - { - name: "static_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - StaticConfigs: []monitoringv1alpha1.StaticConfig{ - { - Targets: []monitoringv1alpha1.Target{"http://localhost:9100"}, - Labels: map[monitoringv1.LabelName]string{ - "label1": "value1", - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_Static.golden", - }, - { - name: "file_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - FileSDConfigs: []monitoringv1alpha1.FileSDConfig{ - { - Files: []monitoringv1alpha1.SDFile{"/tmp/myfile.json"}, - RefreshInterval: &refreshInterval, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_FileSD.golden", - }, - { - name: "http_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HTTPSDConfigs: []monitoringv1alpha1.HTTPSDConfig{ - { - URL: "http://localhost:9100/sd.json", - RefreshInterval: &refreshInterval, - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(false), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "proxy-header", - }, - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HTTPSD.golden", - }, - { - name: "metrics_path", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - MetricsPath: ptr.To("/metrics"), - }, - golden: "ScrapeConfigSpecConfig_MetricPath.golden", - }, - { - name: "empty_relabel_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - RelabelConfigs: []*monitoringv1.RelabelConfig{}, - }, - golden: "ScrapeConfigSpecConfig_EmptyRelabelConfig.golden", - }, - { - name: "non_empty_relabel_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - RelabelConfigs: []*monitoringv1.RelabelConfig{ - { - Action: "Replace", - Regex: "(.+)(?::d+)", - Replacement: "$1:9537", - SourceLabels: []monitoringv1.LabelName{"__address__"}, - TargetLabel: "__address__", - }, - }, - }, - golden: "ScrapeConfigSpecConfig_NonEmptyRelabelConfig.golden", - }, - { - name: "honor_timestamp", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HonorTimestamps: ptr.To(true), - }, - golden: "ScrapeConfigSpecConfig_HonorTimeStamp.golden", - }, - { - name: "track_timestamps_staleness", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - TrackTimestampsStaleness: ptr.To(true), - }, - golden: "ScrapeConfigSpecConfig_TrackTimestampsStaleness.golden", - }, - { - name: "honor_labels", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HonorLabels: ptr.To(true), - }, - golden: "ScrapeConfigSpecConfig_HonorLabels.golden", - }, - { - name: "basic_auth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "password", - }, - }, - HTTPSDConfigs: []monitoringv1alpha1.HTTPSDConfig{ - { - URL: "http://localhost:9100/sd.json", - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "password", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_BasicAuth.golden", - }, - { - name: "authorization", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "key", - }, - }, - }, - HTTPSDConfigs: []monitoringv1alpha1.HTTPSDConfig{ - { - URL: "http://localhost:9100/sd.json", - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "key", - }, - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_Authorization.golden", - }, - { - name: "tlsconfig", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca-global", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - HTTPSDConfigs: []monitoringv1alpha1.HTTPSDConfig{ - { - URL: "http://localhost:9100/sd.json", - TLSConfig: &monitoringv1.SafeTLSConfig{ - InsecureSkipVerify: true, - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca-http", - }, - }, - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_TLSConfig.golden", - }, - { - name: "scheme", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - Scheme: ptr.To("HTTPS"), - }, - golden: "ScrapeConfigSpecConfig_Scheme.golden", - }, - { - name: "limits", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - SampleLimit: ptr.To(uint64(10000)), - TargetLimit: ptr.To(uint64(1000)), - LabelLimit: ptr.To(uint64(50)), - LabelNameLengthLimit: ptr.To(uint64(40)), - LabelValueLengthLimit: ptr.To(uint64(30)), - }, - golden: "ScrapeConfigSpecConfig_Limits.golden", - }, - { - name: "params", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - MetricsPath: ptr.To("/federate"), - Params: map[string][]string{"match[]": {"{job=\"prometheus\"}", "{__name__=~\"job:.*\"}"}}, - }, - golden: "ScrapeConfigSpecConfig_Params.golden", - }, - { - name: "scrape_interval", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ScrapeInterval: ptr.To(monitoringv1.Duration("15s")), - }, - golden: "ScrapeConfigSpecConfig_ScrapeInterval.golden", - }, - { - name: "scrape_timeout", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ScrapeTimeout: ptr.To(monitoringv1.Duration("10s")), - }, - golden: "ScrapeConfigSpecConfig_ScrapeTimeout.golden", - }, - { - name: "scrape_protocols", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ScrapeProtocols: []monitoringv1.ScrapeProtocol{ - monitoringv1.ScrapeProtocol("PrometheusProto"), - monitoringv1.ScrapeProtocol("OpenMetricsText1.0.0"), - monitoringv1.ScrapeProtocol("OpenMetricsText0.0.1"), - monitoringv1.ScrapeProtocol("PrometheusText0.0.4"), - }, - }, - golden: "ScrapeConfigSpecConfig_ScrapeProtocols.golden", - }, - { - name: "non_empty_metric_relabel_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - MetricRelabelConfigs: []*monitoringv1.RelabelConfig{ - { - Regex: "noisy_labels.*", - Action: "labeldrop", - }, - }, - }, - golden: "ScrapeConfigSpecConfig_NonEmptyMetricRelabelConfig.golden", - }, - { - name: "proxy_settings", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(false), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "proxy-header", - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_ProxySettings.golden", - }, - { - name: "proxy_settings_incompatible_prometheus_version", - patchProm: func(p *monitoringv1.Prometheus) { - p.Spec.CommonPrometheusFields.Version = "v2.42.0" - }, - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(false), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "proxy-header", - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_ProxySettingsIncompatiblePrometheusVersion.golden", - }, - { - name: "dns_sd_config-srv-record", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DNSSDConfigs: []monitoringv1alpha1.DNSSDConfig{ - { - Names: []string{"web.example.com"}, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DNSSD_SRVRecord.golden", - }, - { - name: "dns_sd_config-a-record", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DNSSDConfigs: []monitoringv1alpha1.DNSSDConfig{ - { - Names: []string{"node.demo.do.prometheus.io"}, - Type: ptr.To("A"), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DNSSD_ARecord.golden", - }, - { - name: "dns_sd_config-ns-record", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DNSSDConfigs: []monitoringv1alpha1.DNSSDConfig{ - { - Names: []string{"node.demo.do.prometheus.io"}, - Type: ptr.To("NS"), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DNSSD_NSRecord.golden", - }, - { - name: "dns_sd_config-ns-record-old-version", - version: "v2.48.0", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DNSSDConfigs: []monitoringv1alpha1.DNSSDConfig{ - { - Names: []string{"node.demo.do.prometheus.io"}, - Type: ptr.To("NS"), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DNSSD_NSRecord_OldVersion.golden", - }, - { - name: "enable_compression_is_set_to_true", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EnableCompression: ptr.To(true), - }, - golden: "ScrapeConfigSpecConfig_EnableCompression_True.golden", - }, - { - name: "enable_compression_is_set_to_false", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EnableCompression: ptr.To(false), - }, - golden: "ScrapeConfigSpecConfig_EnableCompression_False.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - if tc.version != "" { - p.Spec.CommonPrometheusFields.Version = tc.version - } - if tc.patchProm != nil { - tc.patchProm(p) - } - - cg := mustNewConfigGenerator(t, p) - - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.BasicAuthAssets = map[string]assets.BasicAuthCredentials{ - "scrapeconfig/default/testscrapeconfig1": { - Username: "scrape-bob", - Password: "scrape-alice", - }, - "scrapeconfig/default/testscrapeconfig1/httpsdconfig/0": { - Username: "http-sd-bob", - Password: "http-sd-alice", - }, - } - store.TokenAssets = map[string]assets.Token{ - "scrapeconfig/auth/default/testscrapeconfig1": assets.Token("scrape-secret"), - "scrapeconfig/auth/default/testscrapeconfig1/httpsdconfig/0": assets.Token("http-sd-secret"), - } - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithKubernetesSD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "kubernetes_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD.golden", - }, - { - name: "kubernetes_sd_config_with_namespace_discovery_and_own_namespace", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Pod"), - Namespaces: &monitoringv1alpha1.NamespaceDiscovery{ - IncludeOwnNamespace: ptr.To(true), - Names: []string{"ns1", "ns2"}, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_NamespaceDiscovery_and_OwnNamespace.golden", - }, - { - name: "kubernetes_sd_config_with_namespace_discovery", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Pod"), - Namespaces: &monitoringv1alpha1.NamespaceDiscovery{ - Names: []string{"ns1", "ns2"}, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_NamespaceDiscovery.golden", - }, - { - name: "kubernetes_sd_config_with_supported_role_attach_metadata", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Pod"), - AttachMetadata: &monitoringv1alpha1.AttachMetadata{ - Node: ptr.To(true), - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_AttachMetadata.golden", - }, - { - name: "kubernetes_sd_config_with_unsupported_role_attach_metadata", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Service"), - AttachMetadata: &monitoringv1alpha1.AttachMetadata{ - Node: ptr.To(true), - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_Unsupported_Role_AttachMetadata.golden", - }, - { - name: "kubernetes_sd_config_with_selectors", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - Selectors: []monitoringv1alpha1.K8SSelectorConfig{ - { - Role: "node", - Label: "type=infra", - Field: "spec.unschedulable=false", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_Selectors.golden", - }, - { - name: "kubernetes_sd_config_basic_auth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "Username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "Password", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_BasicAuth.golden", - }, { - name: "kubernetes_sd_config_authorization", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_Authorization.golden", - }, { - name: "kubernetes_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_OAuth.golden", - }, { - name: "kubernetes_sd_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KubernetesSDConfigs: []monitoringv1alpha1.KubernetesSDConfig{ - { - Role: monitoringv1alpha1.Role("Node"), - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_K8SSD_with_TLSConfig.golden", - }} { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.BasicAuthAssets = map[string]assets.BasicAuthCredentials{ - "scrapeconfig/default/testscrapeconfig1/kubernetessdconfig/0": { - Username: "kube-admin", - Password: "password", - }, - } - - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/kubernetessdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - - } -} - -func TestScrapeConfigSpecConfigWithConsulSD(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - }, - }, - ) - for _, tc := range []struct { - name string - patchProm func(*monitoringv1.Prometheus) - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "consul_scrape_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ConsulSDConfigs: []monitoringv1alpha1.ConsulSDConfig{ - { - Server: "localhost", - Datacenter: ptr.To("we1"), - Namespace: ptr.To("observability"), - Partition: ptr.To("1"), - Scheme: ptr.To("https"), - Services: []string{"prometheus", "alertmanager"}, - Tags: []string{"tag1"}, - TagSeparator: ptr.To(";"), - NodeMeta: map[string]string{ - "service": "service_name", - "name": "node_name", - }, - AllowStale: ptr.To(false), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHttp2: ptr.To(true), - TokenRef: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "token", - }, - }, - }, - }, - golden: "ConsulScrapeConfig.golden", - }, { - name: "consul_scrape_config_basic_auth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ConsulSDConfigs: []monitoringv1alpha1.ConsulSDConfig{ - { - Server: "localhost:8500", - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "password", - }, - }, - }, - }, - }, - golden: "ConsulScrapeConfigBasicAuth.golden", - }, { - name: "consul_scrape_config_authorization", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ConsulSDConfigs: []monitoringv1alpha1.ConsulSDConfig{ - { - Server: "localhost:8500", - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "credential", - }, - }, - }, - }, - }, - golden: "ConsulScrapeConfigAuthorization.golden", - }, { - name: "consul_scrape_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ConsulSDConfigs: []monitoringv1alpha1.ConsulSDConfig{ - { - Server: "localhost:8500", - Oauth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ConsulScrapeConfigOAuth.golden", - }, { - name: "consul_scrape_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - ConsulSDConfigs: []monitoringv1alpha1.ConsulSDConfig{ - { - Server: "localhost:8500", - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca-global", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ConsulScrapeConfigTLSConfig.golden", - }} { - t.Run(tc.name, func(t *testing.T) { - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.BasicAuthAssets = map[string]assets.BasicAuthCredentials{ - "scrapeconfig/default/testscrapeconfig1/consulsdconfig/0": { - Username: "consul-sd-bob", - Password: "consul-sd-alice", - }, - } - - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/consulsdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - store.TokenAssets = map[string]assets.Token{ - "scrapeconfig/auth/default/testscrapeconfig1/consulsdconfig/0": assets.Token("authorization"), - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - if tc.patchProm != nil { - tc.patchProm(p) - } - - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - - } -} - -func TestScrapeConfigSpecConfigWithEC2SD(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "aws-access-api", - Namespace: "default", - }, - Data: map[string][]byte{ - "accessKey": []byte("access-key"), - "secretKey": []byte("secret-key"), - }, - }, - ) - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - expectedErr bool - }{ - { - name: "ec2_sd_config_valid_with_api_keys", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{ - { - Region: ptr.To("us-east-1"), - AccessKey: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "aws-access-api", - }, - Key: "accessKey", - }, - SecretKey: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "aws-access-api", - }, - Key: "secretKey", - }, - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EC2SDConfigValidAPIKeys.golden", - }, - { - name: "ec2_sd_config_valid_with_role_arn", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{ - { - Region: ptr.To("us-east-1"), - RoleARN: ptr.To("arn:aws:iam::123456789:role/prometheus-role"), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EC2SDConfigValidRoleARN.golden", - }, - { - name: "ec2_sd_config_valid_with_filters", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{ - { - Region: ptr.To("us-east-1"), - RoleARN: ptr.To("arn:aws:iam::123456789:role/prometheus-role"), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - Filters: []*monitoringv1alpha1.EC2Filter{ - { - Name: "tag:environment", - Values: []string{"prod"}, - }, - { - Name: "tag:service", - Values: []string{"web", "db"}, - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EC2SDConfigFilters.golden", - }, - { - name: "ec2_sd_config_invalid", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{ - { - Region: ptr.To("us-east-1"), - AccessKey: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "wrong-secret-name", - }, - Key: "accessKey", - }, - SecretKey: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "aws-access-api", - }, - Key: "secretKey", - }, - }, - }, - }, - expectedErr: true, - }, - { - name: "ec2_sd_config_empty", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{}, - }, - golden: "ScrapeConfigSpecConfig_EC2SDConfigEmpty.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - assets.NewStore(c.CoreV1(), c.CoreV1()), - nil, - nil, - nil, - nil, - ) - if tc.expectedErr { - require.Error(t, err) - return - } - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithAzureSD(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "azure-client-secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "clientSecret": []byte("my-secret"), - }, - }, - ) - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - expectedErr bool - }{ - { - name: "azure_sd_config_valid", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - AzureSDConfigs: []monitoringv1alpha1.AzureSDConfig{ - { - Environment: ptr.To("AzurePublicCloud"), - AuthenticationMethod: ptr.To("OAuth"), - SubscriptionID: "11AAAA11-A11A-111A-A111-1111A1111A11", - TenantID: ptr.To("BBBB222B-B2B2-2B22-B222-2BB2222BB2B2"), - ClientID: ptr.To("333333CC-3C33-3333-CCC3-33C3CCCCC33C"), - ClientSecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "azure-client-secret", - }, - Key: "clientSecret", - }, - ResourceGroup: ptr.To("my-resource-group"), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_AzureSDConfigValid.golden", - }, - { - name: "azure_sd_config_invalid", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - AzureSDConfigs: []monitoringv1alpha1.AzureSDConfig{ - { - ClientSecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "wrong-secret-name", - }, - Key: "clientSecret", - }, - }, - }, - }, - expectedErr: true, - }, - { - name: "azure_sd_config_empty", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EC2SDConfigs: []monitoringv1alpha1.EC2SDConfig{}, - }, - golden: "ScrapeConfigSpecConfig_AzureSDConfigEmpty.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - assets.NewStore(c.CoreV1(), c.CoreV1()), - nil, - nil, - nil, - nil, - ) - if tc.expectedErr { - require.Error(t, err) - return - } - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithGCESD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - expectedErr bool - }{ - { - name: "gce_sd_config_valid", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - GCESDConfigs: []monitoringv1alpha1.GCESDConfig{ - { - Project: "devops-dev", - Zone: "us-west-1", - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_GCESDConfigValid.golden", - }, - { - name: "gce_sd_config_empty", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - GCESDConfigs: []monitoringv1alpha1.GCESDConfig{}, - }, - golden: "ScrapeConfigSpecConfig_GCESDConfigEmpty.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - nil, - nil, - nil, - nil, - nil, - ) - if tc.expectedErr { - require.Error(t, err) - return - } - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithOpenStackSD(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "openstack-access-secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "password": []byte("password"), - "applicationCredentialsSecret": []byte("application-credentials"), - }, - }, - ) - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - expectedErr bool - }{ - { - name: "openstack_sd_config_valid", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - OpenStackSDConfigs: []monitoringv1alpha1.OpenStackSDConfig{ - { - Role: "Instance", - Region: "region-1", - IdentityEndpoint: ptr.To("http://identity.example.com:5000/v2.0"), - Username: ptr.To("nova-user-1"), - Password: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "openstack-access-secret", - }, - Key: "password", - }, - DomainName: ptr.To("devops-project-1"), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - Port: ptr.To(9100), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_OpenStackSDConfigValid.golden", - }, - { - name: "openstack_sd_config_invalid_secret_ref", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - OpenStackSDConfigs: []monitoringv1alpha1.OpenStackSDConfig{ - { - Role: "Instance", - Region: "region-1", - ApplicationCredentialSecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "openstack-access-secret", - }, - Key: "invalid-key", - }, - }, - }, - }, - expectedErr: true, - }, - { - name: "openstack_sd_config_empty", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - OpenStackSDConfigs: []monitoringv1alpha1.OpenStackSDConfig{}, - }, - golden: "ScrapeConfigSpecConfig_OpenStackSDConfigEmpty.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - assets.NewStore(c.CoreV1(), c.CoreV1()), - nil, - nil, - nil, - nil, - ) - if tc.expectedErr { - require.Error(t, err) - return - } - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithDigitalOceanSD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "digitalocean_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DigitalOceanSDConfigs: []monitoringv1alpha1.DigitalOceanSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - Port: ptr.To(9100), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DigitalOceanSD.golden", - }, - { - name: "digitalocean_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DigitalOceanSDConfigs: []monitoringv1alpha1.DigitalOceanSDConfig{ - { - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DigitalOceanSD_with_OAuth.golden", - }, { - name: "digitalocean_sd_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DigitalOceanSDConfigs: []monitoringv1alpha1.DigitalOceanSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DigitalOceanSD_with_TLSConfig.golden", - }} { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - "credential": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/digitaloceansdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithDockerSDConfig(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "docker_sd_config_with_authorization", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DockerSDConfigs: []monitoringv1alpha1.DockerSDConfig{ - { - Host: "hostAddress", - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - Port: ptr.To(9100), - RefreshInterval: ptr.To(monitoringv1.Duration("30s")), - HostNetworkingHost: ptr.To("localhost"), - Filters: &[]monitoringv1alpha1.DockerFilter{ - {Name: "dummy_label_1", - Values: []string{"dummy_value_1"}}, - {Name: "dummy_label_2", - Values: []string{"dummy_value_2", "dummy_value_3"}}, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DockerSDConfig.golden", - }, - { - name: "docker_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DockerSDConfigs: []monitoringv1alpha1.DockerSDConfig{ - { - Host: "hostAddress", - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - Filters: &[]monitoringv1alpha1.DockerFilter{ - {Name: "dummy_label_1", - Values: []string{"dummy_value_1"}}, - {Name: "dummy_label_2", - Values: []string{"dummy_value_2", "dummy_value_3"}}, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DockerSD_with_OAuth.golden", - }, - { - name: "docker_sd_config_basicauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - DockerSDConfigs: []monitoringv1alpha1.DockerSDConfig{ - { - Host: "hostAddress", - Filters: &[]monitoringv1alpha1.DockerFilter{ - {Name: "dummy_label_1", - Values: []string{"dummy_value_1"}}, - {Name: "dummy_label_2", - Values: []string{"dummy_value_2", "dummy_value_3"}}, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "foo", - }, - Key: "password", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_DockerSD_with_BasicAuth.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - "credential": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/dockersdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - store.BasicAuthAssets = map[string]assets.BasicAuthCredentials{ - "alertmanager/auth/0": { - Username: "bob", - Password: "alice", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} -func TestScrapeConfigSpecConfigWithHetznerSD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "hetzner_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HetznerSDConfigs: []monitoringv1alpha1.HetznerSDConfig{ - { - Role: "hcloud", - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - Port: ptr.To(9100), - RefreshInterval: ptr.To(monitoringv1.Duration("5m")), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HetznerSD.golden", - }, - { - name: "hetzner_sd_config_basic_auth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HetznerSDConfigs: []monitoringv1alpha1.HetznerSDConfig{ - { - Role: "hcloud", - BasicAuth: &monitoringv1.BasicAuth{ - Username: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "Username", - }, - Password: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "Password", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HetznerSD_with_BasicAuth.golden", - }, { - name: "hetzner_sd_config_authorization", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HetznerSDConfigs: []monitoringv1alpha1.HetznerSDConfig{ - { - Role: "hcloud", - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HetznerSD_with_Authorization.golden", - }, { - name: "hetzner_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HetznerSDConfigs: []monitoringv1alpha1.HetznerSDConfig{ - { - Role: "hcloud", - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HetznerSD_with_OAuth.golden", - }, { - name: "hetzner_sd_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - HetznerSDConfigs: []monitoringv1alpha1.HetznerSDConfig{ - { - Role: "hcloud", - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_HetznerSD_with_TLSConfig.golden", - }, - } { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.BasicAuthAssets = map[string]assets.BasicAuthCredentials{ - "scrapeconfig/default/testscrapeconfig1/hetznersdconfig/0": { - Username: "kube-admin", - Password: "password", - }, - } - - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/hetznersdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestTracingConfig(t *testing.T) { - samplingTwo := resource.MustParse("0.5") - testCases := []struct { - tracingConfig *monitoringv1.PrometheusTracingConfig - name string - expectedErr bool - golden string - }{ - { - name: "Config only with endpoint", - tracingConfig: &monitoringv1.PrometheusTracingConfig{ - Endpoint: "https://otel-collector.default.svc.local:3333", - }, - golden: "TracingConfig_Config_only_with_endpoint.golden", - expectedErr: false, - }, - { - tracingConfig: &monitoringv1.PrometheusTracingConfig{ - ClientType: ptr.To("grpc"), - Endpoint: "https://otel-collector.default.svc.local:3333", - SamplingFraction: &samplingTwo, - Headers: map[string]string{ - "custom": "header", - }, - Compression: ptr.To("gzip"), - Timeout: ptr.To(monitoringv1.Duration("10s")), - Insecure: ptr.To(false), - }, - name: "Expect valid config", - expectedErr: false, - golden: "TracingConfig_Expect_valid_config.golden", - }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - p := defaultPrometheus() - - p.Spec.CommonPrometheusFields.TracingConfig = tc.tracingConfig - - cg := mustNewConfigGenerator(t, p) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - p.Spec.RuleSelector, - p.Spec.Exemplars, - p.Spec.TSDB, - p.Spec.Alerting, - p.Spec.RemoteRead, - nil, - nil, - nil, - nil, - nil, - nil, - nil, - nil, - nil, - ) - if tc.expectedErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestScrapeConfigSpecConfigWithKumaSD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "kuma_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KumaSDConfigs: []monitoringv1alpha1.KumaSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - Server: "127.0.0.1", - ClientID: ptr.To("client"), - FetchTimeout: (*monitoringv1.Duration)(ptr.To("5s")), - RefreshInterval: (*monitoringv1.Duration)(ptr.To("30s")), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_KumaSD.golden", - }, - { - name: "kuma_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KumaSDConfigs: []monitoringv1alpha1.KumaSDConfig{ - { - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_KumaSD_with_OAuth.golden", - }, { - name: "kuma_sd_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - KumaSDConfigs: []monitoringv1alpha1.KumaSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_KumaSD_with_TLSConfig.golden", - }} { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - "credential": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/kumasdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func defaultServiceMonitor() *monitoringv1.ServiceMonitor { - return &monitoringv1.ServiceMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "defaultServiceMonitor", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.ServiceMonitorSpec{ - Selector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "group": "group1", - }, - }, - Endpoints: []monitoringv1.Endpoint{ - { - Port: "web", - Interval: "30s", - }, - }, - }, - } -} - -func defaultProbe() *monitoringv1.Probe { - return &monitoringv1.Probe{ - ObjectMeta: metav1.ObjectMeta{ - Name: "defaultProbe", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.ProbeSpec{ - ProberSpec: monitoringv1.ProberSpec{ - Scheme: "http", - URL: "blackbox.exporter.io", - Path: "/probe", - }, - Module: "http_2xx", - Targets: monitoringv1.ProbeTargets{ - StaticConfig: &monitoringv1.ProbeTargetStaticConfig{ - Targets: []string{ - "prometheus.io", - "promcon.io", - }, - Labels: map[string]string{ - "namespace": "custom", - "static": "label", - }, - }, - }, - MetricRelabelConfigs: []*monitoringv1.RelabelConfig{ - { - Regex: "noisy_labels.*", - Action: "labeldrop", - }, - }, - }, - } -} - -func defaultPodMonitor() *monitoringv1.PodMonitor { - return &monitoringv1.PodMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "defaultPodMonitor", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1.PodMonitorSpec{ - Selector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "group": "group1", - }, - }, - PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{ - { - Port: "web", - Interval: "30s", - }, - }, - }, - } -} - -func defaultScrapeConfig() *monitoringv1alpha1.ScrapeConfig { - return &monitoringv1alpha1.ScrapeConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: "defaultScrapeConfig", - Namespace: "default", - Labels: map[string]string{ - "group": "group1", - }, - }, - Spec: monitoringv1alpha1.ScrapeConfigSpec{ - HTTPSDConfigs: []monitoringv1alpha1.HTTPSDConfig{ - { - URL: "http://localhost:9100/sd.json", - RefreshInterval: ptr.To(monitoringv1.Duration("5m")), - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(false), - }, - }, - }, - }, - } -} - -func TestScrapeClass(t *testing.T) { - testCases := []struct { - name string - scrapeClass []monitoringv1.ScrapeClass - tlsConfig *monitoringv1.TLSConfig - golden string - }{ - { - name: "Monitor Object without Scrape Class", - golden: "monitorObjectWithoutScrapeClass.golden", - scrapeClass: []monitoringv1.ScrapeClass{}, - }, - { - name: "Monitor object with Non Default Scrape Class and TLS Config", - golden: "monitorObjectWithNonDefaultScrapeClassAndTLSConfig.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - }, - }, - { - name: "Monitor object with Default Scrape Class and TLS Config", - golden: "monitorObjectWithDefaultScrapeClassAndTLSConfig.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - Default: ptr.To(true), - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/default/ca.crt", - CertFile: "/etc/prometheus/secrets/default/tls.crt", - KeyFile: "/etc/prometheus/secrets/default/tls.key", - }, - }, - }, - }, - } - - for _, tc := range testCases { - prometheus := defaultPrometheus() - serviceMonitor := defaultServiceMonitor() - podMonitor := defaultPodMonitor() - probe := defaultProbe() - scrapeConfig := defaultScrapeConfig() - - for _, sc := range tc.scrapeClass { - prometheus.Spec.ScrapeClasses = append(prometheus.Spec.ScrapeClasses, sc) - if sc.Default == nil { - serviceMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - podMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - probe.Spec.ScrapeClassName = ptr.To(sc.Name) - scrapeConfig.Spec.ScrapeClassName = ptr.To(sc.Name) - } - } - - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{"monitor": serviceMonitor}, - map[string]*monitoringv1.PodMonitor{"monitor": podMonitor}, - map[string]*monitoringv1.Probe{"monitor": probe}, - map[string]*monitoringv1alpha1.ScrapeConfig{"monitor": scrapeConfig}, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - } -} - -func TestServiceMonitorScrapeClassWithDefaultTls(t *testing.T) { - testCases := []struct { - name string - scrapeClass []monitoringv1.ScrapeClass - tlsConfig *monitoringv1.TLSConfig - golden string - }{ - { - name: "Monitor object with Non Default Scrape Class and existing TLS Config", - golden: "serviceMonitorObjectWithNonDefaultScrapeClassAndExistingTLSConfig.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - }, - tlsConfig: &monitoringv1.TLSConfig{ - SafeTLSConfig: monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca-global", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - { - name: "Monitor object with Non Default Scrape Class and existing TLS config missing ca", - golden: "serviceMonitorObjectWithNonDefaultScrapeClassAndExistingTLSConfigMissingCA.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - }, - tlsConfig: &monitoringv1.TLSConfig{ - SafeTLSConfig: monitoringv1.SafeTLSConfig{ - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - } - - for _, tc := range testCases { - prometheus := defaultPrometheus() - serviceMonitor := defaultServiceMonitor() - - for _, sc := range tc.scrapeClass { - prometheus.Spec.ScrapeClasses = append(prometheus.Spec.ScrapeClasses, sc) - if sc.Default == nil { - serviceMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - } - } - - serviceMonitor.Spec.Endpoints[0].TLSConfig = tc.tlsConfig - - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{"monitor": serviceMonitor}, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - } -} - -func TestPodMonitorScrapeClassWithDefaultTls(t *testing.T) { - testCases := []struct { - name string - scrapeClass []monitoringv1.ScrapeClass - tlsConfig *monitoringv1.SafeTLSConfig - golden string - }{ - { - name: "Monitor object with Non Default Scrape Class and existing TLS Config", - golden: "podMonitorObjectWithNonDefaultScrapeClassAndExistingTLSConfig.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - }, - tlsConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca-global", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - { - name: "Monitor object with Non Default Scrape Class and existing TLS config missing ca", - golden: "podMonitorObjectWithNonDefaultScrapeClassAndExistingTLSConfigMissingCA.golden", - scrapeClass: []monitoringv1.ScrapeClass{ - { - Name: "test-tls-scrape-class", - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - }, - tlsConfig: &monitoringv1.SafeTLSConfig{ - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - } - - for _, tc := range testCases { - prometheus := defaultPrometheus() - podMonitor := defaultPodMonitor() - - for _, sc := range tc.scrapeClass { - prometheus.Spec.ScrapeClasses = append(prometheus.Spec.ScrapeClasses, sc) - if sc.Default == nil { - podMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - } - } - podMonitor.Spec.PodMetricsEndpoints[0].TLSConfig = tc.tlsConfig - - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{"monitor": podMonitor}, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - } -} - -func TestNewConfigGeneratorWithMultipleDefaultScrapeClass(t *testing.T) { - logger := level.NewFilter(log.NewLogfmtLogger(os.Stdout), level.AllowWarn()) - p := defaultPrometheus() - p.Spec.ScrapeClasses = []monitoringv1.ScrapeClass{ - { - Name: "test-default-scrape-class", - Default: ptr.To(true), - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - { - Name: "test-default-scrape-class-2", - Default: ptr.To(true), - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "/etc/prometheus/secrets/ca.crt", - CertFile: "/etc/prometheus/secrets/tls.crt", - KeyFile: "/etc/prometheus/secrets/tls.key", - }, - }, - } - _, err := NewConfigGenerator(log.With(logger, "test", "NewConfigGeneratorWithMultipleDefaultScrapeClass"), p, false) - require.Error(t, err) - require.Equal(t, "failed to parse scrape classes: multiple default scrape classes defined", err.Error()) -} - -func TestMergeTLSConfigWithScrapeClass(t *testing.T) { - tests := []struct { - name string - tlsConfig *monitoringv1.TLSConfig - scrapeClass *monitoringv1.ScrapeClass - expectedConfig *monitoringv1.TLSConfig - cg *ConfigGenerator - }{ - { - name: "nil TLSConfig and ScrapeClass with default", - tlsConfig: nil, - scrapeClass: nil, - expectedConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - cg: &ConfigGenerator{ - defaultScrapeClassName: "default", - scrapeClasses: map[string]*monitoringv1.ScrapeClass{ - "default": { - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - }, - }, - }, - }, - { - name: "nil TLSConfig and ScrapeClass without default", - tlsConfig: nil, - scrapeClass: nil, - expectedConfig: nil, - cg: &ConfigGenerator{ - scrapeClasses: map[string]*monitoringv1.ScrapeClass{ - "default": { - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - }, - }, - }, - }, - { - name: "non-nil TLSConfig and nil ScrapeClass", - tlsConfig: &monitoringv1.TLSConfig{ - CAFile: "caFile", - CertFile: "certFile", - KeyFile: "keyFile", - }, - scrapeClass: nil, - expectedConfig: &monitoringv1.TLSConfig{ - CAFile: "caFile", - CertFile: "certFile", - KeyFile: "keyFile", - }, - cg: &ConfigGenerator{ - defaultScrapeClassName: "default", - scrapeClasses: map[string]*monitoringv1.ScrapeClass{ - "default": { - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - }, - }, - }, - }, - { - name: "nil TLSConfig and non-nil ScrapeClass", - tlsConfig: nil, - scrapeClass: &monitoringv1.ScrapeClass{ - Name: "default", - }, - expectedConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - cg: &ConfigGenerator{ - defaultScrapeClassName: "default", - scrapeClasses: map[string]*monitoringv1.ScrapeClass{ - "default": { - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - }, - }, - }, - }, - { - name: "nil TLSConfig, non-nil ScrapeClass with nil TLSConfig", - tlsConfig: nil, - scrapeClass: &monitoringv1.ScrapeClass{ - Name: "default", - TLSConfig: nil, - }, - expectedConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - cg: &ConfigGenerator{ - defaultScrapeClassName: "default", - scrapeClasses: map[string]*monitoringv1.ScrapeClass{ - "default": { - TLSConfig: &monitoringv1.TLSConfig{ - CAFile: "defaultCAFile", - CertFile: "defaultCertFile", - KeyFile: "defaultKeyFile", - }, - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := tt.cg.MergeTLSConfigWithScrapeClass(tt.tlsConfig, tt.scrapeClass) - require.Equal(t, tt.expectedConfig, result, "expected %v, got %v", tt.expectedConfig, result) - }) - } -} - -func TestScrapeConfigSpecConfigWithEurekaSD(t *testing.T) { - for _, tc := range []struct { - name string - scSpec monitoringv1alpha1.ScrapeConfigSpec - golden string - }{ - { - name: "eureka_sd_config", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EurekaSDConfigs: []monitoringv1alpha1.EurekaSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - ProxyConfig: monitoringv1.ProxyConfig{ - ProxyURL: ptr.To("http://no-proxy.com"), - NoProxy: ptr.To("0.0.0.0"), - ProxyFromEnvironment: ptr.To(true), - ProxyConnectHeader: map[string]v1.SecretKeySelector{ - "header": { - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "proxy-header", - }, - }, - }, - FollowRedirects: ptr.To(true), - EnableHTTP2: ptr.To(true), - Server: "127.0.0.1", - RefreshInterval: (*monitoringv1.Duration)(ptr.To("30s")), - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EurekaSD.golden", - }, - { - name: "eureka_sd_config_oauth", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EurekaSDConfigs: []monitoringv1alpha1.EurekaSDConfig{ - { - OAuth2: &monitoringv1.OAuth2{ - ClientID: monitoringv1.SecretOrConfigMap{ - ConfigMap: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_id", - }, - }, - ClientSecret: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "oauth2", - }, - Key: "client_secret", - }, - TokenURL: "http://test.url", - Scopes: []string{"scope 1", "scope 2"}, - EndpointParams: map[string]string{ - "param1": "value1", - "param2": "value2", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EurekaSD_with_OAuth.golden", - }, { - name: "eureka_sd_config_tls", - scSpec: monitoringv1alpha1.ScrapeConfigSpec{ - EurekaSDConfigs: []monitoringv1alpha1.EurekaSDConfig{ - { - Authorization: &monitoringv1.SafeAuthorization{ - Credentials: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "credential", - }, - }, - TLSConfig: &monitoringv1.SafeTLSConfig{ - CA: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-ca", - }, - }, - }, - Cert: monitoringv1.SecretOrConfigMap{ - Secret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret-cert", - }, - }, - }, - KeySecret: &v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: "secret", - }, - Key: "key", - }, - }, - }, - }, - }, - golden: "ScrapeConfigSpecConfig_EurekaSD_with_TLSConfig.golden", - }} { - t.Run(tc.name, func(t *testing.T) { - c := fake.NewSimpleClientset( - &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "proxy-header": []byte("value"), - "token": []byte("value"), - "credential": []byte("value"), - }, - }, - ) - store := assets.NewStore(c.CoreV1(), c.CoreV1()) - store.OAuth2Assets = map[string]assets.OAuth2Credentials{ - "scrapeconfig/default/testscrapeconfig1/eurekasdconfig/0": { - ClientID: "client-id", - ClientSecret: "client-secret", - }, - } - - scs := map[string]*monitoringv1alpha1.ScrapeConfig{ - "sc": { - ObjectMeta: metav1.ObjectMeta{ - Name: "testscrapeconfig1", - Namespace: "default", - }, - Spec: tc.scSpec, - }, - } - - p := defaultPrometheus() - cg := mustNewConfigGenerator(t, p) - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - p.Spec.EvaluationInterval, - p.Spec.QueryLogFile, - nil, - nil, - p.Spec.TSDB, - nil, - nil, - nil, - nil, - nil, - scs, - store, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), tc.golden) - }) - } -} - -func TestServiceMonitorWithDefaultScrapeClassRelabelings(t *testing.T) { - prometheus := defaultPrometheus() - serviceMonitor := defaultServiceMonitor() - scrapeClasses := []monitoringv1.ScrapeClass{ - { - Name: "default", - Default: ptr.To(true), - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_app_name"}, - TargetLabel: "app", - }, - }, - }, - { - Name: "not-default", - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_node_name"}, - TargetLabel: "node", - }, - }, - }, - } - - prometheus.Spec.ScrapeClasses = scrapeClasses - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{"monitor": serviceMonitor}, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "serviceMonitorObjectWithDefaultScrapeClassWithRelabelings.golden") -} - -func TestServiceMonitorWithNonDefaultScrapeClassRelabelings(t *testing.T) { - prometheus := defaultPrometheus() - serviceMonitor := defaultServiceMonitor() - sc := monitoringv1.ScrapeClass{ - Name: "test-extra-relabelings-scrape-class", - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_node_name"}, - TargetLabel: "node", - }, - }, - } - - prometheus.Spec.ScrapeClasses = append(prometheus.Spec.ScrapeClasses, sc) - serviceMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - map[string]*monitoringv1.ServiceMonitor{"monitor": serviceMonitor}, - nil, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "serviceMonitorObjectWithNonDefaultScrapeClassWithRelabelings.golden") -} - -func TestPodMonitorWithDefaultScrapeClassRelabelings(t *testing.T) { - prometheus := defaultPrometheus() - podMonitor := defaultPodMonitor() - scrapeClasses := []monitoringv1.ScrapeClass{ - { - Name: "default", - Default: ptr.To(true), - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_app_name"}, - TargetLabel: "app", - }, - }, - }, - { - Name: "not-default", - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_node_name"}, - TargetLabel: "node", - }, - }, - }, - } - - prometheus.Spec.ScrapeClasses = scrapeClasses - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{"monitor": podMonitor}, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "podMonitorObjectWithDefaultScrapeClassWithRelabelings.golden") -} - -func TestPodMonitorWithNonDefaultScrapeClassRelabelings(t *testing.T) { - prometheus := defaultPrometheus() - podMonitor := defaultPodMonitor() - sc := monitoringv1.ScrapeClass{ - Name: "test-extra-relabelings-scrape-class", - Relabelings: []*monitoringv1.RelabelConfig{ - { - Action: "replace", - SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_pod_node_name"}, - TargetLabel: "node", - }, - }, - } - - prometheus.Spec.ScrapeClasses = append(prometheus.Spec.ScrapeClasses, sc) - podMonitor.Spec.ScrapeClassName = ptr.To(sc.Name) - cg := mustNewConfigGenerator(t, prometheus) - - cfg, err := cg.GenerateServerConfiguration( - context.Background(), - prometheus.Spec.EvaluationInterval, - prometheus.Spec.QueryLogFile, - prometheus.Spec.RuleSelector, - prometheus.Spec.Exemplars, - prometheus.Spec.TSDB, - prometheus.Spec.Alerting, - prometheus.Spec.RemoteRead, - nil, - map[string]*monitoringv1.PodMonitor{"monitor": podMonitor}, - nil, - nil, - &assets.Store{}, - nil, - nil, - nil, - nil, - ) - require.NoError(t, err) - golden.Assert(t, string(cfg), "podMonitorObjectWithNonDefaultScrapeClassWithRelabelings.golden") -}