Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion Readme.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ dev:

## Environment Configuration

Dagster-uc allows you to have specific user-code deployement configurations per environment. This enables different configurations for your Kubernetes cluster, container registry, resource usage, etc.
Dagster-uc allows you to have specific user-code deployment configurations per environment. This enables different configurations for your Kubernetes cluster, container registry, resource usage, etc.

The default environment used is `dev`, so you need to have `dev` in your configuration file. Other environment names are up to you. An example structure:

Expand All @@ -80,6 +80,18 @@ prd:

Specify the environment with `dagster-uc --environment prd deployment deploy`, or `dagster-uc -e prd deployment deploy` to use the prd config for the deployment.

### Settings defaults

Defaults can be specified for all environments, every key that can be set in the main config can be defined in the defaults. Order of loading config, is defaults -> environment config -> environment variable override.

```yaml
defaults:
repository_root: "."
docker_root: "."
dockerfile: "docker/dev/Dockerfile"
image_prefix: 'team-alpha'
```

### Overriding Config Settings Through Environment Variables

It's possible to dynamically set different values for fields in one of the environment configurations, while loading the config. This can be achieved through environment variables, examples:
Expand Down
5 changes: 5 additions & 0 deletions dagster_uc/_helm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from dagster_uc._helm.client import Client

__all__ = [
"Client",
]
126 changes: 126 additions & 0 deletions dagster_uc/_helm/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import functools
import pathlib
from typing import Any

from dagster_uc._helm.command import Command
from dagster_uc._helm.models import Chart, ReleaseRevision


def mergeconcat(
defaults: dict[Any, Any],
*overrides: dict[Any, Any],
) -> dict[Any, Any]:
"""Deep-merge two or more dictionaries together. Lists are concatenated."""

def mergeconcat2(defaults, overrides): # noqa: ANN001, ANN202
if isinstance(defaults, dict) and isinstance(overrides, dict):
merged = dict(defaults)
for key, value in overrides.items():
if key in defaults:
merged[key] = mergeconcat2(defaults[key], value)
else:
merged[key] = value
return merged
elif isinstance(defaults, list | tuple) and isinstance(overrides, list | tuple):
merged = list(defaults)
merged.extend(overrides)
return merged
else:
return overrides if overrides is not None else defaults

return functools.reduce(mergeconcat2, overrides, defaults) # type: ignore


class Client:
"""Entrypoint for interactions with Helm."""

def __init__(
self,
*,
default_timeout: int | str = "5m",
executable: str = "helm",
history_max_revisions: int = 10,
insecure_skip_tls_verify: bool = False,
kubeconfig: pathlib.Path | None = None,
kubecontext: str | None = None,
unpack_directory: str | None = None,
):
self._command = Command(
default_timeout=default_timeout,
executable=executable,
history_max_revisions=history_max_revisions,
insecure_skip_tls_verify=insecure_skip_tls_verify,
kubeconfig=kubeconfig,
kubecontext=kubecontext,
unpack_directory=unpack_directory,
)

async def get_chart(
self,
chart_ref: pathlib.Path | str,
*,
devel: bool = False,
repo: str | None = None,
version: str | None = None,
) -> Chart:
"""Returns the resolved chart for the given ref, repo and version."""
return Chart(
self._command, # type: ignore
ref=chart_ref,
repo=repo,
# Load the metadata for the specified args
metadata=await self._command.show_chart(
chart_ref,
devel=devel,
repo=repo,
version=version,
),
)

async def install_or_upgrade_release(
self,
release_name: str,
chart: Chart,
*values: dict[str, Any],
atomic: bool = False,
cleanup_on_fail: bool = False,
create_namespace: bool = True,
description: str | None = None,
dry_run: bool = False,
force: bool = False,
namespace: str | None = None,
no_hooks: bool = False,
reset_values: bool = False,
reuse_values: bool = False,
skip_crds: bool = False,
timeout: int | str | None = None,
wait: bool = False,
disable_openapi_validation: bool = False,
) -> ReleaseRevision:
"""Install or upgrade the named release using the given chart and values and return
the new revision.
"""
return ReleaseRevision._from_status(
await self._command.install_or_upgrade(
release_name,
chart.ref,
mergeconcat(*values) if values else None,
atomic=atomic,
cleanup_on_fail=cleanup_on_fail,
create_namespace=create_namespace,
description=description,
dry_run=dry_run,
force=force,
namespace=namespace,
no_hooks=no_hooks,
repo=chart.repo,
reset_values=reset_values,
reuse_values=reuse_values,
skip_crds=skip_crds,
timeout=timeout,
version=chart.metadata.version,
wait=wait,
disable_openapi_validation=disable_openapi_validation,
),
self._command,
)
Loading