diff --git a/tests/e2e-long-running/tempostack-retention-global/00-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/00-assert.yaml new file mode 100644 index 000000000..afa1f9c34 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/00-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio +status: + readyReplicas: 1 diff --git a/tests/e2e-long-running/tempostack-retention-global/00-install-storage.yaml b/tests/e2e-long-running/tempostack-retention-global/00-install-storage.yaml new file mode 100644 index 000000000..d85862e72 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/00-install-storage.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: minio + name: minio +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio +spec: + selector: + matchLabels: + app.kubernetes.io/name: minio + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/name: minio + spec: + containers: + - command: + - /bin/sh + - -c + - | + mkdir -p /storage/tempo && \ + minio server /storage + env: + - name: MINIO_ACCESS_KEY + value: tempo + - name: MINIO_SECRET_KEY + value: supersecret + image: quay.io/minio/minio:latest + name: minio + ports: + - containerPort: 9000 + volumeMounts: + - mountPath: /storage + name: storage + volumes: + - name: storage + persistentVolumeClaim: + claimName: minio +--- +apiVersion: v1 +kind: Service +metadata: + name: minio +spec: + ports: + - port: 9000 + protocol: TCP + targetPort: 9000 + selector: + app.kubernetes.io/name: minio + type: ClusterIP +--- +apiVersion: v1 +kind: Secret +metadata: + name: minio +stringData: + endpoint: http://minio:9000 + bucket: tempo + access_key_id: tempo + access_key_secret: supersecret +type: Opaque diff --git a/tests/e2e-long-running/tempostack-retention-global/01-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/01-assert.yaml new file mode 100644 index 000000000..5907b1e13 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/01-assert.yaml @@ -0,0 +1,371 @@ +apiVersion: tempo.grafana.com/v1alpha1 +kind: TempoStack +metadata: + name: global +# +# Service Accounts +# +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tempo-global + labels: + app.kubernetes.io/component: serviceaccount + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +# +# Deployments +# +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tempo-global-query-frontend + labels: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +spec: + selector: + matchLabels: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +status: + readyReplicas: 1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tempo-global-distributor + labels: + app.kubernetes.io/component: distributor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: distributor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +status: + readyReplicas: 1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tempo-global-querier + labels: + app.kubernetes.io/component: querier + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +spec: + selector: + matchLabels: + app.kubernetes.io/component: querier + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +status: + readyReplicas: 1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tempo-global-compactor + labels: + app.kubernetes.io/component: compactor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +spec: + selector: + matchLabels: + app.kubernetes.io/component: compactor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +status: + readyReplicas: 1 +# +# StatefulSets +# +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: tempo-global-ingester + labels: + app.kubernetes.io/component: ingester + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +spec: + selector: + matchLabels: + app.kubernetes.io/component: ingester + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +status: + readyReplicas: 1 +# +# Services +# +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: compactor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-compactor +spec: + ports: + - name: http-memberlist + port: 7946 + protocol: TCP + targetPort: http-memberlist + - name: http + port: 3200 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/component: compactor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: distributor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-distributor +spec: + ports: + - name: otlp-http + port: 4318 + protocol: TCP + targetPort: otlp-http + - name: otlp-grpc + port: 4317 + protocol: TCP + targetPort: otlp-grpc + - name: http + port: 3200 + protocol: TCP + targetPort: http + - name: thrift-http + port: 14268 + protocol: TCP + targetPort: thrift-http + - name: thrift-compact + port: 6831 + protocol: UDP + targetPort: thrift-compact + - name: thrift-binary + port: 6832 + protocol: UDP + targetPort: thrift-binary + - name: jaeger-grpc + port: 14250 + protocol: TCP + targetPort: jaeger-grpc + - name: http-zipkin + port: 9411 + protocol: TCP + targetPort: http-zipkin + selector: + app.kubernetes.io/component: distributor + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: gossip-ring + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-gossip-ring +spec: + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: http-memberlist + port: 7946 + protocol: TCP + targetPort: http-memberlist + selector: + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + tempo-gossip-member: "true" +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: ingester + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-ingester +spec: + ports: + - name: http + port: 3200 + protocol: TCP + targetPort: http + - name: grpc + port: 9095 + protocol: TCP + targetPort: grpc + selector: + app.kubernetes.io/component: ingester + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: querier + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-querier +spec: + ports: + - name: http-memberlist + port: 7946 + protocol: TCP + targetPort: http-memberlist + - name: http + port: 3200 + protocol: TCP + targetPort: http + - name: grpc + port: 9095 + protocol: TCP + targetPort: grpc + selector: + app.kubernetes.io/component: querier + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-query-frontend +spec: + ports: + - name: http + port: 3200 + protocol: TCP + targetPort: http + - name: grpc + port: 9095 + protocol: TCP + targetPort: grpc + - name: jaeger-grpc + port: 16685 + protocol: TCP + targetPort: jaeger-grpc + - name: jaeger-ui + port: 16686 + protocol: TCP + targetPort: jaeger-ui + - name: jaeger-metrics + port: 16687 + protocol: TCP + targetPort: jaeger-metrics + selector: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: query-frontend-discovery + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-query-frontend-discovery +spec: + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: http + port: 3200 + protocol: TCP + targetPort: http + - name: grpc + port: 9095 + protocol: TCP + targetPort: grpc + - name: grpclb + port: 9096 + protocol: TCP + targetPort: grpclb + - name: jaeger-grpc + port: 16685 + protocol: TCP + targetPort: jaeger-grpc + - name: jaeger-ui + port: 16686 + protocol: TCP + targetPort: jaeger-ui + - name: jaeger-metrics + port: 16687 + protocol: TCP + targetPort: jaeger-metrics + selector: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator +# +# Ingresses +# +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/component: query-frontend + app.kubernetes.io/instance: global + app.kubernetes.io/managed-by: tempo-operator + app.kubernetes.io/name: tempo + name: tempo-global-query-frontend +spec: + defaultBackend: + service: + name: tempo-global-query-frontend + port: + name: jaeger-ui diff --git a/tests/e2e-long-running/tempostack-retention-global/01-install.yaml b/tests/e2e-long-running/tempostack-retention-global/01-install.yaml new file mode 100644 index 000000000..983ffe53c --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/01-install.yaml @@ -0,0 +1,24 @@ +apiVersion: tempo.grafana.com/v1alpha1 +kind: TempoStack +metadata: + name: global +spec: + storage: + secret: + name: minio + type: s3 + storageSize: 200M + resources: + total: + limits: + memory: 6Gi + cpu: 2000m + retention: + global: + traces: "32m" + template: + queryFrontend: + jaegerQuery: + enabled: true + ingress: + type: ingress diff --git a/tests/e2e-long-running/tempostack-retention-global/03-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/03-assert.yaml new file mode 100644 index 000000000..3f7323066 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/03-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: generate-traces +status: + conditions: + - status: "True" + type: Complete diff --git a/tests/e2e-long-running/tempostack-retention-global/03-generate-traces.yaml b/tests/e2e-long-running/tempostack-retention-global/03-generate-traces.yaml new file mode 100644 index 000000000..a1938be85 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/03-generate-traces.yaml @@ -0,0 +1,17 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: generate-traces +spec: + template: + spec: + containers: + - name: telemetrygen + image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:v0.92.0 + args: + - traces + - --otlp-endpoint=tempo-global-distributor:4317 + - --otlp-insecure + - --traces=10 + restartPolicy: Never + backoffLimit: 4 diff --git a/tests/e2e-long-running/tempostack-retention-global/04-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/04-assert.yaml new file mode 100644 index 000000000..ab9e98db3 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/04-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-jaeger +status: + conditions: + - status: "True" + type: Complete diff --git a/tests/e2e-long-running/tempostack-retention-global/04-verify-traces-jaeger.yaml b/tests/e2e-long-running/tempostack-retention-global/04-verify-traces-jaeger.yaml new file mode 100644 index 000000000..2674e4d7e --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/04-verify-traces-jaeger.yaml @@ -0,0 +1,36 @@ +# Simulate Jaeger Query API requests. +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-jaeger +spec: + template: + spec: + containers: + - name: verify-traces-jaeger + image: ghcr.io/grafana/tempo-operator/test-utils:main + command: + - /bin/bash + - -eux + - -c + args: + - | + # The query frontend must be accessible via HTTP (no mTLS) to enable connections from Grafana + curl \ + -v -G \ + http://tempo-global-query-frontend:3200/api/search \ + --data-urlencode "q={}" \ + | tee /tmp/tempo.out + num_traces=$(jq ".traces | length" /tmp/tempo.out) + if [[ "$num_traces" -ne 10 ]]; then + echo && echo "The Tempo API returned $num_traces instead of 10 traces." + exit 1 + fi + + curl -v -G http://tempo-global-query-frontend:16686/api/traces --data-urlencode "service=telemetrygen" | tee /tmp/jaeger.out + num_traces=$(jq ".data | length" /tmp/jaeger.out) + if [[ "$num_traces" -ne 10 ]]; then + echo && echo "The Jaeger API returned $num_traces instead of 10 traces." + exit 1 + fi + restartPolicy: Never diff --git a/tests/e2e-long-running/tempostack-retention-global/05-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/05-assert.yaml new file mode 100644 index 000000000..7eec01bfb --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/05-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-grafana +status: + conditions: + - status: "True" + type: Complete diff --git a/tests/e2e-long-running/tempostack-retention-global/05-verify-traces-grafana.yaml b/tests/e2e-long-running/tempostack-retention-global/05-verify-traces-grafana.yaml new file mode 100644 index 000000000..43f70521b --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/05-verify-traces-grafana.yaml @@ -0,0 +1,46 @@ +# Simulate Grafana Dashboard API requests. +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-grafana +spec: + template: + spec: + containers: + - name: verify-traces-grafana + image: ghcr.io/grafana/tempo-operator/test-utils:main + command: + - /bin/bash + - -eux + - -c + args: + - | + # Get the current Unix timestamp for "end" time, which is the current time + end_time=$(date -u +%s) + + # Calculate "start" time by subtracting 24 hours (86400 seconds) from the "end" time + start_time=$((end_time - 86400)) + + # The query frontend must be accessible via HTTP (no mTLS) to enable connections from Grafana + + # Run the curl command and capture the HTTP status code and output in a file + response_file=$(mktemp) + http_status=$(curl -s -o "$response_file" -w "%{http_code}" "http://tempo-global-query-frontend:3200/api/search?tags=%20service.name%3D%22telemetrygen%22%20name%3D%22okey-dokey%22&limit=20&start=$start_time&end=$end_time") + + # Check the HTTP status code to detect API call failures + if [[ "$http_status" -ne 200 ]]; then + echo "API call failed with HTTP status code $http_status." + exit 1 + fi + + # Parse the JSON output from the file and check if the "traces" array is empty + output=$(cat "$response_file" | jq .) + + if [[ "$(echo "$output" | jq -r '.traces | length')" -eq 0 ]]; then + echo "The Tempo API returned 0 Traces." + exit 1 + else + echo "Traces found." + exit 0 + fi + restartPolicy: Never diff --git a/tests/e2e-long-running/tempostack-retention-global/chainsaw-test.yaml b/tests/e2e-long-running/tempostack-retention-global/chainsaw-test.yaml new file mode 100755 index 000000000..c69d46f99 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/chainsaw-test.yaml @@ -0,0 +1,59 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: tempostack-retention-global +spec: + steps: + - name: step-00 + try: + - apply: + file: 00-install-storage.yaml + - assert: + file: 00-assert.yaml + - name: step-01 + try: + - apply: + file: 01-install.yaml + - assert: + file: 01-assert.yaml + - name: step-02 + try: + - script: + timeout: 5m + content: kubectl get --namespace $NAMESPACE tempo global -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' | grep True + - name: step-03 + try: + - apply: + file: 03-generate-traces.yaml + - assert: + file: 03-assert.yaml + - name: step-04 + try: + - apply: + file: 04-verify-traces-jaeger.yaml + - assert: + file: 04-assert.yaml + - name: step-05 + try: + - apply: + file: 05-verify-traces-grafana.yaml + - assert: + file: 05-assert.yaml + - name: Wait for the TempoStack global retention time period + try: + - sleep: + duration: 45m + - name: The number of traces must be 0 post the retention period + try: + - apply: + file: verify-traces-jaeger-ret.yaml + - assert: + file: verify-traces-jaeger-ret-assert.yaml + - name: The number of traces must be 0 post the retention period + try: + - apply: + file: verify-traces-grafana-ret.yaml + - assert: + file: verify-traces-grafana-ret-assert.yaml diff --git a/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret-assert.yaml new file mode 100644 index 000000000..f6d3a4998 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-grafana-ret +status: + conditions: + - status: "True" + type: Complete diff --git a/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret.yaml b/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret.yaml new file mode 100644 index 000000000..332447033 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/verify-traces-grafana-ret.yaml @@ -0,0 +1,46 @@ +# Simulate Grafana Dashboard API requests. +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-grafana-ret +spec: + template: + spec: + containers: + - name: verify-traces-grafana + image: ghcr.io/grafana/tempo-operator/test-utils:main + command: + - /bin/bash + - -eux + - -c + args: + - | + # Get the current Unix timestamp for "end" time, which is the current time + end_time=$(date -u +%s) + + # Calculate "start" time by subtracting 24 hours (86400 seconds) from the "end" time + start_time=$((end_time - 86400)) + + # The query frontend must be accessible via HTTP (no mTLS) to enable connections from Grafana + + # Run the curl command and capture the HTTP status code and output in a file + response_file=$(mktemp) + http_status=$(curl -s -o "$response_file" -w "%{http_code}" "http://tempo-global-query-frontend:3200/api/search?tags=%20service.name%3D%22telemetrygen%22%20name%3D%22okey-dokey%22&limit=20&start=$start_time&end=$end_time") + + # Check the HTTP status code to detect API call failures + if [[ "$http_status" -ne 200 ]]; then + echo "API call failed with HTTP status code $http_status." + exit 1 + fi + + # Parse the JSON output from the file and check if the "traces" array is empty + output=$(cat "$response_file" | jq .) + + if [[ "$(echo "$output" | jq -r '.traces | length')" -eq 0 ]]; then + echo "The Tempo API returned 0 Traces." + exit 0 + else + echo "Traces found." + exit 1 + fi + restartPolicy: Never diff --git a/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret-assert.yaml b/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret-assert.yaml new file mode 100644 index 000000000..19895c419 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-jaeger-ret +status: + conditions: + - status: "True" + type: Complete diff --git a/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret.yaml b/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret.yaml new file mode 100644 index 000000000..c573e2609 --- /dev/null +++ b/tests/e2e-long-running/tempostack-retention-global/verify-traces-jaeger-ret.yaml @@ -0,0 +1,36 @@ +# Simulate Jaeger Query API requests. +apiVersion: batch/v1 +kind: Job +metadata: + name: verify-traces-jaeger-ret +spec: + template: + spec: + containers: + - name: verify-traces-jaeger + image: ghcr.io/grafana/tempo-operator/test-utils:main + command: + - /bin/bash + - -eux + - -c + args: + - | + # The query frontend must be accessible via HTTP (no mTLS) to enable connections from Grafana + curl \ + -v -G \ + http://tempo-global-query-frontend:3200/api/search \ + --data-urlencode "q={}" \ + | tee /tmp/tempo.out + num_traces=$(jq ".traces | length" /tmp/tempo.out) + if [[ "$num_traces" -ne 0 ]]; then + echo && echo "The Tempo API returned $num_traces instead of 0 traces." + exit 1 + fi + + curl -v -G http://tempo-global-query-frontend:16686/api/traces --data-urlencode "service=telemetrygen" | tee /tmp/jaeger.out + num_traces=$(jq ".data | length" /tmp/jaeger.out) + if [[ "$num_traces" -ne 0 ]]; then + echo && echo "The Jaeger API returned $num_traces instead of 0 traces." + exit 1 + fi + restartPolicy: Never