Skip to content

Commit

Permalink
Add secret support
Browse files Browse the repository at this point in the history
  • Loading branch information
allenporter committed Dec 24, 2023
1 parent ee470f1 commit 0d86014
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 4 deletions.
23 changes: 21 additions & 2 deletions flux_local/git_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
HelmRepository,
Kustomization,
Manifest,
ConfigMap,
Secret,
SECRET_KIND,
)
from .exceptions import InputException
Expand All @@ -73,6 +75,8 @@
KUSTOMIZE_KIND = "Kustomization"
HELM_REPO_KIND = "HelmRepository"
HELM_RELEASE_KIND = "HelmRelease"
CONFIG_MAP_KIND = "ConfigMap"
SECRET_KIND = "Secret"
CLUSTER_POLICY_KIND = "ClusterPolicy"
GIT_REPO_KIND = "GitRepository"
OCI_REPO_KIND = "OCIRepository"
Expand Down Expand Up @@ -509,7 +513,7 @@ async def build_kustomization(
selector: ResourceSelector,
kustomize_flags: list[str],
builder: CachableBuilder,
) -> tuple[Iterable[HelmRepository], Iterable[HelmRelease], Iterable[ClusterPolicy]]:
) -> tuple[Iterable[HelmRepository], Iterable[HelmRelease], Iterable[ClusterPolicy], Iterable[ConfigMap], Iterable[Secret]]:
"""Build helm objects for the Kustomization."""

root: Path = selector.path.root
Expand Down Expand Up @@ -555,6 +559,9 @@ async def build_kustomization(
kinds.append(HELM_REPO_KIND)
if helm_release_selector.enabled:
kinds.append(HELM_RELEASE_KIND)
# Needed for expanding value references
kinds.append(CONFIG_MAP_KIND)
kinds.append(SECRET_KIND)
if cluster_policy_selector.enabled:
kinds.append(CLUSTER_POLICY_KIND)
if selector.doc_visitor:
Expand Down Expand Up @@ -599,6 +606,16 @@ async def build_kustomization(
if doc.get("kind") == CLUSTER_POLICY_KIND
],
),
[
ConfigMap.parse_doc(doc)
for doc in docs
if doc.get("kind") == CONFIG_MAP_KIND
],
[
Secret.parse_doc(doc)
for doc in docs
if doc.get("kind") == SECRET_KIND
],
)


Expand Down Expand Up @@ -653,13 +670,15 @@ async def update_kustomization(cluster: Cluster) -> None:
)
)
results = list(await asyncio.gather(*build_tasks))
for kustomization, (helm_repos, helm_releases, cluster_policies) in zip(
for kustomization, (helm_repos, helm_releases, cluster_policies, config_maps, secrets) in zip(
cluster.kustomizations,
results,
):
kustomization.helm_repos = list(helm_repos)
kustomization.helm_releases = list(helm_releases)
kustomization.cluster_policies = list(cluster_policies)
kustomization.config_maps = list(config_maps)
kustomization.secrets = list(secrets)

kustomization_tasks = []
# Expand and visit Kustomizations
Expand Down
90 changes: 90 additions & 0 deletions flux_local/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,84 @@ def compact_exclude_fields(cls) -> dict[str, Any]:
}


class ConfigMap(BaseManifest):
"""A ConfigMap is an API object used to store data in key-value pairs."""

name: str
"""The name of the kustomization."""

namespace: str | None = None
"""The namespace of the kustomization."""

data: dict[str, Any] | None = None
"""The data in the ConfigMap."""

binaryData: dict[str, Any] | None = None
"""The binary data in the ConfigMap."""

@classmethod
def parse_doc(cls, doc: dict[str, Any]) -> "ConfigMap":
"""Parse a config map object from a kubernetes resource."""
_check_version(doc, "v1")
if not (metadata := doc.get("metadata")):
raise InputException(f"Invalid {cls} missing metadata: {doc}")
if not (name := metadata.get("name")):
raise InputException(f"Invalid {cls} missing metadata.name: {doc}")
namespace = metadata.get("namespace")
return ConfigMap(name=name, namespace=namespace, data=doc.get("data"), binaryData=doc.get("binaryData"))

@classmethod
def compact_exclude_fields(cls) -> dict[str, Any]:
"""Return a dictionary of fields to exclude from compact_dict."""
return {
"data": True,
"binaryData": True,
}


class Secret(BaseManifest):
"""A Secret contains a small amount of sensitive data."""

name: str
"""The name of the kustomization."""

namespace: str | None = None
"""The namespace of the kustomization."""

data: dict[str, Any] | None = None
"""The data in the Secret."""

stringData: dict[str, Any] | None = None
"""The string data in the Secret."""

@classmethod
def parse_doc(cls, doc: dict[str, Any]) -> "Secret":
"""Parse a secret object from a kubernetes resource."""
_check_version(doc, "v1")
if not (metadata := doc.get("metadata")):
raise InputException(f"Invalid {cls} missing metadata: {doc}")
if not (name := metadata.get("name")):
raise InputException(f"Invalid {cls} missing metadata.name: {doc}")
namespace = metadata.get("namespace")
# While secrets are not typically stored in the cluster, we replace with
# placeholder values anyway.
if data := doc.get("data"):
for key, value in data.items():
data[key] = "**PLACEHOLDER**"
if stringData := doc.get("stringData"):
for key, value in stringData.items():
data[key] = "**PLACEHOLDER**"
return Secret(name=name, namespace=namespace, data=data, stringData=stringData)

@classmethod
def compact_exclude_fields(cls) -> dict[str, Any]:
"""Return a dictionary of fields to exclude from compact_dict."""
return {
"data": True,
"stringData": True,
}


class Kustomization(BaseManifest):
"""A Kustomization is a set of declared cluster artifacts.
Expand All @@ -295,6 +373,12 @@ class Kustomization(BaseManifest):
cluster_policies: list[ClusterPolicy] = Field(default_factory=list)
"""The set of ClusterPolicies represented in this kustomization."""

config_maps: list[str] = Field(default_factory=list)
"""The list of config maps referenced in the kustomization."""

secrets: list[str] = Field(default_factory=list)
"""The list of secrets referenced in the kustomization."""

source_path: str | None = None
"""Optional source path for this Kustomization, relative to the build path."""

Expand Down Expand Up @@ -363,6 +447,12 @@ def compact_exclude_fields(cls) -> dict[str, Any]:
"cluster_policies": {
"__all__": ClusterPolicy.compact_exclude_fields(),
},
"config_maps": {
"__all__": ConfigMap.compact_exclude_fields(),
},
"secrets": {
"__all__": Secret.compact_exclude_fields(),
},
"source_path": True,
"source_name": True,
"source_namespace": True,
Expand Down
3 changes: 2 additions & 1 deletion tests/testdata/cluster8/apps/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ kind: Kustomization
resources:
- pods.yaml
- podinfo.yaml
- podinfo-values.yaml
- podinfo-values.yaml
- podinfo-tls-values.yaml
7 changes: 7 additions & 0 deletions tests/testdata/cluster8/apps/podinfo-tls-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Secret
metadata:
name: podinfo-tls-values
data:
crt: dmFsdWUtMg0KDQo=
2 changes: 1 addition & 1 deletion tests/testdata/cluster8/apps/podinfo-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ data:
- host: podinfo.production
paths:
- path: /
pathType: ImplementationSpecific
pathType: ImplementationSpecific

0 comments on commit 0d86014

Please sign in to comment.