diff --git a/airflow/config_templates/config.yml b/airflow/config_templates/config.yml index b7eb88d62199a..1225c73a97d7b 100644 --- a/airflow/config_templates/config.yml +++ b/airflow/config_templates/config.yml @@ -1670,12 +1670,13 @@ or insert it into a database (depending of the backend) This status is used by the scheduler to update the state of the task The use of a database is highly recommended + When not specified, sql_alchemy_conn with a db+ scheme prefix will be used http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-result-backend-settings version_added: ~ type: string sensitive: true - example: ~ - default: "db+postgresql://postgres:airflow@postgres/airflow" + example: "db+postgresql://postgres:airflow@postgres/airflow" + default: ~ - name: flower_host description: | Celery Flower is a sweet UI for Celery. Airflow has a shortcut to start diff --git a/airflow/config_templates/default_airflow.cfg b/airflow/config_templates/default_airflow.cfg index f47d0a82a2e6b..214890947b438 100644 --- a/airflow/config_templates/default_airflow.cfg +++ b/airflow/config_templates/default_airflow.cfg @@ -846,8 +846,10 @@ broker_url = redis://redis:6379/0 # or insert it into a database (depending of the backend) # This status is used by the scheduler to update the state of the task # The use of a database is highly recommended +# When not specified, sql_alchemy_conn with a db+ scheme prefix will be used # http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-result-backend-settings -result_backend = db+postgresql://postgres:airflow@postgres/airflow +# Example: result_backend = db+postgresql://postgres:airflow@postgres/airflow +# result_backend = # Celery Flower is a sweet UI for Celery. Airflow has a shortcut to start # it ``airflow celery flower``. This defines the IP that Celery Flower runs on diff --git a/airflow/config_templates/default_celery.py b/airflow/config_templates/default_celery.py index 9d81c6353fba2..0ca5a1676999b 100644 --- a/airflow/config_templates/default_celery.py +++ b/airflow/config_templates/default_celery.py @@ -36,6 +36,12 @@ def _broker_supports_visibility_timeout(url): if _broker_supports_visibility_timeout(broker_url): broker_transport_options['visibility_timeout'] = 21600 +if conf.has_option("celery", 'RESULT_BACKEND'): + result_backend = conf.get_mandatory_value('celery', 'RESULT_BACKEND') +else: + log.debug("Value for celery result_backend not found. Using sql_alchemy_conn with db+ prefix.") + result_backend = f'db+{conf.get("database", "SQL_ALCHEMY_CONN")}' + DEFAULT_CELERY_CONFIG = { 'accept_content': ['json'], 'event_serializer': 'json', @@ -46,7 +52,7 @@ def _broker_supports_visibility_timeout(url): 'task_track_started': conf.getboolean('celery', 'task_track_started'), 'broker_url': broker_url, 'broker_transport_options': broker_transport_options, - 'result_backend': conf.get('celery', 'RESULT_BACKEND'), + 'result_backend': result_backend, 'worker_concurrency': conf.getint('celery', 'WORKER_CONCURRENCY'), 'worker_enable_remote_control': conf.getboolean('celery', 'worker_enable_remote_control'), } @@ -92,7 +98,6 @@ def _broker_supports_visibility_timeout(url): f'all necessary certs and key ({e}).' ) -result_backend = str(DEFAULT_CELERY_CONFIG['result_backend']) if 'amqp://' in result_backend or 'redis://' in result_backend or 'rpc://' in result_backend: log.warning( "You have configured a result_backend of %s, it is highly recommended " diff --git a/chart/templates/_helpers.yaml b/chart/templates/_helpers.yaml index 8f61e6ca95d7b..19f3a63c587d1 100644 --- a/chart/templates/_helpers.yaml +++ b/chart/templates/_helpers.yaml @@ -74,6 +74,7 @@ If release name contains chart name it will be used as a full name. key: webserver-secret-key {{- end }} {{- if or (eq .Values.executor "CeleryExecutor") (eq .Values.executor "CeleryKubernetesExecutor") }} + {{- if or (semverCompare "<2.4.0" .Values.airflowVersion) (.Values.data.resultBackendSecretName) (.Values.data.resultBackendConnection) }} {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__CELERY_RESULT_BACKEND }} # (Airflow 1.10.* variant) - name: AIRFLOW__CELERY__CELERY_RESULT_BACKEND @@ -89,6 +90,7 @@ If release name contains chart name it will be used as a full name. name: {{ template "airflow_result_backend_secret" . }} key: connection {{- end }} + {{- end }} {{- if .Values.enableBuiltInSecretEnvVars.AIRFLOW__CELERY__BROKER_URL }} - name: AIRFLOW__CELERY__BROKER_URL valueFrom: diff --git a/chart/templates/secrets/result-backend-connection-secret.yaml b/chart/templates/secrets/result-backend-connection-secret.yaml index 46fd603b704b9..1c66367e0275e 100644 --- a/chart/templates/secrets/result-backend-connection-secret.yaml +++ b/chart/templates/secrets/result-backend-connection-secret.yaml @@ -20,6 +20,7 @@ ################################# {{- if not .Values.data.resultBackendSecretName }} {{- if or (eq .Values.executor "CeleryExecutor") (eq .Values.executor "CeleryKubernetesExecutor") }} +{{- if or (semverCompare "<2.4.0" .Values.airflowVersion) (and (semverCompare ">=2.4.0" .Values.airflowVersion) .Values.data.resultBackendConnection) }} {{- $connection := .Values.data.resultBackendConnection | default .Values.data.metadataConnection }} {{- $resultBackendHost := $connection.host | default (printf "%s-%s" .Release.Name "postgresql") }} @@ -45,3 +46,4 @@ data: connection: {{ urlJoin (dict "scheme" (printf "db+%s" $connection.protocol) "userinfo" (printf "%s:%s" ($connection.user|urlquery) ($connection.pass | urlquery)) "host" (printf "%s:%s" $host $port) "path" (printf "/%s" $database) "query" $query) | b64enc | quote }} {{- end }} {{- end }} +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index 6b1ca62970e04..45d7a58a93f3c 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -319,7 +319,22 @@ extraEnvFrom: ~ # Airflow database & redis config data: # If secret names are provided, use those secrets + # These secrets must be created manually, eg: + # + # kind: Secret + # apiVersion: v1 + # metadata: + # name: custom-airflow-metadata-secret + # type: Opaque + # data: + # connection: base64_encoded_connection_string + metadataSecretName: ~ + # When providing secret names and using the same database for metadata and + # result backend, for Airflow < 2.4.0 it is necessary to create a separate + # secret for result backend but with a db+ scheme prefix. + # For Airflow >= 2.4.0 it is possible to not specify the secret again, + # as Airflow will use sql_alchemy_conn with a db+ scheme prefix by default. resultBackendSecretName: ~ brokerUrlSecretName: ~ diff --git a/tests/charts/test_basic_helm_chart.py b/tests/charts/test_basic_helm_chart.py index 5c732c3fb3536..0776718c24184 100644 --- a/tests/charts/test_basic_helm_chart.py +++ b/tests/charts/test_basic_helm_chart.py @@ -25,24 +25,44 @@ from tests.charts.helm_template_generator import render_chart -OBJECT_COUNT_IN_BASIC_DEPLOYMENT = 35 +OBJECT_COUNT_IN_BASIC_DEPLOYMENT = 34 class TestBaseChartTest(unittest.TestCase): - def test_basic_deployments(self): + def _get_values_with_version(self, values, version): + if version != "default": + values["airflowVersion"] = version + return values + + def _get_object_count(self, version): + # TODO remove default from condition after airflow update + if version == "2.3.2" or version == "default": + return OBJECT_COUNT_IN_BASIC_DEPLOYMENT + 1 + return OBJECT_COUNT_IN_BASIC_DEPLOYMENT + + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_basic_deployments(self, version): + expected_object_count_in_basic_deployment = self._get_object_count(version) k8s_objects = render_chart( "TEST-BASIC", - values={ - "chart": { - 'metadata': 'AA', + self._get_values_with_version( + values={ + "chart": { + 'metadata': 'AA', + }, + 'labels': {"TEST-LABEL": "TEST-VALUE"}, + "fullnameOverride": "TEST-BASIC", }, - 'labels': {"TEST-LABEL": "TEST-VALUE"}, - "fullnameOverride": "TEST-BASIC", - }, + version=version, + ), ) list_of_kind_names_tuples = { (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects } + # TODO remove default from condition after airflow update + if version == "2.3.2" or version == "default": + assert ('Secret', 'TEST-BASIC-airflow-result-backend') in list_of_kind_names_tuples + list_of_kind_names_tuples.remove(('Secret', 'TEST-BASIC-airflow-result-backend')) assert list_of_kind_names_tuples == { ('ServiceAccount', 'TEST-BASIC-create-user-job'), ('ServiceAccount', 'TEST-BASIC-migrate-database-job'), @@ -53,7 +73,6 @@ def test_basic_deployments(self): ('ServiceAccount', 'TEST-BASIC-webserver'), ('ServiceAccount', 'TEST-BASIC-worker'), ('Secret', 'TEST-BASIC-airflow-metadata'), - ('Secret', 'TEST-BASIC-airflow-result-backend'), ('Secret', 'TEST-BASIC-broker-url'), ('Secret', 'TEST-BASIC-fernet-key'), ('Secret', 'TEST-BASIC-webserver-secret-key'), @@ -80,7 +99,7 @@ def test_basic_deployments(self): ('Job', 'TEST-BASIC-create-user'), ('Job', 'TEST-BASIC-run-airflow-migrations'), } - assert OBJECT_COUNT_IN_BASIC_DEPLOYMENT == len(k8s_objects) + assert expected_object_count_in_basic_deployment == len(k8s_objects) for k8s_object in k8s_objects: labels = jmespath.search('metadata.labels', k8s_object) or {} if 'helm.sh/chart' in labels: @@ -94,16 +113,20 @@ def test_basic_deployments(self): "TEST-LABEL" ), f"Missing label TEST-LABEL on {k8s_name}. Current labels: {labels}" - def test_basic_deployment_without_default_users(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_basic_deployment_without_default_users(self, version): + expected_object_count_in_basic_deployment = self._get_object_count(version) k8s_objects = render_chart( "TEST-BASIC", - values={"webserver": {"defaultUser": {'enabled': False}}}, + values=self._get_values_with_version( + values={"webserver": {"defaultUser": {'enabled': False}}}, version=version + ), ) list_of_kind_names_tuples = [ (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects ] assert ('Job', 'TEST-BASIC-create-user') not in list_of_kind_names_tuples - assert OBJECT_COUNT_IN_BASIC_DEPLOYMENT - 2 == len(k8s_objects) + assert expected_object_count_in_basic_deployment - 2 == len(k8s_objects) def test_network_policies_are_valid(self): k8s_objects = render_chart( @@ -139,6 +162,17 @@ def test_labels_are_valid(self): values={ "labels": {"label1": "value1", "label2": "value2"}, "executor": "CeleryExecutor", + "data": { + "resultBackendConnection": { + "user": "someuser", + "pass": "somepass", + "host": "somehost", + "protocol": "postgresql", + "port": 7777, + "db": "somedb", + "sslmode": "allow", + } + }, "pgbouncer": {"enabled": True}, "redis": {"enabled": True}, "ingress": {"enabled": True}, diff --git a/tests/charts/test_rbac.py b/tests/charts/test_rbac.py index fee74f0a1cad2..bd75de30819af 100644 --- a/tests/charts/test_rbac.py +++ b/tests/charts/test_rbac.py @@ -18,13 +18,13 @@ import unittest import jmespath +from parameterized import parameterized from tests.charts.helm_template_generator import render_chart DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES = [ ('Secret', 'TEST-RBAC-postgresql'), ('Secret', 'TEST-RBAC-airflow-metadata'), - ('Secret', 'TEST-RBAC-airflow-result-backend'), ('Secret', 'TEST-RBAC-pgbouncer-config'), ('Secret', 'TEST-RBAC-pgbouncer-stats'), ('ConfigMap', 'TEST-RBAC-airflow-config'), @@ -105,34 +105,51 @@ class RBACTest(unittest.TestCase): - def test_deployments_no_rbac_no_sa(self): + def _get_values_with_version(self, values, version): + if version != "default": + values["airflowVersion"] = version + return values + + def _get_object_count(self, version): + # TODO remove default from condition after airflow update + if version == "2.3.2" or version == "default": + return [ + ('Secret', 'TEST-RBAC-airflow-result-backend') + ] + DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES + return DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES + + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_deployments_no_rbac_no_sa(self, version): k8s_objects = render_chart( "TEST-RBAC", - values={ - "fullnameOverride": "TEST-RBAC", - "rbac": {"create": False}, - "cleanup": { - "enabled": True, - "serviceAccount": { - "create": False, + values=self._get_values_with_version( + values={ + "fullnameOverride": "TEST-RBAC", + "rbac": {"create": False}, + "cleanup": { + "enabled": True, + "serviceAccount": { + "create": False, + }, }, - }, - "pgbouncer": { - "enabled": True, - "serviceAccount": { - "create": False, + "pgbouncer": { + "enabled": True, + "serviceAccount": { + "create": False, + }, }, + "redis": {"serviceAccount": {"create": False}}, + "scheduler": {"serviceAccount": {"create": False}}, + "webserver": {"serviceAccount": {"create": False}}, + "workers": {"serviceAccount": {"create": False}}, + "triggerer": {"serviceAccount": {"create": False}}, + "statsd": {"serviceAccount": {"create": False}}, + "createUserJob": {"serviceAccount": {"create": False}}, + "migrateDatabaseJob": {"serviceAccount": {"create": False}}, + "flower": {"enabled": True, "serviceAccount": {"create": False}}, }, - "redis": {"serviceAccount": {"create": False}}, - "scheduler": {"serviceAccount": {"create": False}}, - "webserver": {"serviceAccount": {"create": False}}, - "workers": {"serviceAccount": {"create": False}}, - "triggerer": {"serviceAccount": {"create": False}}, - "statsd": {"serviceAccount": {"create": False}}, - "createUserJob": {"serviceAccount": {"create": False}}, - "migrateDatabaseJob": {"serviceAccount": {"create": False}}, - "flower": {"enabled": True, "serviceAccount": {"create": False}}, - }, + version=version, + ), ) list_of_kind_names_tuples = [ (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects @@ -140,83 +157,93 @@ def test_deployments_no_rbac_no_sa(self): self.assertCountEqual( list_of_kind_names_tuples, - DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES, + self._get_object_count(version), ) - def test_deployments_no_rbac_with_sa(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_deployments_no_rbac_with_sa(self, version): k8s_objects = render_chart( "TEST-RBAC", - values={ - "fullnameOverride": "TEST-RBAC", - "rbac": {"create": False}, - "cleanup": {"enabled": True}, - "flower": {"enabled": True}, - "pgbouncer": {"enabled": True}, - }, + values=self._get_values_with_version( + values={ + "fullnameOverride": "TEST-RBAC", + "rbac": {"create": False}, + "cleanup": {"enabled": True}, + "flower": {"enabled": True}, + "pgbouncer": {"enabled": True}, + }, + version=version, + ), ) list_of_kind_names_tuples = [ (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects ] - real_list_of_kind_names = DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES + SERVICE_ACCOUNT_NAME_TUPLES + real_list_of_kind_names = self._get_object_count(version) + SERVICE_ACCOUNT_NAME_TUPLES self.assertCountEqual( list_of_kind_names_tuples, real_list_of_kind_names, ) - def test_deployments_with_rbac_no_sa(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_deployments_with_rbac_no_sa(self, version): k8s_objects = render_chart( "TEST-RBAC", - values={ - "fullnameOverride": "TEST-RBAC", - "cleanup": { - "enabled": True, - "serviceAccount": { - "create": False, + values=self._get_values_with_version( + values={ + "fullnameOverride": "TEST-RBAC", + "cleanup": { + "enabled": True, + "serviceAccount": { + "create": False, + }, }, - }, - "scheduler": {"serviceAccount": {"create": False}}, - "webserver": {"serviceAccount": {"create": False}}, - "workers": {"serviceAccount": {"create": False}}, - "triggerer": {"serviceAccount": {"create": False}}, - "flower": {"enabled": True, "serviceAccount": {"create": False}}, - "statsd": {"serviceAccount": {"create": False}}, - "redis": {"serviceAccount": {"create": False}}, - "pgbouncer": { - "enabled": True, - "serviceAccount": { - "create": False, + "scheduler": {"serviceAccount": {"create": False}}, + "webserver": {"serviceAccount": {"create": False}}, + "workers": {"serviceAccount": {"create": False}}, + "triggerer": {"serviceAccount": {"create": False}}, + "flower": {"enabled": True, "serviceAccount": {"create": False}}, + "statsd": {"serviceAccount": {"create": False}}, + "redis": {"serviceAccount": {"create": False}}, + "pgbouncer": { + "enabled": True, + "serviceAccount": { + "create": False, + }, }, + "createUserJob": {"serviceAccount": {"create": False}}, + "migrateDatabaseJob": {"serviceAccount": {"create": False}}, }, - "createUserJob": {"serviceAccount": {"create": False}}, - "migrateDatabaseJob": {"serviceAccount": {"create": False}}, - }, + version=version, + ), ) list_of_kind_names_tuples = [ (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects ] - real_list_of_kind_names = DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES + RBAC_ENABLED_KIND_NAME_TUPLES + real_list_of_kind_names = self._get_object_count(version) + RBAC_ENABLED_KIND_NAME_TUPLES self.assertCountEqual( list_of_kind_names_tuples, real_list_of_kind_names, ) - def test_deployments_with_rbac_with_sa(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_deployments_with_rbac_with_sa(self, version): k8s_objects = render_chart( "TEST-RBAC", - values={ - "fullnameOverride": "TEST-RBAC", - "cleanup": {"enabled": True}, - "flower": {"enabled": True}, - "pgbouncer": {"enabled": True}, - }, + values=self._get_values_with_version( + values={ + "fullnameOverride": "TEST-RBAC", + "cleanup": {"enabled": True}, + "flower": {"enabled": True}, + "pgbouncer": {"enabled": True}, + }, + version=version, + ), ) list_of_kind_names_tuples = [ (k8s_object['kind'], k8s_object['metadata']['name']) for k8s_object in k8s_objects ] real_list_of_kind_names = ( - DEPLOYMENT_NO_RBAC_NO_SA_KIND_NAME_TUPLES - + SERVICE_ACCOUNT_NAME_TUPLES - + RBAC_ENABLED_KIND_NAME_TUPLES + self._get_object_count(version) + SERVICE_ACCOUNT_NAME_TUPLES + RBAC_ENABLED_KIND_NAME_TUPLES ) self.assertCountEqual( list_of_kind_names_tuples, diff --git a/tests/charts/test_result_backend_connection_secret.py b/tests/charts/test_result_backend_connection_secret.py index d32a3bcf0e5da..ba7cdd199f5d2 100644 --- a/tests/charts/test_result_backend_connection_secret.py +++ b/tests/charts/test_result_backend_connection_secret.py @@ -17,6 +17,7 @@ import base64 import unittest +from typing import Union import jmespath from parameterized import parameterized @@ -25,6 +26,17 @@ class ResultBackendConnectionSecretTest(unittest.TestCase): + def _get_values_with_version(self, values, version): + if version != "default": + values["airflowVersion"] = version + return values + + def _assert_for_old_version(self, version, value, expected_value): + # TODO remove default from condition after airflow update + if version == "2.3.2" or version == "default": + assert value == expected_value + else: + assert value is None non_chart_database_values = { "user": "someuser", @@ -53,49 +65,69 @@ def test_should_not_generate_a_document_if_using_existing_secret(self): ) def test_should_a_document_be_generated_for_executor(self, executor, expected_doc_count): docs = render_chart( - values={"executor": executor}, + values={ + "executor": executor, + "data": { + "metadataConnection": {**self.non_chart_database_values}, + "resultBackendConnection": { + **self.non_chart_database_values, + "user": "anotheruser", + "pass": "anotherpass", + }, + }, + }, show_only=["templates/secrets/result-backend-connection-secret.yaml"], ) assert expected_doc_count == len(docs) - def _get_connection(self, values: dict) -> str: + def _get_connection(self, values: dict) -> Union[str, None]: docs = render_chart( values=values, show_only=["templates/secrets/result-backend-connection-secret.yaml"], ) + if len(docs) == 0: + return None encoded_connection = jmespath.search("data.connection", docs[0]) return base64.b64decode(encoded_connection).decode() - def test_default_connection(self): - connection = self._get_connection({}) - - assert ( - "db+postgresql://postgres:postgres@RELEASE-NAME-postgresql:5432/postgres?sslmode=disable" - == connection + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_default_connection_old_version(self, version): + connection = self._get_connection(self._get_values_with_version(version=version, values={})) + self._assert_for_old_version( + version, + value=connection, + expected_value="db+postgresql://postgres:postgres@RELEASE-NAME" + "-postgresql:5432/postgres?sslmode=disable", ) - def test_should_default_to_custom_metadata_db_connection_with_pgbouncer_overrides(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_should_default_to_custom_metadata_db_connection_with_pgbouncer_overrides(self, version): values = { "pgbouncer": {"enabled": True}, "data": {"metadataConnection": {**self.non_chart_database_values}}, } - connection = self._get_connection(values) + connection = self._get_connection(self._get_values_with_version(values=values, version=version)) # host, port, dbname still get overridden - assert ( - "db+postgresql://someuser:somepass@RELEASE-NAME-pgbouncer:6543" - "/RELEASE-NAME-result-backend?sslmode=allow" == connection + self._assert_for_old_version( + version, + value=connection, + expected_value="db+postgresql://someuser:somepass@RELEASE-NAME-pgbouncer" + ":6543/RELEASE-NAME-result-backend?sslmode=allow", ) - def test_should_set_pgbouncer_overrides_when_enabled(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_should_set_pgbouncer_overrides_when_enabled(self, version): values = {"pgbouncer": {"enabled": True}} - connection = self._get_connection(values) + connection = self._get_connection(self._get_values_with_version(values=values, version=version)) # host, port, dbname get overridden - assert ( - "db+postgresql://postgres:postgres@RELEASE-NAME-pgbouncer:6543" - "/RELEASE-NAME-result-backend?sslmode=disable" == connection + self._assert_for_old_version( + version, + value=connection, + expected_value="db+postgresql://postgres:postgres@RELEASE-NAME-pgbouncer" + ":6543/RELEASE-NAME-result-backend?sslmode=disable", ) def test_should_set_pgbouncer_overrides_with_non_chart_database_when_enabled(self): @@ -111,13 +143,17 @@ def test_should_set_pgbouncer_overrides_with_non_chart_database_when_enabled(sel "/RELEASE-NAME-result-backend?sslmode=allow" == connection ) - def test_should_default_to_custom_metadata_db_connection(self): + @parameterized.expand(["2.3.2", "2.4.0", "default"]) + def test_should_default_to_custom_metadata_db_connection_in_old_version(self, version): values = { "data": {"metadataConnection": {**self.non_chart_database_values}}, } - connection = self._get_connection(values) - - assert "db+postgresql://someuser:somepass@somehost:7777/somedb?sslmode=allow" == connection + connection = self._get_connection(self._get_values_with_version(values=values, version=version)) + self._assert_for_old_version( + version, + value=connection, + expected_value="db+postgresql://someuser:somepass@somehost:7777/somedb?sslmode=allow", + ) def test_should_correctly_use_non_chart_database(self): values = {"data": {"resultBackendConnection": {**self.non_chart_database_values}}}