mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-27 05:43:02 +00:00
helm - new module to perform helm pull (#410)
helm - new module to perform helm pull Depends-On: ansible/ansible-zuul-jobs#1586 SUMMARY #355 new module to manage chart downloading helm pull ISSUE TYPE Feature Pull Request COMPONENT NAME helm_pull Reviewed-by: Mike Graves <mgraves@redhat.com> Reviewed-by: Bikouo Aubin <None>
This commit is contained in:
@@ -161,10 +161,12 @@ def get_helm_version(module, helm_bin):
|
||||
|
||||
helm_version_command = helm_bin + " version"
|
||||
rc, out, err = module.run_command(helm_version_command)
|
||||
if rc == 0:
|
||||
m = re.match(r'version.BuildInfo{Version:"v([0-9\.]*)",', out)
|
||||
if m:
|
||||
return m.group(1)
|
||||
m = re.match(r'version.BuildInfo{Version:"v([0-9\.]*)",', out)
|
||||
if m:
|
||||
return m.group(1)
|
||||
m = re.match(r'Client: &version.Version{SemVer:"v([0-9\.]*)", ', out)
|
||||
if m:
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
310
plugins/modules/helm_pull.py
Normal file
310
plugins/modules/helm_pull.py
Normal file
@@ -0,0 +1,310 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2022, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
---
|
||||
module: helm_pull
|
||||
short_description: download a chart from a repository and (optionally) unpack it in local directory.
|
||||
version_added: "2.4.0"
|
||||
author:
|
||||
- Aubin Bikouo (@abikouo)
|
||||
description:
|
||||
- Retrieve a package from a package repository, and download it locally.
|
||||
- It can also be used to perform cryptographic verification of a chart without installing the chart.
|
||||
- There are options for unpacking the chart after download.
|
||||
|
||||
requirements:
|
||||
- "helm >= 3.0 (https://github.com/helm/helm/releases)"
|
||||
|
||||
options:
|
||||
chart_ref:
|
||||
description:
|
||||
- chart name on chart repository.
|
||||
- absolute URL.
|
||||
required: true
|
||||
type: str
|
||||
chart_version:
|
||||
description:
|
||||
- Specify a version constraint for the chart version to use.
|
||||
- This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0).
|
||||
- Mutually exclusive with C(chart_devel).
|
||||
type: str
|
||||
verify_chart:
|
||||
description:
|
||||
- Verify the package before using it.
|
||||
default: False
|
||||
type: bool
|
||||
verify_chart_keyring:
|
||||
description:
|
||||
- location of public keys used for verification.
|
||||
type: path
|
||||
provenance:
|
||||
description:
|
||||
- Fetch the provenance file, but don't perform verification.
|
||||
type: bool
|
||||
default: False
|
||||
repo_url:
|
||||
description:
|
||||
- chart repository url where to locate the requested chart.
|
||||
type: str
|
||||
aliases: [ url, chart_repo_url ]
|
||||
repo_username:
|
||||
description:
|
||||
- Chart repository username where to locate the requested chart.
|
||||
- Required if C(repo_password) is specified.
|
||||
type: str
|
||||
aliases: [ username, chart_repo_username ]
|
||||
repo_password:
|
||||
description:
|
||||
- Chart repository password where to locate the requested chart.
|
||||
- Required if C(repo_username) is specified.
|
||||
type: str
|
||||
aliases: [ password, chart_repo_password ]
|
||||
pass_credentials:
|
||||
description:
|
||||
- Pass credentials to all domains.
|
||||
default: False
|
||||
type: bool
|
||||
skip_tls_certs_check:
|
||||
description:
|
||||
- Whether or not to check tls certificate for the chart download.
|
||||
- Requires helm >= 3.3.0.
|
||||
type: bool
|
||||
default: False
|
||||
chart_devel:
|
||||
description:
|
||||
- Use development versions, too. Equivalent to version '>0.0.0-0'.
|
||||
- Mutually exclusive with C(chart_version).
|
||||
type: bool
|
||||
untar_chart:
|
||||
description:
|
||||
- if set to true, will untar the chart after downloading it.
|
||||
type: bool
|
||||
default: False
|
||||
destination:
|
||||
description:
|
||||
- location to write the chart.
|
||||
type: path
|
||||
required: True
|
||||
chart_ca_cert:
|
||||
description:
|
||||
- Verify certificates of HTTPS-enabled servers using this CA bundle.
|
||||
- Requires helm >= 3.1.0.
|
||||
type: path
|
||||
chart_ssl_cert_file:
|
||||
description:
|
||||
- Identify HTTPS client using this SSL certificate file.
|
||||
- Requires helm >= 3.1.0.
|
||||
type: path
|
||||
chart_ssl_key_file:
|
||||
description:
|
||||
- Identify HTTPS client using this SSL key file
|
||||
- Requires helm >= 3.1.0.
|
||||
type: path
|
||||
binary_path:
|
||||
description:
|
||||
- The path of a helm binary to use.
|
||||
required: false
|
||||
type: path
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
- name: Download chart using chart url
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: /path/to/chart
|
||||
|
||||
- name: Download Chart using chart_name and repo_url
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: redis
|
||||
repo_url: https://charts.bitnami.com/bitnami
|
||||
untar_chart: yes
|
||||
destination: /path/to/chart
|
||||
|
||||
- name: Download Chart (skip tls certificate check)
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: redis
|
||||
repo_url: https://charts.bitnami.com/bitnami
|
||||
untar_chart: yes
|
||||
destination: /path/to/chart
|
||||
skip_tls_certs_check: yes
|
||||
|
||||
- name: Download Chart using chart registry credentials
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: redis
|
||||
repo_url: https://charts.bitnami.com/bitnami
|
||||
untar_chart: yes
|
||||
destination: /path/to/chart
|
||||
username: myuser
|
||||
password: mypassword123
|
||||
"""
|
||||
|
||||
RETURN = r"""
|
||||
stdout:
|
||||
type: str
|
||||
description: Full `helm pull` command stdout, in case you want to display it or examine the event log
|
||||
returned: always
|
||||
sample: ''
|
||||
stderr:
|
||||
type: str
|
||||
description: Full `helm pull` command stderr, in case you want to display it or examine the event log
|
||||
returned: always
|
||||
sample: ''
|
||||
command:
|
||||
type: str
|
||||
description: Full `helm pull` command built by this module, in case you want to re-run the command outside the module or debug a problem.
|
||||
returned: always
|
||||
sample: helm pull --repo test ...
|
||||
rc:
|
||||
type: int
|
||||
description: Helm pull command return code
|
||||
returned: always
|
||||
sample: 1
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
||||
run_helm,
|
||||
get_helm_version,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||
LooseVersion,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argspec = dict(
|
||||
chart_ref=dict(type="str", required=True),
|
||||
chart_version=dict(type="str"),
|
||||
verify_chart=dict(type="bool", default=False),
|
||||
verify_chart_keyring=dict(type="path"),
|
||||
provenance=dict(type="bool", default=False),
|
||||
repo_url=dict(type="str", aliases=["url", "chart_repo_url"]),
|
||||
repo_username=dict(type="str", aliases=["username", "chart_repo_username"]),
|
||||
repo_password=dict(
|
||||
type="str", no_log=True, aliases=["password", "chart_repo_password"]
|
||||
),
|
||||
pass_credentials=dict(type="bool", default=False),
|
||||
skip_tls_certs_check=dict(type="bool", default=False),
|
||||
chart_devel=dict(type="bool"),
|
||||
untar_chart=dict(type="bool", default=False),
|
||||
destination=dict(type="path", required=True),
|
||||
chart_ca_cert=dict(type="path"),
|
||||
chart_ssl_cert_file=dict(type="path"),
|
||||
chart_ssl_key_file=dict(type="path"),
|
||||
binary_path=dict(type="path"),
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec=argspec,
|
||||
supports_check_mode=True,
|
||||
required_by=dict(
|
||||
repo_username=("repo_password"),
|
||||
repo_password=("repo_username"),
|
||||
),
|
||||
mutually_exclusive=[("chart_version", "chart_devel")],
|
||||
)
|
||||
|
||||
bin_path = module.params.get("binary_path")
|
||||
if bin_path is not None:
|
||||
helm_cmd_common = bin_path
|
||||
else:
|
||||
helm_cmd_common = "helm"
|
||||
|
||||
helm_cmd_common = module.get_bin_path(helm_cmd_common, required=True)
|
||||
|
||||
helm_version = get_helm_version(module, helm_cmd_common)
|
||||
if LooseVersion(helm_version) < LooseVersion("3.0.0"):
|
||||
module.fail_json(
|
||||
msg="This module requires helm >= 3.0.0, current version is {0}".format(
|
||||
helm_version
|
||||
)
|
||||
)
|
||||
|
||||
helm_pull_opt_versionning = dict(
|
||||
skip_tls_certs_check="3.3.0",
|
||||
chart_ca_cert="3.1.0",
|
||||
chart_ssl_cert_file="3.1.0",
|
||||
chart_ssl_key_file="3.1.0",
|
||||
)
|
||||
|
||||
def test_version_requirement(opt):
|
||||
req_version = helm_pull_opt_versionning.get(opt)
|
||||
if req_version and LooseVersion(helm_version) < LooseVersion(req_version):
|
||||
module.fail_json(
|
||||
msg="Parameter {0} requires helm >= {1}, current version is {2}".format(
|
||||
opt, req_version, helm_version
|
||||
)
|
||||
)
|
||||
|
||||
# Set `helm pull` arguments requiring values
|
||||
helm_pull_opts = []
|
||||
|
||||
helm_value_args = dict(
|
||||
chart_version="version",
|
||||
verify_chart_keyring="keyring",
|
||||
repo_url="repo",
|
||||
repo_username="username",
|
||||
repo_password="password",
|
||||
destination="destination",
|
||||
chart_ca_cert="ca-file",
|
||||
chart_ssl_cert_file="cert-file",
|
||||
chart_ssl_key_file="key-file",
|
||||
)
|
||||
|
||||
for opt, cmdkey in helm_value_args.items():
|
||||
if module.params.get(opt):
|
||||
test_version_requirement(opt)
|
||||
helm_pull_opts.append("--{0} {1}".format(cmdkey, module.params.get(opt)))
|
||||
|
||||
# Set `helm pull` arguments flags
|
||||
helm_flag_args = dict(
|
||||
verify_chart=dict(key="verify"),
|
||||
provenance=dict(key="prov"),
|
||||
pass_credentials=dict(key="pass-credentials"),
|
||||
skip_tls_certs_check=dict(key="insecure-skip-tls-verify"),
|
||||
chart_devel=dict(key="devel"),
|
||||
untar_chart=dict(key="untar"),
|
||||
)
|
||||
|
||||
for k, v in helm_flag_args.items():
|
||||
if module.params.get(k):
|
||||
test_version_requirement(k)
|
||||
helm_pull_opts.append("--{0}".format(v["key"]))
|
||||
|
||||
helm_cmd_common = "{0} pull {1} {2}".format(
|
||||
helm_cmd_common, module.params.get("chart_ref"), " ".join(helm_pull_opts)
|
||||
)
|
||||
if not module.check_mode:
|
||||
rc, out, err = run_helm(module, helm_cmd_common, fails_on_error=False)
|
||||
else:
|
||||
rc, out, err = (0, "", "")
|
||||
|
||||
if rc == 0:
|
||||
module.exit_json(
|
||||
failed=False,
|
||||
changed=True,
|
||||
command=helm_cmd_common,
|
||||
stdout=out,
|
||||
stderr=err,
|
||||
rc=rc,
|
||||
)
|
||||
else:
|
||||
module.fail_json(
|
||||
msg="Failure when executing Helm command.",
|
||||
command=helm_cmd_common,
|
||||
changed=False,
|
||||
stdout=out,
|
||||
stderr=err,
|
||||
rc=rc,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,8 +1,9 @@
|
||||
# slow - 11min
|
||||
slow
|
||||
time=313
|
||||
time=334
|
||||
helm_info
|
||||
helm_plugin
|
||||
helm_plugin_info
|
||||
helm_repository
|
||||
helm_template
|
||||
helm_pull
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
- name: Test in-memory kubeconfig
|
||||
include_tasks: tests_in_memory_kubeconfig.yml
|
||||
|
||||
- name: Test helm pull
|
||||
include_tasks: tests_helm_pull.yml
|
||||
|
||||
- name: Clean helm install
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
|
||||
232
tests/integration/targets/helm/tasks/tests_helm_pull.yml
Normal file
232
tests/integration/targets/helm/tasks/tests_helm_pull.yml
Normal file
@@ -0,0 +1,232 @@
|
||||
---
|
||||
- name: Define helm versions to test
|
||||
set_fact:
|
||||
helm_versions:
|
||||
- 3.8.0
|
||||
- 3.1.0
|
||||
- 3.0.0
|
||||
- 2.3.0
|
||||
|
||||
- block:
|
||||
- name: Create temp directory for helm tests
|
||||
tempfile:
|
||||
state: directory
|
||||
register: tmpdir
|
||||
|
||||
- name: Set temp directory fact
|
||||
set_fact:
|
||||
temp_dir: "{{ tmpdir.path }}"
|
||||
|
||||
- set_fact:
|
||||
destination: "{{ temp_dir }}"
|
||||
|
||||
- name: Create Helm directories
|
||||
file:
|
||||
state: directory
|
||||
path: "{{ temp_dir }}/{{ item }}"
|
||||
with_items: "{{ helm_versions }}"
|
||||
|
||||
- name: Unarchive Helm binary
|
||||
unarchive:
|
||||
src: "https://get.helm.sh/helm-v{{ item }}-linux-amd64.tar.gz"
|
||||
dest: "{{ temp_dir }}/{{ item }}"
|
||||
remote_src: yes
|
||||
with_items: "{{ helm_versions }}"
|
||||
|
||||
# Testing helm pull with helm version == 2.3.0
|
||||
- block:
|
||||
- name: Assert that helm pull failed with helm <= 3.0.0
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
ignore_errors: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is failed
|
||||
- _result.msg == "This module requires helm >= 3.0.0, current version is 2.3.0"
|
||||
|
||||
vars:
|
||||
helm_path: "{{ temp_dir }}/2.3.0/linux-amd64/helm"
|
||||
|
||||
# Testing helm pull with helm version == 3.0.0
|
||||
- block:
|
||||
- name: Download chart using chart_ssl_cert_file
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
chart_ssl_cert_file: ssl_cert_file
|
||||
ignore_errors: true
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is failed
|
||||
- _result.msg == "Parameter chart_ssl_cert_file requires helm >= 3.1.0, current version is 3.0.0"
|
||||
|
||||
- name: Download chart using chart_ssl_key_file
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
chart_ssl_key_file: ssl_key_file
|
||||
ignore_errors: true
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is failed
|
||||
- _result.msg == "Parameter chart_ssl_key_file requires helm >= 3.1.0, current version is 3.0.0"
|
||||
|
||||
- name: Download chart using chart_ca_cert
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
chart_ca_cert: ca_cert_file
|
||||
ignore_errors: true
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is failed
|
||||
- _result.msg == "Parameter chart_ca_cert requires helm >= 3.1.0, current version is 3.0.0"
|
||||
|
||||
vars:
|
||||
helm_path: "{{ temp_dir }}/3.0.0/linux-amd64/helm"
|
||||
|
||||
# Testing helm pull with helm version == 3.1.0
|
||||
- block:
|
||||
- name: Download chart using chart_ssl_cert_file, chart_ca_cert, chart_ssl_key_file
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
chart_ssl_cert_file: ssl_cert_file
|
||||
chart_ssl_key_file: ssl_key_file
|
||||
chart_ca_cert: ca_cert_file
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is changed
|
||||
- '"--ca-file ca_cert_file" in _result.command'
|
||||
- '"--cert-file ssl_cert_file" in _result.command'
|
||||
- '"--key-file ssl_key_file" in _result.command'
|
||||
|
||||
- name: Download chart using skip_tls_certs_check
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
skip_tls_certs_check: true
|
||||
ignore_errors: true
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- name: assert that module failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- _result is failed
|
||||
- _result.msg == "Parameter skip_tls_certs_check requires helm >= 3.3.0, current version is 3.1.0"
|
||||
|
||||
vars:
|
||||
helm_path: "{{ temp_dir }}/3.1.0/linux-amd64/helm"
|
||||
|
||||
# Testing helm pull with helm version == 3.8.0
|
||||
- block:
|
||||
# Test options chart_version, verify, pass-credentials, provenance, untar_chart
|
||||
# skip_tls_certs_check, repo_url, repo_username, repo_password
|
||||
- name: Testing chart version
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: redis
|
||||
destination: "{{ destination }}"
|
||||
chart_version: "0.2.1"
|
||||
verify_chart: true
|
||||
pass_credentials: true
|
||||
provenance: true
|
||||
untar_chart: true
|
||||
skip_tls_certs_check: true
|
||||
repo_url: "https://charts.bitnami.com/bitnami"
|
||||
repo_username: ansible
|
||||
repo_password: testing123
|
||||
verify_chart_keyring: pubring.gpg
|
||||
check_mode: true
|
||||
register: _result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- _result is changed
|
||||
- '"--version 0.2.1" in _result.command'
|
||||
- '"--verify" in _result.command'
|
||||
- '"--pass-credentials" in _result.command'
|
||||
- '"--prov" in _result.command'
|
||||
- '"--untar" in _result.command'
|
||||
- '"--insecure-skip-tls-verify" in _result.command'
|
||||
- '"--repo https://charts.bitnami.com/bitnami" in _result.command'
|
||||
- '"--username ansible" in _result.command'
|
||||
- '"--password ***" in _result.command'
|
||||
- '"--keyring pubring.gpg" in _result.command'
|
||||
|
||||
- name: Download chart using chart_ref
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||
destination: "{{ destination }}"
|
||||
register: _result
|
||||
|
||||
- name: Check chart on local filesystem
|
||||
stat:
|
||||
path: "{{ destination }}/grafana-5.6.0.tgz"
|
||||
register: _chart
|
||||
|
||||
- name: Validate that chart was downloaded
|
||||
assert:
|
||||
that:
|
||||
- _result is changed
|
||||
- _chart.stat.exists
|
||||
- _chart.stat.isreg
|
||||
|
||||
- name: Download chart using untar_chart
|
||||
kubernetes.core.helm_pull:
|
||||
binary_path: "{{ helm_path }}"
|
||||
chart_ref: redis
|
||||
destination: "{{ destination }}"
|
||||
repo_url: "https://charts.bitnami.com/bitnami"
|
||||
untar_chart: true
|
||||
register: _result
|
||||
|
||||
- name: Check chart on local filesystem
|
||||
stat:
|
||||
path: "{{ destination }}/redis"
|
||||
register: _chart
|
||||
|
||||
- name: Validate that chart was downloaded
|
||||
assert:
|
||||
that:
|
||||
- _result is changed
|
||||
- _chart.stat.exists
|
||||
- _chart.stat.isdir
|
||||
|
||||
vars:
|
||||
helm_path: "{{ temp_dir }}/3.8.0/linux-amd64/helm"
|
||||
|
||||
|
||||
always:
|
||||
- name: Delete temp directory
|
||||
file:
|
||||
state: absent
|
||||
path: "{{ temp_dir }}"
|
||||
Reference in New Issue
Block a user