Skip to content

Commit

Permalink
Allow mounting secrets as env or file for image processes
Browse files Browse the repository at this point in the history
  • Loading branch information
totycro committed Jun 26, 2024
1 parent 7db4dc2 commit a21ee9b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 37 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 1.2.5
Save execution parameters for image processes
* Save execution parameters for image processes
* Allow mounting secrets as env or file for image processes

## 1.2.4
* Implement failed/success notifications
Expand Down
37 changes: 37 additions & 0 deletions pygeoapi_kubernetes_papermill/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ContainerKubernetesProcessorMixin:
extra_volume_mounts: list
allow_fargate: bool
tolerations: list
secrets: list[dict[str, str]]

def _extra_podspec(self, requested: Any):
extra_podspec: dict[str, Any] = {
Expand Down Expand Up @@ -165,6 +166,14 @@ def extra_configs() -> Iterable[ExtraConfig]:
s3_url=self.s3["s3_url"],
)

access_functions = {
"env": extra_secret_env_config,
"mount": extra_secret_mount_config,
}
for num, secret in enumerate(self.secrets):
access_fun = access_functions[secret.get("access", "mount")]
yield access_fun(secret_name=secret["name"], num=num)

return functools.reduce(operator.add, extra_configs(), ExtraConfig())


Expand Down Expand Up @@ -312,3 +321,31 @@ def setup_byoa_results_dir_cmd(
f'ln -sf --no-dereference "{path_to_subdir}" "{result_data_path}" && '
# NOTE: no-dereference is useful if home is a persisted mounted volume
)


def extra_secret_mount_config(secret_name: str, num: int) -> ExtraConfig:
volume_name = f"secret-{num}"
return ExtraConfig(
volumes=[
k8s_client.V1Volume(
secret=k8s_client.V1SecretVolumeSource(secret_name=secret_name),
name=volume_name,
)
],
volume_mounts=[
k8s_client.V1VolumeMount(
mount_path=str(PurePath("/secret") / secret_name),
name=volume_name,
)
],
)


def extra_secret_env_config(secret_name: str, num: int) -> ExtraConfig:
return ExtraConfig(
env_from=[
k8s_client.V1EnvFromSource(
secret_ref=k8s_client.V1SecretEnvSource(name=secret_name)
)
]
)
2 changes: 2 additions & 0 deletions pygeoapi_kubernetes_papermill/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def __init__(self, processor_def: dict) -> None:
self.tolerations: list = processor_def["tolerations"]
self.allow_fargate: bool = processor_def["allow_fargate"]
self.parameters_env: dict[str, str] = processor_def["parameters_env"]
self.secrets = processor_def["secrets"]

def create_job_pod_spec(
self,
Expand Down Expand Up @@ -145,6 +146,7 @@ def create_job_pod_spec(
to_k8s_env(requested.parameters_env) if requested.parameters_env else []
)
+ to_k8s_env(self.parameters_env),
env_from=extra_config.env_from,
)

return KubernetesProcessor.JobPodSpec(
Expand Down
36 changes: 0 additions & 36 deletions pygeoapi_kubernetes_papermill/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,6 @@ def extra_configs() -> Iterable[ExtraConfig]:
for num, extra_pvc in enumerate(self.extra_pvcs)
)

access_functions = {
"env": extra_secret_env_config,
"mount": extra_secret_mount_config,
}
for num, secret in enumerate(self.secrets):
access_fun = access_functions[secret.get("access", "mount")]
yield access_fun(secret_name=secret["name"], num=num)

if self.auto_mount_secrets:
yield extra_auto_secrets()

Expand Down Expand Up @@ -619,34 +611,6 @@ def extra_pvc_config(extra_pvc: dict) -> ExtraConfig:
)


def extra_secret_mount_config(secret_name: str, num: int) -> ExtraConfig:
volume_name = f"secret-{num}"
return ExtraConfig(
volumes=[
k8s_client.V1Volume(
secret=k8s_client.V1SecretVolumeSource(secret_name=secret_name),
name=volume_name,
)
],
volume_mounts=[
k8s_client.V1VolumeMount(
mount_path=str(PurePath("/secret") / secret_name),
name=volume_name,
)
],
)


def extra_secret_env_config(secret_name: str, num: int) -> ExtraConfig:
return ExtraConfig(
env_from=[
k8s_client.V1EnvFromSource(
secret_ref=k8s_client.V1SecretEnvSource(name=secret_name)
)
]
)


def extra_auto_secrets() -> ExtraConfig:
secrets: k8s_client.V1SecretList = k8s_client.CoreV1Api().list_namespaced_secret(
namespace=current_namespace()
Expand Down
9 changes: 9 additions & 0 deletions tests/test_image_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def _create_processor(def_override=None):
"tolerations": [],
"allow_fargate": False,
"parameters_env": {},
"secrets": [],
**(def_override if def_override else {}),
}
)
Expand Down Expand Up @@ -121,3 +122,11 @@ def test_env_parameters_are_saved_as_json(create_processor, create_pod_kwargs_wi
**create_pod_kwargs_with({"parameters_env": {"a": "b"}})
)
assert spec.extra_annotations["parameters"] == '{"a": "b"}'


def test_secrets_can_be_injected_via_env_vars(create_processor, create_pod_kwargs):
spec = create_processor(
{"secrets": [{"name": "secA", "access": "env"}]}
).create_job_pod_spec(**create_pod_kwargs)

assert "secA" == spec.pod_spec.containers[0].env_from[0].secret_ref.name

0 comments on commit a21ee9b

Please sign in to comment.