diff --git a/chart/values.schema.json b/chart/values.schema.json index cadc5e9d75de3..3ad6a95aa3f33 100644 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -9511,7 +9511,7 @@ "tracesEnabled": { "description": "Send Airflow traces to the OTel Collector. Sets `[traces] otel_on` in the rendered Airflow config and deploys the collector when either `tracesEnabled` or `metricsEnabled` is true.", "type": "boolean", - "default": true + "default": false }, "metricsEnabled": { "description": "Send Airflow metrics to the OTel Collector. Sets `[metrics] otel_on` in the rendered Airflow config and forces `[metrics] statsd_on` to False because Airflow can only export metrics to one backend at a time.", diff --git a/chart/values.yaml b/chart/values.yaml index 1fe6b159a29d0..c5e2446c20618 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -3504,7 +3504,7 @@ statsd: # OpenTelemetry Collector settings otelCollector: # Send Airflow traces to the OTel Collector (sets [traces] otel_on). - tracesEnabled: true + tracesEnabled: false # Send Airflow metrics to the OTel Collector (sets [metrics] otel_on and disables statsd). metricsEnabled: false diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py index 8fa844d781fee..1e23757276311 100644 --- a/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py +++ b/helm-tests/tests/helm_tests/airflow_aux/test_airflow_common.py @@ -419,10 +419,6 @@ def test_should_disable_some_variables(self): "AIRFLOW__CORE__FERNET_KEY", "AIRFLOW_CONN_AIRFLOW_DB", "AIRFLOW__CELERY__BROKER_URL", - "OTEL_SERVICE_NAME", - "OTEL_EXPORTER_OTLP_PROTOCOL", - "OTEL_TRACES_EXPORTER", - "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", ] expected_vars_in_worker = ["DUMB_INIT_SETSID"] + expected_vars for doc in docs: @@ -453,10 +449,6 @@ def test_have_all_variables(self): "AIRFLOW__API__SECRET_KEY", "AIRFLOW__API_AUTH__JWT_SECRET", "AIRFLOW__CELERY__BROKER_URL", - "OTEL_SERVICE_NAME", - "OTEL_EXPORTER_OTLP_PROTOCOL", - "OTEL_TRACES_EXPORTER", - "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", ] expected_vars_no_jwt = [ "AIRFLOW_HOME", @@ -465,10 +457,6 @@ def test_have_all_variables(self): "AIRFLOW_CONN_AIRFLOW_DB", "AIRFLOW__API__SECRET_KEY", "AIRFLOW__CELERY__BROKER_URL", - "OTEL_SERVICE_NAME", - "OTEL_EXPORTER_OTLP_PROTOCOL", - "OTEL_TRACES_EXPORTER", - "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", ] for doc in docs: component = doc["metadata"]["labels"]["component"] diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py index 5b073ce1e59ab..f6f3c31952b7e 100644 --- a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py +++ b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py @@ -33,7 +33,6 @@ ("ServiceAccount", "test-basic-airflow-redis"), ("ServiceAccount", "test-basic-airflow-scheduler"), ("ServiceAccount", "test-basic-airflow-statsd"), - ("ServiceAccount", "test-basic-airflow-otel-collector"), ("ServiceAccount", "test-basic-airflow-triggerer"), ("ServiceAccount", "test-basic-airflow-worker"), ("Secret", "test-basic-airflow-metadata"), @@ -43,21 +42,18 @@ ("Secret", "test-basic-postgresql"), ("ConfigMap", "test-basic-airflow-config"), ("ConfigMap", "test-basic-airflow-statsd"), - ("ConfigMap", "test-basic-airflow-otel-collector"), ("Role", "test-basic-airflow-pod-launcher-role"), ("Role", "test-basic-airflow-pod-log-reader-role"), ("RoleBinding", "test-basic-airflow-pod-launcher-rolebinding"), ("RoleBinding", "test-basic-airflow-pod-log-reader-rolebinding"), ("Service", "test-basic-airflow-redis"), ("Service", "test-basic-airflow-statsd"), - ("Service", "test-basic-airflow-otel-collector"), ("Service", "test-basic-airflow-triggerer"), ("Service", "test-basic-airflow-worker"), ("Service", "test-basic-postgresql"), ("Service", "test-basic-postgresql-hl"), ("Deployment", "test-basic-airflow-scheduler"), ("Deployment", "test-basic-airflow-statsd"), - ("Deployment", "test-basic-airflow-otel-collector"), ("StatefulSet", "test-basic-airflow-redis"), ("StatefulSet", "test-basic-airflow-worker"), ("StatefulSet", "test-basic-airflow-triggerer"), @@ -134,7 +130,6 @@ def test_basic_deployments(self, version): ("ServiceAccount", "test-basic-redis"), ("ServiceAccount", "test-basic-scheduler"), ("ServiceAccount", "test-basic-statsd"), - ("ServiceAccount", "test-basic-otel-collector"), ("ServiceAccount", "test-basic-triggerer"), ("ServiceAccount", "test-basic-worker"), ("Secret", "test-basic-metadata"), @@ -144,7 +139,6 @@ def test_basic_deployments(self, version): ("Secret", "test-basic-redis-password"), ("ConfigMap", "test-basic-config"), ("ConfigMap", "test-basic-statsd"), - ("ConfigMap", "test-basic-otel-collector"), ("Role", "test-basic-pod-launcher-role"), ("Role", "test-basic-pod-log-reader-role"), ("RoleBinding", "test-basic-pod-launcher-rolebinding"), @@ -153,12 +147,10 @@ def test_basic_deployments(self, version): ("Service", "test-basic-postgresql"), ("Service", "test-basic-redis"), ("Service", "test-basic-statsd"), - ("Service", "test-basic-otel-collector"), ("Service", "test-basic-triggerer"), ("Service", "test-basic-worker"), ("Deployment", "test-basic-scheduler"), ("Deployment", "test-basic-statsd"), - ("Deployment", "test-basic-otel-collector"), ("StatefulSet", "test-basic-triggerer"), ("StatefulSet", "test-basic-postgresql"), ("StatefulSet", "test-basic-redis"), @@ -340,6 +332,7 @@ def test_network_policies_are_valid(self, airflow_version, executor): "executor": executor, "flower": {"enabled": True}, "pgbouncer": {"enabled": True}, + "otelCollector": {"tracesEnabled": True}, }, version=airflow_version, ), diff --git a/helm-tests/tests/helm_tests/otel_collector/test_labels_deployment.py b/helm-tests/tests/helm_tests/otel_collector/test_labels_deployment.py index 40d2e7b33d677..2c4ff0fae430a 100644 --- a/helm-tests/tests/helm_tests/otel_collector/test_labels_deployment.py +++ b/helm-tests/tests/helm_tests/otel_collector/test_labels_deployment.py @@ -26,7 +26,6 @@ class TestOtelCollectorDeployment: TEMPLATE_FILE = "templates/otel-collector/otel-collector-deployment.yaml" def test_should_add_global_labels_to_metadata(self): - """Test adding only .Values.labels to metadata.labels.""" docs = render_chart( values={ "otelCollector": {"tracesEnabled": True}, @@ -39,7 +38,6 @@ def test_should_add_global_labels_to_metadata(self): assert jmespath.search("metadata.labels", docs[0])["test_global_label"] == "test_global_label_value" def test_should_add_global_labels_to_pod_template(self): - """Test adding only .Values.labels to spec.template.metadata.labels.""" docs = render_chart( values={ "otelCollector": {"tracesEnabled": True}, @@ -55,7 +53,6 @@ def test_should_add_global_labels_to_pod_template(self): ) def test_should_add_component_specific_labels_to_pod_template(self): - """Test adding only .Values.otelCollector.labels to spec.template.metadata.labels.""" docs = render_chart( values={ "otelCollector": { @@ -73,7 +70,6 @@ def test_should_add_component_specific_labels_to_pod_template(self): ) def test_should_merge_global_and_component_specific_labels_in_pod_template(self): - """Test adding both .Values.labels and .Values.otelCollector.labels to spec.template.metadata.labels.""" docs = render_chart( values={ "otelCollector": { @@ -97,7 +93,6 @@ def test_should_merge_global_and_component_specific_labels_in_pod_template(self) ) def test_component_specific_labels_should_override_global_labels(self): - """Test that component-specific labels take precedence over global labels with the same key.""" docs = render_chart( values={ "otelCollector": { diff --git a/helm-tests/tests/helm_tests/otel_collector/test_labels_networkpolicy.py b/helm-tests/tests/helm_tests/otel_collector/test_labels_networkpolicy.py index 57595157cc1cb..e156fe48e6c9e 100644 --- a/helm-tests/tests/helm_tests/otel_collector/test_labels_networkpolicy.py +++ b/helm-tests/tests/helm_tests/otel_collector/test_labels_networkpolicy.py @@ -26,7 +26,6 @@ class TestOtelCollectorNetworkPolicy: TEMPLATE_FILE = "templates/otel-collector/otel-collector-networkpolicy.yaml" def test_should_add_global_labels(self): - """Test adding only .Values.labels.""" docs = render_chart( values={ "otelCollector": {"tracesEnabled": True}, @@ -40,7 +39,6 @@ def test_should_add_global_labels(self): assert jmespath.search("metadata.labels", docs[0])["test_global_label"] == "test_global_label_value" def test_should_add_component_specific_labels(self): - """Test adding only .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -59,7 +57,6 @@ def test_should_add_component_specific_labels(self): ) def test_should_merge_global_and_component_specific_labels(self): - """Test adding both .Values.labels and .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -81,7 +78,6 @@ def test_should_merge_global_and_component_specific_labels(self): ) def test_component_specific_labels_should_override_global_labels(self): - """Test that component-specific labels take precedence over global labels with the same key.""" docs = render_chart( values={ "otelCollector": { diff --git a/helm-tests/tests/helm_tests/otel_collector/test_labels_service.py b/helm-tests/tests/helm_tests/otel_collector/test_labels_service.py index f92abc10205e6..86b0023d80140 100644 --- a/helm-tests/tests/helm_tests/otel_collector/test_labels_service.py +++ b/helm-tests/tests/helm_tests/otel_collector/test_labels_service.py @@ -26,7 +26,6 @@ class TestOtelCollectorService: TEMPLATE_FILE = "templates/otel-collector/otel-collector-service.yaml" def test_should_add_global_labels(self): - """Test adding only .Values.labels.""" docs = render_chart( values={ "otelCollector": {"tracesEnabled": True}, @@ -39,7 +38,6 @@ def test_should_add_global_labels(self): assert jmespath.search("metadata.labels", docs[0])["test_global_label"] == "test_global_label_value" def test_should_add_component_specific_labels(self): - """Test adding only .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -57,7 +55,6 @@ def test_should_add_component_specific_labels(self): ) def test_should_merge_global_and_component_specific_labels(self): - """Test adding both .Values.labels and .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -78,7 +75,6 @@ def test_should_merge_global_and_component_specific_labels(self): ) def test_component_specific_labels_should_override_global_labels(self): - """Test that component-specific labels take precedence over global labels with the same key.""" docs = render_chart( values={ "otelCollector": { diff --git a/helm-tests/tests/helm_tests/otel_collector/test_labels_serviceaccount.py b/helm-tests/tests/helm_tests/otel_collector/test_labels_serviceaccount.py index c899670766fc8..9775676bfd616 100644 --- a/helm-tests/tests/helm_tests/otel_collector/test_labels_serviceaccount.py +++ b/helm-tests/tests/helm_tests/otel_collector/test_labels_serviceaccount.py @@ -26,7 +26,6 @@ class TestOtelCollectorServiceAccount: TEMPLATE_FILE = "templates/otel-collector/otel-collector-serviceaccount.yaml" def test_should_add_global_labels(self): - """Test adding only .Values.labels.""" docs = render_chart( values={ "otelCollector": {"tracesEnabled": True}, @@ -39,7 +38,6 @@ def test_should_add_global_labels(self): assert jmespath.search("metadata.labels", docs[0])["test_global_label"] == "test_global_label_value" def test_should_add_component_specific_labels(self): - """Test adding only .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -57,7 +55,6 @@ def test_should_add_component_specific_labels(self): ) def test_should_merge_global_and_component_specific_labels(self): - """Test adding both .Values.labels and .Values.otelCollector.labels.""" docs = render_chart( values={ "otelCollector": { @@ -78,7 +75,6 @@ def test_should_merge_global_and_component_specific_labels(self): ) def test_component_specific_labels_should_override_global_labels(self): - """Test that component-specific labels take precedence over global labels with the same key.""" docs = render_chart( values={ "otelCollector": { diff --git a/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py b/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py index 70ef3aec2fd47..b7d84347fb931 100644 --- a/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py +++ b/helm-tests/tests/helm_tests/otel_collector/test_otel_collector.py @@ -22,16 +22,12 @@ from chart_utils.helm_template_generator import render_chart OTEL_TEMPLATES = [ - "templates/configmaps/otel-collector-configmap.yaml", - "templates/otel-collector/otel-collector-deployment.yaml", - "templates/otel-collector/otel-collector-service.yaml", - "templates/otel-collector/otel-collector-serviceaccount.yaml", + (CONFIGMAP_TEMPLATE := "templates/configmaps/otel-collector-configmap.yaml"), + (DEPLOYMENT_TEMPLATE := "templates/otel-collector/otel-collector-deployment.yaml"), + (SERVICE_TEMPLATE := "templates/otel-collector/otel-collector-service.yaml"), + (SERVICE_ACCOUNT_TEMPLATE := "templates/otel-collector/otel-collector-serviceaccount.yaml"), ] -DEPLOYMENT_TEMPLATE = "templates/otel-collector/otel-collector-deployment.yaml" -SERVICE_TEMPLATE = "templates/otel-collector/otel-collector-service.yaml" -CONFIGMAP_TEMPLATE = "templates/configmaps/otel-collector-configmap.yaml" -SERVICE_ACCOUNT_TEMPLATE = "templates/otel-collector/otel-collector-serviceaccount.yaml" AIRFLOW_CONFIGMAP_TEMPLATE = "templates/configmaps/configmap.yaml" AIRFLOW_POD_TEMPLATES = [ @@ -43,50 +39,50 @@ ] -def _env_names(doc): - """Return the list of env var names from the first container of a pod spec.""" - env = jmespath.search("spec.template.spec.containers[0].env", doc) or [] - return [e["name"] for e in env] - +class TestOtelCollectorCommon: + def test_standard_naming(self): + docs = render_chart( + name="test-basic", + values={"useStandardNaming": True, "otelCollector": {"tracesEnabled": True}}, + show_only=OTEL_TEMPLATES, + ) -def _env_value(doc, name): - env = jmespath.search("spec.template.spec.containers[0].env", doc) or [] - for entry in env: - if entry["name"] == name: - return entry.get("value") - return None + assert len(docs) == 4 + assert jmespath.search("[*].[kind, metadata.name]", docs) == [ + ["ConfigMap", "test-basic-airflow-otel-collector"], + ["Deployment", "test-basic-airflow-otel-collector"], + ["Service", "test-basic-airflow-otel-collector"], + ["ServiceAccount", "test-basic-airflow-otel-collector"], + ] class TestOtelCollectorResourceGating: - """Resource emission depends on tracesEnabled / metricsEnabled.""" - - def test_default_renders_all_resources(self): + def test_renders_default(self): docs = render_chart(show_only=OTEL_TEMPLATES) - kinds = {d["kind"] for d in docs} - assert kinds == {"ConfigMap", "Deployment", "Service", "ServiceAccount"} + assert len(docs) == 0 - def test_both_flags_disabled_renders_nothing(self): + @pytest.mark.parametrize("otel_field", ["tracesEnabled", "metricsEnabled"]) + def test_should_render(self, otel_field): + docs = render_chart(values={"otelCollector": {otel_field: True}}, show_only=OTEL_TEMPLATES) + + assert len(docs) == 4 + assert jmespath.search("[*].kind", docs) == ["ConfigMap", "Deployment", "Service", "ServiceAccount"] + + def test_should_not_render(self): docs = render_chart( values={"otelCollector": {"tracesEnabled": False, "metricsEnabled": False}}, show_only=OTEL_TEMPLATES, ) - assert docs == [] - def test_metrics_only_renders_all_resources(self): - docs = render_chart( - values={"otelCollector": {"tracesEnabled": False, "metricsEnabled": True}}, - show_only=OTEL_TEMPLATES, - ) - kinds = {d["kind"] for d in docs} - assert kinds == {"ConfigMap", "Deployment", "Service", "ServiceAccount"} + assert docs == [] class TestOtelCollectorDefaultConfig: """The chart-rendered config.yml has the default config for the otel-collector.""" @staticmethod - def _get_config_yml(values=None): - docs = render_chart(values=values or {}, show_only=[CONFIGMAP_TEMPLATE]) + def _get_config_yml(): + docs = render_chart(values={"otelCollector": {"tracesEnabled": True}}, show_only=[CONFIGMAP_TEMPLATE]) config_yml = jmespath.search('data."config.yml"', docs[0]) return yaml.safe_load(config_yml) @@ -114,7 +110,7 @@ def test_default_pipelines_only_export_to_logging(self): class TestOtelCollectorConfigOverride: """`otelCollector.config` replaces the default and supports `tpl`.""" - def test_override_replaces_default(self): + def test_override_default(self): override = ( "receivers:\n" " otlp:\n" @@ -130,16 +126,15 @@ def test_override_replaces_default(self): " exporters: [logging]\n" ) docs = render_chart( - values={"otelCollector": {"config": override}}, + values={"otelCollector": {"tracesEnabled": True, "config": override}}, show_only=[CONFIGMAP_TEMPLATE], ) rendered = yaml.safe_load(jmespath.search('data."config.yml"', docs[0])) - # The value is '0.0.0.0:9999' instead of the default '0.0.0.0:4318'. assert rendered["receivers"]["otlp"]["protocols"]["http"]["endpoint"] == "0.0.0.0:9999" # default `health_check` extension is gone in the override assert "extensions" not in rendered - def test_tpl_resolves_chart_values(self): + def test_override_default_tpl(self): override = ( "receivers:\n" " otlp:\n" @@ -148,7 +143,7 @@ def test_tpl_resolves_chart_values(self): " endpoint: 0.0.0.0:{{ .Values.ports.otelCollectorOtlpHttp }}\n" ) docs = render_chart( - values={"otelCollector": {"config": override}}, + values={"otelCollector": {"tracesEnabled": True, "config": override}}, show_only=[CONFIGMAP_TEMPLATE], ) rendered = yaml.safe_load(jmespath.search('data."config.yml"', docs[0])) @@ -156,10 +151,10 @@ def test_tpl_resolves_chart_values(self): class TestOtelCollectorDeployment: - """Deployment-level configurability.""" - def test_default_args(self): - docs = render_chart(show_only=[DEPLOYMENT_TEMPLATE]) + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[DEPLOYMENT_TEMPLATE] + ) assert jmespath.search("spec.template.spec.containers[0].args", docs[0]) == [ "--config=/etc/otel-collector/config.yml" ] @@ -167,88 +162,136 @@ def test_default_args(self): def test_args_override(self): custom = ["--config=/etc/otel-collector/config.yml", "--feature-gates=+foo"] docs = render_chart( - values={"otelCollector": {"args": custom}}, + values={"otelCollector": {"tracesEnabled": True, "args": custom}}, show_only=[DEPLOYMENT_TEMPLATE], ) assert jmespath.search("spec.template.spec.containers[0].args", docs[0]) == custom def test_default_probes(self): - docs = render_chart(show_only=[DEPLOYMENT_TEMPLATE]) - liveness = jmespath.search("spec.template.spec.containers[0].livenessProbe", docs[0]) - readiness = jmespath.search("spec.template.spec.containers[0].readinessProbe", docs[0]) - assert liveness["initialDelaySeconds"] == 10 - assert liveness["periodSeconds"] == 15 - assert liveness["httpGet"] == {"path": "/", "port": 13133} - assert readiness["initialDelaySeconds"] == 10 - assert readiness["periodSeconds"] == 15 + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[DEPLOYMENT_TEMPLATE] + ) + + assert jmespath.search("spec.template.spec.containers[0].livenessProbe", docs[0]) == { + "initialDelaySeconds": 10, + "periodSeconds": 15, + "httpGet": {"path": "/", "port": 13133}, + } + + assert jmespath.search("spec.template.spec.containers[0].readinessProbe", docs[0]) == { + "initialDelaySeconds": 10, + "periodSeconds": 15, + "httpGet": {"path": "/", "port": 13133}, + } def test_probe_overrides(self): docs = render_chart( values={ "otelCollector": { + "tracesEnabled": True, "livenessProbe": {"initialDelaySeconds": 30, "periodSeconds": 45}, "readinessProbe": {"initialDelaySeconds": 5, "periodSeconds": 7}, } }, show_only=[DEPLOYMENT_TEMPLATE], ) - liveness = jmespath.search("spec.template.spec.containers[0].livenessProbe", docs[0]) - readiness = jmespath.search("spec.template.spec.containers[0].readinessProbe", docs[0]) - assert liveness["initialDelaySeconds"] == 30 - assert liveness["periodSeconds"] == 45 - assert readiness["initialDelaySeconds"] == 5 - assert readiness["periodSeconds"] == 7 + + assert jmespath.search("spec.template.spec.containers[0].livenessProbe", docs[0]) == { + "initialDelaySeconds": 30, + "periodSeconds": 45, + "httpGet": {"path": "/", "port": 13133}, + } + + assert jmespath.search("spec.template.spec.containers[0].readinessProbe", docs[0]) == { + "initialDelaySeconds": 5, + "periodSeconds": 7, + "httpGet": {"path": "/", "port": 13133}, + } def test_resources_default_empty(self): - docs = render_chart(show_only=[DEPLOYMENT_TEMPLATE]) + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[DEPLOYMENT_TEMPLATE] + ) assert jmespath.search("spec.template.spec.containers[0].resources", docs[0]) == {} def test_resources_configurable(self): docs = render_chart( values={ "otelCollector": { + "tracesEnabled": True, "resources": { "limits": {"cpu": "200m", "memory": "256Mi"}, "requests": {"cpu": "100m", "memory": "128Mi"}, - } + }, } }, show_only=[DEPLOYMENT_TEMPLATE], ) - resources = jmespath.search("spec.template.spec.containers[0].resources", docs[0]) - assert resources == { + + assert jmespath.search("spec.template.spec.containers[0].resources", docs[0]) == { "limits": {"cpu": "200m", "memory": "256Mi"}, "requests": {"cpu": "100m", "memory": "128Mi"}, } + def test_termination_grace_period_seconds_default(self): + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[DEPLOYMENT_TEMPLATE] + ) + assert jmespath.search("spec.template.spec.terminationGracePeriodSeconds", docs[0]) == 30 + + def test_termination_grace_period_seconds_override(self): + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True, "terminationGracePeriodSeconds": 1200}}, + show_only=[DEPLOYMENT_TEMPLATE], + ) + assert jmespath.search("spec.template.spec.terminationGracePeriodSeconds", docs[0]) == 1200 + + def test_revision_history_limit_default(self): + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[DEPLOYMENT_TEMPLATE] + ) + assert jmespath.search("spec.revisionHistoryLimit", docs[0]) is None + + def test_revision_history_limit_global_unset(self): + docs = render_chart( + values={"revisionHistoryLimit": None, "otelCollector": {"tracesEnabled": True}}, + show_only=[DEPLOYMENT_TEMPLATE], + ) + + assert jmespath.search("spec.revisionHistoryLimit", docs[0]) is None + + def test_revision_history_limit_global(self): + docs = render_chart( + values={"revisionHistoryLimit": 8, "otelCollector": {"tracesEnabled": True}}, + show_only=[DEPLOYMENT_TEMPLATE], + ) + + assert jmespath.search("spec.revisionHistoryLimit", docs[0]) == 8 + @pytest.mark.parametrize( - ("values", "expected"), + ("local_limit", "global_limit"), [ - ({}, 30), - ({"otelCollector": {"terminationGracePeriodSeconds": 1200}}, 1200), + (8, 10), + (None, 8), + (8, None), ], ) - def test_termination_grace_period_seconds(self, values, expected): - docs = render_chart(values=values, show_only=[DEPLOYMENT_TEMPLATE]) - assert jmespath.search("spec.template.spec.terminationGracePeriodSeconds", docs[0]) == expected + def test_revision_history_limit_overwrite(self, local_limit, global_limit): + docs = render_chart( + values={ + "revisionHistoryLimit": global_limit, + "otelCollector": {"tracesEnabled": True, "revisionHistoryLimit": local_limit}, + }, + show_only=[DEPLOYMENT_TEMPLATE], + ) - @pytest.mark.parametrize( - ("component", "global_", "expected"), - [(8, 10, 8), (10, 8, 10), (8, None, 8), (None, 10, 10), (0, 10, 0), (None, 0, 0)], - ) - def test_revision_history_limit(self, component, global_, expected): - values = {"otelCollector": {}} - if component is not None: - values["otelCollector"]["revisionHistoryLimit"] = component - if global_ is not None: - values["revisionHistoryLimit"] = global_ - docs = render_chart(values=values, show_only=[DEPLOYMENT_TEMPLATE]) - assert jmespath.search("spec.revisionHistoryLimit", docs[0]) == expected + assert jmespath.search("spec.revisionHistoryLimit", docs[0]) == 8 def test_scheduling_constraints(self): docs = render_chart( values={ "otelCollector": { + "tracesEnabled": True, "nodeSelector": {"diskType": "ssd"}, "tolerations": [{"key": "k", "operator": "Equal", "value": "v", "effect": "NoSchedule"}], "affinity": { @@ -288,10 +331,11 @@ def test_security_contexts(self): docs = render_chart( values={ "otelCollector": { + "tracesEnabled": True, "securityContexts": { "pod": {"runAsUser": 2000, "fsGroup": 1000}, "container": {"allowPrivilegeEscalation": False, "readOnlyRootFilesystem": True}, - } + }, } }, show_only=[DEPLOYMENT_TEMPLATE], @@ -309,6 +353,7 @@ def test_annotations_and_pod_annotations(self): docs = render_chart( values={ "otelCollector": { + "tracesEnabled": True, "annotations": {"deploy_anno": "deploy_value"}, "podAnnotations": {"pod_anno": "pod_value"}, } @@ -327,7 +372,8 @@ def test_image_override(self): "tag": "1.2.3", "pullPolicy": "Always", } - } + }, + "otelCollector": {"tracesEnabled": True}, }, show_only=[DEPLOYMENT_TEMPLATE], ) @@ -338,45 +384,48 @@ def test_image_override(self): class TestOtelCollectorService: - """Service-level configurability.""" - def test_service_annotations(self): docs = render_chart( - values={"otelCollector": {"service": {"annotations": {"some_anno": "some_value"}}}}, + values={ + "otelCollector": { + "tracesEnabled": True, + "service": {"annotations": {"some_anno": "some_value"}}, + } + }, show_only=[SERVICE_TEMPLATE], ) assert jmespath.search("metadata.annotations.some_anno", docs[0]) == "some_value" def test_service_no_annotations_block_when_unset(self): - docs = render_chart(show_only=[SERVICE_TEMPLATE]) + docs = render_chart(values={"otelCollector": {"tracesEnabled": True}}, show_only=[SERVICE_TEMPLATE]) assert "annotations" not in jmespath.search("metadata", docs[0]) class TestOtelCollectorServiceAccount: - """ServiceAccount-level configurability.""" - def test_default_create(self): - docs = render_chart(show_only=[SERVICE_ACCOUNT_TEMPLATE]) + docs = render_chart( + values={"otelCollector": {"tracesEnabled": True}}, show_only=[SERVICE_ACCOUNT_TEMPLATE] + ) assert docs[0]["kind"] == "ServiceAccount" assert docs[0]["automountServiceAccountToken"] is False def test_create_false_suppresses_sa(self): docs = render_chart( - values={"otelCollector": {"serviceAccount": {"create": False}}}, + values={"otelCollector": {"tracesEnabled": True, "serviceAccount": {"create": False}}}, show_only=[SERVICE_ACCOUNT_TEMPLATE], ) assert docs == [] def test_create_false_deployment_uses_default_sa(self): docs = render_chart( - values={"otelCollector": {"serviceAccount": {"create": False}}}, + values={"otelCollector": {"tracesEnabled": True, "serviceAccount": {"create": False}}}, show_only=[DEPLOYMENT_TEMPLATE], ) assert jmespath.search("spec.template.spec.serviceAccountName", docs[0]) == "default" def test_custom_sa_name_propagates_to_deployment(self): docs = render_chart( - values={"otelCollector": {"serviceAccount": {"name": "my-custom-sa"}}}, + values={"otelCollector": {"tracesEnabled": True, "serviceAccount": {"name": "my-custom-sa"}}}, show_only=[DEPLOYMENT_TEMPLATE, SERVICE_ACCOUNT_TEMPLATE], ) sa = next(d for d in docs if d["kind"] == "ServiceAccount") @@ -386,14 +435,24 @@ def test_custom_sa_name_propagates_to_deployment(self): def test_automount_token_override(self): docs = render_chart( - values={"otelCollector": {"serviceAccount": {"automountServiceAccountToken": True}}}, + values={ + "otelCollector": { + "tracesEnabled": True, + "serviceAccount": {"automountServiceAccountToken": True}, + } + }, show_only=[SERVICE_ACCOUNT_TEMPLATE], ) assert docs[0]["automountServiceAccountToken"] is True def test_sa_annotations(self): docs = render_chart( - values={"otelCollector": {"serviceAccount": {"annotations": {"sa_anno": "sa_value"}}}}, + values={ + "otelCollector": { + "tracesEnabled": True, + "serviceAccount": {"annotations": {"sa_anno": "sa_value"}}, + } + }, show_only=[SERVICE_ACCOUNT_TEMPLATE], ) assert jmespath.search("metadata.annotations.sa_anno", docs[0]) == "sa_value" @@ -404,12 +463,14 @@ class TestOtelCollectorAirflowEnvironment: @pytest.mark.parametrize("template", AIRFLOW_POD_TEMPLATES) def test_default_emits_traces_env_only(self, template): - docs = render_chart(show_only=[template]) - names = _env_names(docs[0]) + docs = render_chart(values={"otelCollector": {"tracesEnabled": True}}, show_only=[template]) + names = jmespath.search("spec.template.spec.containers[0].env | [*].name", docs[0]) + assert "OTEL_SERVICE_NAME" in names assert "OTEL_EXPORTER_OTLP_PROTOCOL" in names assert "OTEL_TRACES_EXPORTER" in names assert "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT" in names + # Metrics env vars aren't present. assert "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT" not in names assert "OTEL_METRIC_EXPORT_INTERVAL" not in names @@ -420,25 +481,42 @@ def test_metrics_enabled_emits_metrics_env(self, template): values={"otelCollector": {"metricsEnabled": True}}, show_only=[template], ) - names = _env_names(docs[0]) + names = jmespath.search("spec.template.spec.containers[0].env | [*].name", docs[0]) + + assert "OTEL_SERVICE_NAME" in names + assert "OTEL_EXPORTER_OTLP_PROTOCOL" in names assert "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT" in names assert "OTEL_METRIC_EXPORT_INTERVAL" in names + # Traces env vars aren't present. + assert "OTEL_TRACES_EXPORTER" not in names + assert "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT" not in names + @pytest.mark.parametrize("template", AIRFLOW_POD_TEMPLATES) def test_both_flags_off_emits_no_otel_env(self, template): docs = render_chart( values={"otelCollector": {"tracesEnabled": False, "metricsEnabled": False}}, show_only=[template], ) - names = _env_names(docs[0]) - assert not any(n.startswith("OTEL_") for n in names) + + assert ( + jmespath.search("spec.template.spec.containers[0].env[?name.starts_with(@, 'OTEL_')]", docs[0]) + == [] + ) def test_metric_export_interval_value(self): docs = render_chart( values={"otelCollector": {"metricsEnabled": True, "metricExportIntervalMs": 12345}}, show_only=[AIRFLOW_POD_TEMPLATES[0]], ) - assert _env_value(docs[0], "OTEL_METRIC_EXPORT_INTERVAL") == "12345" + + assert ( + jmespath.search( + "spec.template.spec.containers[0].env[?name=='OTEL_METRIC_EXPORT_INTERVAL'] | [0].value", + docs[0], + ) + == "12345" + ) class TestOtelCollectorAirflowConfig: @@ -446,7 +524,7 @@ class TestOtelCollectorAirflowConfig: @staticmethod def _get_conf_section(cfg: str, name: str) -> str: - """Return the body of the specified section (everything until the next '[').""" + """Return the body of the specified section.""" return cfg.split(f"[{name}]")[1].split("[")[0] @staticmethod @@ -455,7 +533,9 @@ def _get_airflow_conf(values=None): return jmespath.search('data."airflow.cfg"', docs[0]) def test_default_traces_section_has_otel_on_true(self): - traces = self._get_conf_section(self._get_airflow_conf(), "traces") + traces = self._get_conf_section( + self._get_airflow_conf({"otelCollector": {"tracesEnabled": True}}), "traces" + ) assert "otel_on = True" in traces def test_default_metrics_section_has_otel_off_and_statsd_on(self): diff --git a/helm-tests/tests/helm_tests/security/test_rbac.py b/helm-tests/tests/helm_tests/security/test_rbac.py index 15df115a53c51..eb781786bd14b 100644 --- a/helm-tests/tests/helm_tests/security/test_rbac.py +++ b/helm-tests/tests/helm_tests/security/test_rbac.py @@ -180,7 +180,7 @@ def test_deployments_no_rbac_no_sa(self, version): "workers": {"serviceAccount": {"create": False}}, "triggerer": {"serviceAccount": {"create": False}}, "statsd": {"serviceAccount": {"create": False}}, - "otelCollector": {"serviceAccount": {"create": False}}, + "otelCollector": {"tracesEnabled": True, "serviceAccount": {"create": False}}, "createUserJob": {"serviceAccount": {"create": False}}, "migrateDatabaseJob": {"serviceAccount": {"create": False}}, "flower": {"enabled": True, "serviceAccount": {"create": False}}, @@ -206,6 +206,7 @@ def test_deployments_no_rbac_with_sa(self, version): "databaseCleanup": {"enabled": True}, "flower": {"enabled": True}, "pgbouncer": {"enabled": True}, + "otelCollector": {"tracesEnabled": True}, }, version=version, ), @@ -244,7 +245,7 @@ def test_deployments_with_rbac_no_sa(self, version): "triggerer": {"serviceAccount": {"create": False}}, "flower": {"enabled": True, "serviceAccount": {"create": False}}, "statsd": {"serviceAccount": {"create": False}}, - "otelCollector": {"serviceAccount": {"create": False}}, + "otelCollector": {"tracesEnabled": True, "serviceAccount": {"create": False}}, "redis": {"serviceAccount": {"create": False}}, "pgbouncer": { "enabled": True, @@ -276,6 +277,7 @@ def test_deployments_with_rbac_with_sa(self, version): "databaseCleanup": {"enabled": True}, "flower": {"enabled": True}, "pgbouncer": {"enabled": True}, + "otelCollector": {"tracesEnabled": True}, }, version=version, ), @@ -335,7 +337,10 @@ def test_service_account_custom_names(self): "triggerer": {"serviceAccount": {"name": CUSTOM_TRIGGERER_NAME}}, "flower": {"enabled": True, "serviceAccount": {"name": CUSTOM_FLOWER_NAME}}, "statsd": {"serviceAccount": {"name": CUSTOM_STATSD_NAME}}, - "otelCollector": {"serviceAccount": {"name": CUSTOM_OTEL_COLLECTOR_NAME}}, + "otelCollector": { + "tracesEnabled": True, + "serviceAccount": {"name": CUSTOM_OTEL_COLLECTOR_NAME}, + }, "redis": {"serviceAccount": {"name": CUSTOM_REDIS_NAME}}, "postgresql": {"serviceAccount": {"create": True, "name": CUSTOM_POSTGRESQL_NAME}}, "pgbouncer": { @@ -394,7 +399,10 @@ def test_service_account_custom_names_in_objects(self): "triggerer": {"serviceAccount": {"name": CUSTOM_TRIGGERER_NAME}}, "flower": {"enabled": True, "serviceAccount": {"name": CUSTOM_FLOWER_NAME}}, "statsd": {"serviceAccount": {"name": CUSTOM_STATSD_NAME}}, - "otelCollector": {"serviceAccount": {"name": CUSTOM_OTEL_COLLECTOR_NAME}}, + "otelCollector": { + "tracesEnabled": True, + "serviceAccount": {"name": CUSTOM_OTEL_COLLECTOR_NAME}, + }, "redis": {"serviceAccount": {"name": CUSTOM_REDIS_NAME}}, "postgresql": {"serviceAccount": {"name": CUSTOM_POSTGRESQL_NAME}}, "pgbouncer": {