def test_noop_compute_log_manager( template: HelmTemplate, compute_log_manager_type: ComputeLogManagerType ): helm_values = DagsterHelmValues.construct( computeLogManager=ComputeLogManager.construct(type=compute_log_manager_type) ) configmaps = template.render(helm_values) instance = yaml.full_load(configmaps[0].data["dagster.yaml"]) compute_logs_config = instance["compute_logs"] assert compute_logs_config["module"] == "dagster.core.storage.noop_compute_log_manager" assert compute_logs_config["class"] == "NoOpComputeLogManager"
def test_service_account_global_name(template: HelmTemplate): global_service_account_name = "global-service-account-name" service_account_values = DagsterHelmValues.construct( global_=Global.construct( serviceAccountName=global_service_account_name), ) service_account_templates = template.render(service_account_values) assert len(service_account_templates) == 1 service_account_template = service_account_templates[0] assert service_account_template.metadata.name == global_service_account_name
def test_subchart_image_pull_secrets(subchart_template: HelmTemplate): image_pull_secrets = [{"name": "super-duper-secret"}] deployment_values = DagsterUserDeploymentsHelmValues.construct( imagePullSecrets=image_pull_secrets, ) deployment_templates = subchart_template.render(deployment_values) assert len(deployment_templates) == 1 deployment_template = deployment_templates[0] pod_spec = deployment_template.spec.template.spec assert pod_spec.image_pull_secrets[0].name == image_pull_secrets[0]["name"]
def test_service_account_name(template: HelmTemplate): service_account_name = "service-account-name" service_account_values = DagsterHelmValues.construct( serviceAccount=ServiceAccount.construct(name=service_account_name, create=True)) service_account_templates = template.render(service_account_values) assert len(service_account_templates) == 1 service_account_template = service_account_templates[0] assert service_account_template.metadata.name == service_account_name
def test_startup_probe_enabled(deployment_template: HelmTemplate, enabled: bool): helm_values = DagsterHelmValues.construct(dagit=Dagit.construct( startupProbe=kubernetes.StartupProbe(enabled=enabled))) dagit = deployment_template.render(helm_values) assert len(dagit) == 1 dagit = dagit[0] assert len(dagit.spec.template.spec.containers) == 1 container = dagit.spec.template.spec.containers[0] assert (container.startup_probe is not None) == enabled
def test_subchart_default_postgres_password(subchart_template: HelmTemplate): deployment_values = DagsterUserDeploymentsHelmValues.construct() deployment_templates = subchart_template.render(deployment_values) assert len(deployment_templates) == 1 deployment_template = deployment_templates[0] pod_spec = deployment_template.spec.template.spec container = pod_spec.containers[0] assert container.env[1].name == "DAGSTER_PG_PASSWORD" assert container.env[1].value_from.secret_key_ref.name == "dagster-postgresql-secret"
def test_daemon_default_image_tag_is_chart_version(template: HelmTemplate, chart_version: str): helm_values = DagsterHelmValues.construct() daemon_deployments = template.render(helm_values, chart_version=chart_version) assert len(daemon_deployments) == 1 image = daemon_deployments[0].spec.template.spec.containers[0].image _, image_tag = image.split(":") assert image_tag == chart_version
def test_user_deployment_secrets_and_configmaps( template: HelmTemplate, include_config_in_launched_runs: bool ): name = "foo" secrets = [{"name": "my-secret"}, {"name": "my-other-secret"}] configmaps = [{"name": "my-configmap"}, {"name": "my-other-configmap"}] deployment = UserDeployment( name=name, image=kubernetes.Image(repository=f"repo/{name}", tag="tag1", pullPolicy="Always"), dagsterApiGrpcArgs=["-m", name], port=3030, envConfigMaps=[ kubernetes.ConfigMapEnvSource.construct(None, **configmap) for configmap in configmaps ], envSecrets=[kubernetes.SecretEnvSource.construct(None, **secret) for secret in secrets], includeConfigInLaunchedRuns=UserDeploymentIncludeConfigInLaunchedRuns( enabled=include_config_in_launched_runs ), ) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments( enabled=True, enableSubchart=True, deployments=[deployment], ) ) user_deployments = template.render(helm_values) assert len(user_deployments) == 1 if include_config_in_launched_runs: container_context = user_deployments[0].spec.template.spec.containers[0].env[2] assert container_context.name == "DAGSTER_CLI_API_GRPC_CONTAINER_CONTEXT" assert json.loads(container_context.value) == { "k8s": { "image_pull_policy": "Always", "env_secrets": ["my-secret", "my-other-secret"], "env_config_maps": [ "release-name-dagster-user-deployments-foo-user-env", "my-configmap", "my-other-configmap", ], } } else: _assert_no_container_context(user_deployments[0])
def test_dagit_labels(deployment_template: HelmTemplate): deployment_labels = {"deployment_label": "label"} pod_labels = {"pod_label": "label"} helm_values = DagsterHelmValues.construct(dagit=Dagit.construct( deploymentLabels=deployment_labels, labels=pod_labels, )) [dagit_deployment] = deployment_template.render(helm_values) assert set(deployment_labels.items()).issubset( dagit_deployment.metadata.labels.items()) assert set(pod_labels.items()).issubset( dagit_deployment.spec.template.metadata.labels.items())
def test_standalone_subchart_service_account_name( standalone_subchart_template: HelmTemplate): service_account_name = "service-account-name" service_account_values = DagsterUserDeploymentsHelmValues.construct( serviceAccount=ServiceAccount.construct(name=service_account_name), ) service_account_templates = standalone_subchart_template.render( service_account_values) assert len(service_account_templates) == 1 service_account_template = service_account_templates[0] assert service_account_template.metadata.name == service_account_name
def test_celery_queue_default_image_tag_is_chart_version( deployment_template: HelmTemplate, chart_version: str): helm_values = DagsterHelmValues.construct( runLauncher=RunLauncher.construct(type=RunLauncherType.CELERY)) celery_queue_deployments = deployment_template.render( helm_values, chart_version=chart_version) assert len(celery_queue_deployments) == 1 image = celery_queue_deployments[0].spec.template.spec.containers[0].image _, image_tag = image.split(":") assert image_tag == chart_version
def test_user_deployment_checksum_changes(template: HelmTemplate): pre_upgrade_helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments( enabled=True, enableSubchart=True, deployments=[ create_simple_user_deployment("deployment-one"), create_simple_user_deployment("deployment-two"), ], ) ) post_upgrade_helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments( enabled=True, enableSubchart=True, deployments=[ create_complex_user_deployment("deployment-one"), create_complex_user_deployment("deployment-two"), ], ) ) pre_upgrade_templates = template.render(pre_upgrade_helm_values) post_upgrade_templates = template.render(post_upgrade_helm_values) # User deployment templates with the same Helm values should not redeploy in a Helm upgrade for pre_upgrade_user_deployment, post_upgrade_user_deployment in zip( pre_upgrade_templates, post_upgrade_templates ): pre_upgrade_checksum = pre_upgrade_user_deployment.spec.template.metadata.annotations[ "checksum/dagster-user-deployment" ] post_upgrade_checksum = post_upgrade_user_deployment.spec.template.metadata.annotations[ "checksum/dagster-user-deployment" ] assert pre_upgrade_checksum != post_upgrade_checksum
def test_ingress_tls(template: HelmTemplate): dagit_host = "dagit.com" dagit_readonly_host = "dagit-readonly.com" flower_host = "flower.com" dagit_tls_secret_name = "dagit_tls_secret_name" dagit_readonly_tls_secret_name = "dagit_readonly_tls_secret_name" flower_tls_secret_name = "flower_tls_secret_name" helm_values = DagsterHelmValues.construct( ingress=Ingress.construct( enabled=True, dagit=DagitIngressConfiguration.construct( host=dagit_host, tls=IngressTLSConfiguration(enabled=True, secretName=dagit_tls_secret_name), ), readOnlyDagit=DagitIngressConfiguration.construct( host=dagit_readonly_host, tls=IngressTLSConfiguration( enabled=True, secretName=dagit_readonly_tls_secret_name), ), flower=FlowerIngressConfiguration.construct( host=flower_host, tls=IngressTLSConfiguration(enabled=True, secretName=flower_tls_secret_name), ), ), dagit=Dagit.construct(enableReadOnly=True), ) [ingress] = template.render(helm_values) assert len(ingress.spec.tls) == 3 dagit_tls = ingress.spec.tls[0] assert len(dagit_tls.hosts) == 1 assert dagit_tls.hosts[0] == dagit_host assert dagit_tls.secret_name == dagit_tls_secret_name dagit_readonly_tls = ingress.spec.tls[1] assert len(dagit_readonly_tls.hosts) == 1 assert dagit_readonly_tls.hosts[0] == dagit_readonly_host assert dagit_readonly_tls.secret_name == dagit_readonly_tls_secret_name flower_tls = ingress.spec.tls[2] assert len(flower_tls.hosts) == 1 assert flower_tls.hosts[0] == flower_host assert flower_tls.secret_name == flower_tls_secret_name
def test_startup_probe_enabled(template: HelmTemplate, enabled: bool): deployment = create_simple_user_deployment("foo") deployment.startupProbe = kubernetes.StartupProbe.construct(enabled=enabled) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments.construct(deployments=[deployment]) ) dagster_user_deployment = template.render(helm_values) assert len(dagster_user_deployment) == 1 dagster_user_deployment = dagster_user_deployment[0] assert len(dagster_user_deployment.spec.template.spec.containers) == 1 container = dagster_user_deployment.spec.template.spec.containers[0] assert (container.startup_probe is not None) == enabled
def test_dagit_image_tag(deployment_template: HelmTemplate): repository = "repository" tag = "tag" helm_values = DagsterHelmValues.construct(dagit=Dagit.construct( image=kubernetes.Image.construct(repository=repository, tag=tag))) dagit_deployments = deployment_template.render(helm_values) assert len(dagit_deployments) == 1 image = dagit_deployments[0].spec.template.spec.containers[0].image image_name, image_tag = image.split(":") assert image_name == repository assert image_tag == tag
def test_dagit_default_image_tag_is_chart_version( deployment_template: HelmTemplate, enable_read_only: bool, chart_version: str): helm_values = DagsterHelmValues.construct(dagit=Dagit.construct( enableReadOnly=enable_read_only)) dagit_deployments = deployment_template.render(helm_values, chart_version=chart_version) assert len(dagit_deployments) == 1 + int(enable_read_only) for dagit_deployment in dagit_deployments: image = dagit_deployment.spec.template.spec.containers[0].image _, image_tag = image.split(":") assert image_tag == chart_version
def test_readiness_probes(template: HelmTemplate): deployment = create_simple_user_deployment("foo") deployment.readinessProbe = kubernetes.ReadinessProbe.construct(timeout_seconds=3) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments.construct(deployments=[deployment]) ) dagster_user_deployment = template.render(helm_values) assert len(dagster_user_deployment) == 1 dagster_user_deployment = dagster_user_deployment[0] assert len(dagster_user_deployment.spec.template.spec.containers) == 1 container = dagster_user_deployment.spec.template.spec.containers[0] assert container.startup_probe is None assert container.startup_probe is None assert container.readiness_probe is not None
def test_service_account_annotations(template: HelmTemplate): service_account_name = "service-account-name" service_account_annotations = {"hello": "world"} service_account_values = DagsterHelmValues.construct( serviceAccount=ServiceAccount.construct( name=service_account_name, create=True, annotations=service_account_annotations)) service_account_templates = template.render(service_account_values) assert len(service_account_templates) == 1 service_account_template = service_account_templates[0] assert service_account_template.metadata.name == service_account_name assert service_account_template.metadata.annotations == service_account_annotations
def test_s3_compute_log_manager(template: HelmTemplate): bucket = "bucket" local_dir = "/dir" prefix = "prefix" use_ssl = True verify = True verify_cert_path = "/path" endpoint_url = "endpoint.com" skip_empty_files = True helm_values = DagsterHelmValues.construct( computeLogManager=ComputeLogManager.construct( type=ComputeLogManagerType.S3, config=ComputeLogManagerConfig.construct( s3ComputeLogManager=S3ComputeLogManagerModel( bucket=bucket, localDir=local_dir, prefix=prefix, useSsl=use_ssl, verify=verify, verifyCertPath=verify_cert_path, endpointUrl=endpoint_url, skipEmptyFiles=skip_empty_files, ) ), ) ) configmaps = template.render(helm_values) instance = yaml.full_load(configmaps[0].data["dagster.yaml"]) compute_logs_config = instance["compute_logs"] assert compute_logs_config["module"] == "dagster_aws.s3.compute_log_manager" assert compute_logs_config["class"] == "S3ComputeLogManager" assert compute_logs_config["config"] == { "bucket": bucket, "local_dir": local_dir, "prefix": prefix, "use_ssl": use_ssl, "verify": verify, "verify_cert_path": verify_cert_path, "endpoint_url": endpoint_url, "skip_empty_files": skip_empty_files, } # Test all config fields in configurable class assert compute_logs_config["config"].keys() == S3ComputeLogManager.config_type().keys()
def test_subchart_postgres_password_global_override(subchart_template: HelmTemplate): deployment_values = DagsterUserDeploymentsHelmValues.construct( postgresqlSecretName="postgresql-secret", global_=Global.construct( postgresqlSecretName="global-postgresql-secret", ), ) deployment_templates = subchart_template.render(deployment_values) assert len(deployment_templates) == 1 deployment_template = deployment_templates[0] pod_spec = deployment_template.spec.template.spec container = pod_spec.containers[0] assert container.env[1].name == "DAGSTER_PG_PASSWORD" assert container.env[1].value_from.secret_key_ref.name == "global-postgresql-secret"
def test_user_deployment_image(template: HelmTemplate): deployment = create_simple_user_deployment("foo") helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments( enabled=True, enableSubchart=True, deployments=[deployment], )) user_deployments = template.render(helm_values) assert len(user_deployments) == 1 image = user_deployments[0].spec.template.spec.containers[0].image image_name, image_tag = image.split(":") assert image_name == deployment.image.repository assert image_tag == deployment.image.tag
def test_startup_probe_exec(template: HelmTemplate): deployment = create_simple_user_deployment("foo") deployment.startupProbe = kubernetes.StartupProbe.construct( enabled=True, exec=dict(command=["my", "command"])) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments.construct( deployments=[deployment])) dagster_user_deployment = template.render(helm_values) assert len(dagster_user_deployment) == 1 dagster_user_deployment = dagster_user_deployment[0] assert len(dagster_user_deployment.spec.template.spec.containers) == 1 container = dagster_user_deployment.spec.template.spec.containers[0] assert container.startup_probe._exec.command == [ # pylint:disable=protected-access "my", "command", ]
def test_standalone_subchart_service_account_annotations( standalone_subchart_template: HelmTemplate, ): service_account_name = "service-account-name" service_account_annotations = {"hello": "world"} service_account_values = DagsterUserDeploymentsHelmValues.construct( serviceAccount=ServiceAccount.construct( name=service_account_name, create=True, annotations=service_account_annotations), ) service_account_templates = standalone_subchart_template.render( service_account_values) assert len(service_account_templates) == 1 service_account_template = service_account_templates[0] assert service_account_template.metadata.name == service_account_name assert service_account_template.metadata.annotations == service_account_annotations
def test_dagit_port(deployment_template: HelmTemplate, service_port: int): helm_values = DagsterHelmValues.construct( dagit=Dagit.construct(service=kubernetes.Service( type="ClusterIP", port=service_port, ), )) dagit_template = deployment_template.render(helm_values) # Make sure dagit will start up serving the correct port dagit_command = "".join( dagit_template[0].spec.template.spec.containers[0].command) port_arg = f"-p {helm_values.dagit.service.port}" assert port_arg in dagit_command # Make sure k8s will open the correct port k8s_port = dagit_template[0].spec.template.spec.containers[0].ports[ 0].container_port assert k8s_port == service_port
def test_user_deployment_labels(template: HelmTemplate, include_config_in_launched_runs: bool): name = "foo" labels = {"my-label-key": "my-label-val", "my-other-label-key": "my-other-label-val"} deployment = UserDeployment( name=name, image=kubernetes.Image(repository=f"repo/{name}", tag="tag1", pullPolicy="Always"), dagsterApiGrpcArgs=["-m", name], port=3030, labels=labels, includeConfigInLaunchedRuns=UserDeploymentIncludeConfigInLaunchedRuns( enabled=include_config_in_launched_runs ), ) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments( enabled=True, enableSubchart=True, deployments=[deployment], ) ) user_deployments = template.render(helm_values) assert len(user_deployments) == 1 if include_config_in_launched_runs: container_context = user_deployments[0].spec.template.spec.containers[0].env[2] assert container_context.name == "DAGSTER_CLI_API_GRPC_CONTAINER_CONTEXT" assert json.loads(container_context.value) == { "k8s": { "image_pull_policy": "Always", "env_config_maps": [ "release-name-dagster-user-deployments-foo-user-env", ], "labels": labels, } } else: _assert_no_container_context(user_deployments[0])
def test_queued_run_coordinator_config(template: HelmTemplate, enabled: bool): max_concurrent_runs = 50 tag_concurrency_limits = [ TagConcurrencyLimit(key="key", value="value", limit=10) ] dequeue_interval_seconds = 50 helm_values = DagsterHelmValues.construct(dagsterDaemon=Daemon.construct( runCoordinator=RunCoordinator.construct( enabled=enabled, type=RunCoordinatorType.QUEUED, config=RunCoordinatorConfig.construct( queuedRunCoordinator=QueuedRunCoordinatorConfig.construct( maxConcurrentRuns=max_concurrent_runs, tagConcurrencyLimits=tag_concurrency_limits, dequeueIntervalSeconds=dequeue_interval_seconds, )), ))) configmaps = template.render(helm_values) assert len(configmaps) == 1 instance = yaml.full_load(configmaps[0].data["dagster.yaml"]) assert ("run_coordinator" in instance) == enabled if enabled: assert instance["run_coordinator"][ "module"] == "dagster.core.run_coordinator" assert instance["run_coordinator"]["class"] == "QueuedRunCoordinator" assert instance["run_coordinator"]["config"] run_coordinator_config = instance["run_coordinator"]["config"] assert run_coordinator_config[ "max_concurrent_runs"] == max_concurrent_runs assert run_coordinator_config[ "dequeue_interval_seconds"] == dequeue_interval_seconds assert len(run_coordinator_config["tag_concurrency_limits"]) == len( tag_concurrency_limits) assert run_coordinator_config["tag_concurrency_limits"] == [ tag_concurrency_limit.dict() for tag_concurrency_limit in tag_concurrency_limits ]
def test_celery_queue_image(deployment_template: HelmTemplate): repository = "repository" tag = "tag" helm_values = DagsterHelmValues.construct(runLauncher=RunLauncher( type=RunLauncherType.CELERY, config=RunLauncherConfig( celeryK8sRunLauncher=CeleryK8sRunLauncherConfig.construct( image=kubernetes.Image.construct(repository=repository, tag=tag))), )) celery_queue_deployments = deployment_template.render(helm_values) assert len(celery_queue_deployments) == 1 image = celery_queue_deployments[0].spec.template.spec.containers[0].image image_name, image_tag = image.split(":") assert image_name == repository assert image_tag == tag
def test_default_redis_config(template: HelmTemplate): helm_values = DagsterHelmValues.construct( generateCeleryConfigSecret=True, runLauncher=RunLauncher.construct(type=RunLauncherType.CELERY), redis=Redis.construct( enabled=True, host="myhost", ), ) [secret] = template.render(helm_values) expected_celery_broker = "redis://myhost:6379/0" expected_celery_backend = "redis://myhost:6379/0" assert secret.data["DAGSTER_CELERY_BROKER_URL"] == base64.b64encode( bytes(expected_celery_broker, encoding="utf-8") ).decode("utf-8") assert secret.data["DAGSTER_CELERY_BACKEND_URL"] == base64.b64encode( bytes(expected_celery_backend, encoding="utf-8") ).decode("utf-8")
def test_startup_probe_default_exec(template: HelmTemplate): deployment = create_simple_user_deployment("foo") deployment.startupProbe = kubernetes.StartupProbe.construct(enabled=True) helm_values = DagsterHelmValues.construct( dagsterUserDeployments=UserDeployments.construct( deployments=[deployment])) dagster_user_deployment = template.render(helm_values) assert len(dagster_user_deployment) == 1 dagster_user_deployment = dagster_user_deployment[0] assert len(dagster_user_deployment.spec.template.spec.containers) == 1 container = dagster_user_deployment.spec.template.spec.containers[0] assert container.startup_probe._exec.command == [ # pylint: disable=protected-access "dagster", "api", "grpc-health-check", "-p", str(deployment.port), ]
def test_celery_backend_override_connection_string(template: HelmTemplate): broker_url = "host:6380,password=password,ssl=True" backend_url = "host:6381,password=password,ssl=True" helm_values = DagsterHelmValues.construct( generateCeleryConfigSecret=True, runLauncher=RunLauncher.construct(type=RunLauncherType.CELERY), redis=Redis.construct( enabled=True, brokerUrl=broker_url, backendUrl=backend_url, ), ) [secret] = template.render(helm_values) assert secret.data["DAGSTER_CELERY_BROKER_URL"] == base64.b64encode( bytes(broker_url, encoding="utf-8") ).decode("utf-8") assert secret.data["DAGSTER_CELERY_BACKEND_URL"] == base64.b64encode( bytes(backend_url, encoding="utf-8") ).decode("utf-8")