From 508ecb15643549c0ec8f575d5f8a4a66520e7604 Mon Sep 17 00:00:00 2001 From: Luis Buriola Date: Wed, 22 Mar 2023 20:01:45 +0000 Subject: [PATCH] Simplify input type Helm #977 --- docs/pages/input_types/helm.md | 36 +++++++++++-------- kapitan/inputs/base.py | 7 +++- kapitan/inputs/helm.py | 13 +++++-- kapitan/targets.py | 2 +- tests/test_helm_input.py | 14 +++----- .../targets/acs-engine-autoscaler.yml | 8 +++++ 6 files changed, 51 insertions(+), 29 deletions(-) diff --git a/docs/pages/input_types/helm.md b/docs/pages/input_types/helm.md index 2f5723c35..776a555c0 100644 --- a/docs/pages/input_types/helm.md +++ b/docs/pages/input_types/helm.md @@ -1,6 +1,7 @@ # :kapitan-logo: **Input Type | Helm** -This is a Python binding to `helm template` command for users with helm charts. This does not require the helm executable, and the templates are rendered without the Tiller server. +This is a Python binding to `helm template` command for users with helm charts. This requires the `helm` binary to be installed locally. +If you're using the kapitan docker image, then the `helm` binary is already instealled inside the image. Unlike other input types, Helm input types support the following additional parameters under `kapitan.compile`: @@ -25,11 +26,29 @@ parameters: … ``` +Alternatively, instead of using a local `chart_path`, you can omit the `input_path` and specify the URL and chart name directly + +```yaml +parameters: + kapitan: + compile: + - output_path: + input_type: helm + helm_params: + repo: https://charts.jetstack.io + chart_name: cert-manager + version: 1.1.0 + … +``` + `helm_values` is an object containing values specified that will override the default values in the input chart. This has exactly the same effect as specifying `--values custom_values.yml` for `helm template` command where `custom_values.yml` structure mirrors that of `helm_values`. `helm_values_files` is an array containing the paths to [helm values files](https://helm.sh/docs/chart_template_guide/values_files/) used as input for the chart. This has exactly the same effect as specifying `--file my_custom_values.yml` for the `helm template` command where `my_custom_values.yml` is a helm values file. + If the same keys exist in `helm_values` and in multiple specified `helm_values_files`, the last indexed file in the `helm_values_files` will take precedence followed by the preceding `helm_values_files` and at the bottom the `helm_values` defined in teh compile block. + There is an example in the tests. The `monitoring-dev`(kapitan/tests/test_resources/inventory/targets/monitoring-dev.yml) and `monitoring-prd`(kapitan/tests/test_resources/inventory/targets/monitoring-prd.yml) targets both use the `monitoring`(tests/test_resources/inventory/classes/component/monitoring.yml) component. + This component has helm chart input and takes a `common.yml` helm_values file which is "shared" by any target that uses the component and it also takes a dynamically defined file based on a kapitan variable defined in the target. `helm_path` can be use to provide the helm binary name or path. @@ -55,7 +74,7 @@ Special flags: See the [helm doc](https://helm.sh/docs/helm/helm_template/) for further detail. -#### Example +## Example Let's use [nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress) helm chart as the input. Using [kapitan dependency manager](/external_dependencies.md), this chart can be fetched via a URL as listed in . @@ -107,18 +126,7 @@ $ grep "my-controller" compiled/nginx-from-chart/nginx-ingress/templates/control app: my-controller ``` -#### Building the binding from source - -Run - -```shell -cd kapitan/inputs/helm -./build.sh -``` - -This requires Go 1.14. - -#### Helm subcharts +## Helm subcharts There is an [external dependency manager](/external_dependencies.md) of type `helm` which enables you to specify helm charts to download, including subcharts. diff --git a/kapitan/inputs/base.py b/kapitan/inputs/base.py index 6a4b1efca..c290c395c 100644 --- a/kapitan/inputs/base.py +++ b/kapitan/inputs/base.py @@ -40,7 +40,7 @@ def compile_obj(self, comp_obj, ext_vars, **kwargs): # expand any globbed paths, taking into account provided search paths input_paths = [] - for input_path in comp_obj["input_paths"]: + for input_path in comp_obj.get("input_paths", []): globbed_paths = [glob.glob(os.path.join(path, input_path)) for path in self.search_paths] inputs = list(itertools.chain.from_iterable(globbed_paths)) # remove duplicate inputs @@ -53,6 +53,11 @@ def compile_obj(self, comp_obj, ext_vars, **kwargs): ) input_paths.extend(inputs) + # Enable helm input type to compile without input_paths + # This is when we use helm CLI to download the chart + if input_type == "helm" and "input_paths" not in comp_obj: + self.compile_input_path("", comp_obj, ext_vars, **kwargs) + for input_path in input_paths: self.compile_input_path(input_path, comp_obj, ext_vars, **kwargs) diff --git a/kapitan/inputs/helm.py b/kapitan/inputs/helm.py index 10b4af815..421d91fa0 100644 --- a/kapitan/inputs/helm.py +++ b/kapitan/inputs/helm.py @@ -144,6 +144,7 @@ def render_chart( args = ["template"] name = helm_params.pop("name", None) + chart_name = helm_params.pop("chart_name", None) output_file = helm_params.pop("output_file", None) if helm_flags is None: @@ -208,9 +209,15 @@ def render_chart( if "name_template" not in helm_flags: args.append(name or "--generate-name") - # uses absolute path to make sure helm interprets it as a - # local dir and not a chart_name that it should download. - args.append(chart_dir) + # if chart_name is specified then the last argument to helm_cli is the + # name of the chart we want to use. Otherwise it's the chart_dir that + # was previously downloaded as an external dependency + if chart_name: + args.append(chart_name) + else: + # uses absolute path to make sure helm interprets it as a + # local dir and not a chart_name that it should download. + args.append(chart_dir) # If output_path is '-', output is a string with rendered chart if output_path == "-": diff --git a/kapitan/targets.py b/kapitan/targets.py index 7327fb7d8..cebc75fef 100644 --- a/kapitan/targets.py +++ b/kapitan/targets.py @@ -602,7 +602,7 @@ def valid_target_obj(target_obj, require_compile=True): "suffix_remove": {"type": "boolean"}, "suffix_stripped": {"type": "string"}, }, - "required": ["input_type", "input_paths", "output_path"], + "required": ["input_type", "output_path"], "minItems": 1, "oneOf": [ { diff --git a/tests/test_helm_input.py b/tests/test_helm_input.py index 3cfb23c9e..cbe26d510 100644 --- a/tests/test_helm_input.py +++ b/tests/test_helm_input.py @@ -49,19 +49,13 @@ def test_compile_chart(self): temp = tempfile.mkdtemp() sys.argv = ["kapitan", "compile", "--output-path", temp, "-t", "acs-engine-autoscaler"] main() + base_path = os.path.join(temp, "compiled", "acs-engine-autoscaler") self.assertTrue( - os.path.isfile( - os.path.join( - temp, - "compiled", - "acs-engine-autoscaler", - "acs-engine-autoscaler", - "templates", - "secrets.yaml", - ) - ) + os.path.isfile(os.path.join(base_path, "acs-engine-autoscaler", "templates", "secrets.yaml")) ) + self.assertTrue(os.path.isfile(os.path.join(base_path, "expanded-cert-manager-chart.yaml"))) + def test_compile_subcharts(self): temp = tempfile.mkdtemp() sys.argv = ["kapitan", "compile", "--output-path", temp, "-t", "istio"] diff --git a/tests/test_resources/inventory/targets/acs-engine-autoscaler.yml b/tests/test_resources/inventory/targets/acs-engine-autoscaler.yml index 2112ece46..1750bb7d7 100644 --- a/tests/test_resources/inventory/targets/acs-engine-autoscaler.yml +++ b/tests/test_resources/inventory/targets/acs-engine-autoscaler.yml @@ -8,3 +8,11 @@ parameters: input_type: helm input_paths: - charts/acs-engine-autoscaler + + - output_path: . + input_type: helm + helm_params: + repo: https://charts.jetstack.io + chart_name: cert-manager + version: 1.1.0 + output_file: expanded-cert-manager-chart.yaml