diff --git a/modules/applications/helm.nix b/modules/applications/helm.nix index ef411d6..5a944fa 100644 --- a/modules/applications/helm.nix +++ b/modules/applications/helm.nix @@ -49,6 +49,14 @@ in { Whether or not to include CRDs in the helm release. ''; }; + extraOpts = mkOption { + type = with types; listOf str; + default = []; + example = ["--no-hooks"]; + description = '' + Extra options to pass to `helm template` that is run when rendering the helm chart. + ''; + }; transformer = mkOption { type = with types; functionTo (listOf (attrsOf anything)); default = nixidyDefaults.helm.transformer; @@ -70,7 +78,7 @@ in { config = { objects = with lib; - pipe {inherit (config) name namespace chart values includeCRDs;} [ + pipe {inherit (config) name namespace chart values includeCRDs extraOpts;} [ helm.buildHelmChart builtins.readFile kube.fromYAML diff --git a/tests/default.nix b/tests/default.nix index 604fd50..2476c24 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -13,6 +13,7 @@ ./helm/with-values.nix ./helm/transformer.nix ./helm/resource-override.nix + ./helm/extra-opts.nix ./kustomize/base.nix ./kustomize/overlay.nix ./kustomize/resource-override.nix diff --git a/tests/helm/chart/templates/job-hook.yaml b/tests/helm/chart/templates/job-hook.yaml new file mode 100644 index 0000000..02ff067 --- /dev/null +++ b/tests/helm/chart/templates/job-hook.yaml @@ -0,0 +1,21 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: job-hook + annotations: + helm.sh/hook: post-install,post-upgrade + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + template: + metadata: + labels: + {{- include "chart.labels" . | nindent 8 }} + spec: + containers: + - name: {{ .Chart.Name }}-job-hook + image: busybox + command: + - 'sh' + - '-c' + - 'echo The hook Job is running' diff --git a/tests/helm/extra-opts.nix b/tests/helm/extra-opts.nix new file mode 100644 index 0000000..3cec9d0 --- /dev/null +++ b/tests/helm/extra-opts.nix @@ -0,0 +1,128 @@ +{ + lib, + config, + ... +}: let + apps = config.applications; +in { + # Create an application with a helm chart + # with `extraOpts` set + applications.test1.helm.releases.test1 = { + chart = ./chart; + extraOpts = ["--no-hooks"]; + }; + + test = with lib; { + name = "helm chart with extra opts"; + description = "Create an application with Helm chart and adding extra opts."; + assertions = [ + { + description = "Deployment should be rendered correctly."; + + expression = + findFirst + (x: x.kind == "Deployment" && x.metadata.name == "test1-chart") + null + apps.test1.objects; + + expected = { + apiVersion = "apps/v1"; + kind = "Deployment"; + metadata = { + name = "test1-chart"; + namespace = "test1"; + labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + }; + spec = { + replicas = 1; + selector.matchLabels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/name" = "chart"; + }; + template = { + metadata.labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + spec.containers = [ + { + name = "chart"; + image = "nginx:latest"; + ports = [ + { + name = "http"; + containerPort = 80; + protocol = "TCP"; + } + ]; + } + ]; + }; + }; + }; + } + + { + description = "Service should be rendered correctly."; + + expression = + findFirst + (x: x.kind == "Service" && x.metadata.name == "test1-chart") + null + apps.test1.objects; + + expected = { + apiVersion = "v1"; + kind = "Service"; + metadata = { + name = "test1-chart"; + namespace = "test1"; + labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + }; + spec = { + type = "ClusterIP"; + ports = [ + { + port = 80; + targetPort = "http"; + protocol = "TCP"; + name = "http"; + } + ]; + selector = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/name" = "chart"; + }; + }; + }; + } + + { + description = "Job hook should not be rendered at all."; + + expression = + findFirst + (x: x.kind == "Job" && x.metadata.name == "job-hook") + null + apps.test1.objects; + + expected = null; + } + ]; + }; +} diff --git a/tests/helm/no-values.nix b/tests/helm/no-values.nix index 316b6cc..7f28f92 100644 --- a/tests/helm/no-values.nix +++ b/tests/helm/no-values.nix @@ -110,6 +110,57 @@ in { }; }; } + + { + description = "Job hook should be rendered correctly."; + + expression = + findFirst + (x: x.kind == "Job" && x.metadata.name == "job-hook") + null + apps.test1.objects; + + expected = { + apiVersion = "batch/v1"; + kind = "Job"; + metadata = { + name = "job-hook"; + namespace = "test1"; + annotations = { + "helm.sh/hook" = "post-install,post-upgrade"; + }; + labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + }; + spec = { + template = { + metadata.labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + spec.containers = [ + { + name = "chart-job-hook"; + image = "busybox"; + command = [ + "sh" + "-c" + "echo The hook Job is running" + ]; + } + ]; + }; + }; + }; + } ]; }; } diff --git a/tests/helm/transformer.nix b/tests/helm/transformer.nix index 187eab3..d4dec37 100644 --- a/tests/helm/transformer.nix +++ b/tests/helm/transformer.nix @@ -111,6 +111,55 @@ in { }; }; } + + { + description = "Job hook should be rendered correctly."; + + expression = + findFirst + (x: x.kind == "Job" && x.metadata.name == "job-hook") + null + apps.test1.objects; + + expected = { + apiVersion = "batch/v1"; + kind = "Job"; + metadata = { + name = "job-hook"; + namespace = "test1"; + annotations = { + "helm.sh/hook" = "post-install,post-upgrade"; + }; + labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + }; + }; + spec = { + template = { + metadata.labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + spec.containers = [ + { + name = "chart-job-hook"; + image = "busybox"; + command = [ + "sh" + "-c" + "echo The hook Job is running" + ]; + } + ]; + }; + }; + }; + } ]; }; } diff --git a/tests/helm/with-values.nix b/tests/helm/with-values.nix index 6ebb66a..f52ed31 100644 --- a/tests/helm/with-values.nix +++ b/tests/helm/with-values.nix @@ -143,6 +143,57 @@ in { spec.ca.secretName = "ca-key-pair"; }; } + + { + description = "Job hook should be rendered correctly."; + + expression = + findFirst + (x: x.kind == "Job" && x.metadata.name == "job-hook") + null + apps.test1.objects; + + expected = { + apiVersion = "batch/v1"; + kind = "Job"; + metadata = { + name = "job-hook"; + namespace = "test1"; + annotations = { + "helm.sh/hook" = "post-install,post-upgrade"; + }; + labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + }; + spec = { + template = { + metadata.labels = { + "app.kubernetes.io/instance" = "test1"; + "app.kubernetes.io/managed-by" = "Helm"; + "app.kubernetes.io/name" = "chart"; + "app.kubernetes.io/version" = "1.16.0"; + "helm.sh/chart" = "chart-0.1.0"; + }; + spec.containers = [ + { + name = "chart-job-hook"; + image = "busybox"; + command = [ + "sh" + "-c" + "echo The hook Job is running" + ]; + } + ]; + }; + }; + }; + } ]; }; }