diff --git a/README.md b/README.md index 50260f49..553d7f08 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ For more information about communication, see the [Ansible communication guide]( ## Requirements -### Ansible version compatibility +## Ansible version compatibility This collection has been tested against following Ansible versions: **>=2.15.0**. @@ -47,28 +47,28 @@ This collection supports Kubernetes versions >= 1.24. Click on the name of a plugin or module to view that content's documentation: -#### Connection plugins +### Connection plugins Name | Description --- | --- [kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes. -#### K8s filter plugins +### K8s filter plugins Name | Description --- | --- kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret -#### Inventory plugins +### Inventory plugins Name | Description --- | --- [kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source -#### Lookup plugins +### Lookup plugins Name | Description --- | --- [kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API [kubernetes.core.kustomize](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kustomize_lookup.rst)|Build a set of kubernetes resources using a 'kustomization.yaml' file. -#### Modules +### Modules Name | Description --- | --- [kubernetes.core.helm](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_module.rst)|Manages Kubernetes packages with the Helm package manager @@ -76,6 +76,7 @@ Name | Description [kubernetes.core.helm_plugin](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_module.rst)|Manage Helm plugins [kubernetes.core.helm_plugin_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_info_module.rst)|Gather information about Helm plugins [kubernetes.core.helm_pull](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_pull_module.rst)|download a chart from a repository and (optionally) unpack it in local directory. +[kubernetes.core.helm_registry_auth](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_registry_auth_module.rst)|Helm registry authentication module [kubernetes.core.helm_repository](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_repository_module.rst)|Manage Helm repositories. [kubernetes.core.helm_template](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_template_module.rst)|Render chart templates [kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_module.rst)|Manage Kubernetes (K8s) objects diff --git a/changelogs/fragments/20241116-helm_registry_auth.yaml b/changelogs/fragments/20241116-helm_registry_auth.yaml new file mode 100644 index 00000000..b4391462 --- /dev/null +++ b/changelogs/fragments/20241116-helm_registry_auth.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: + - new module helm_registry_auth to support helm registry login and logout operations. diff --git a/docs/kubernetes.core.helm_registry_auth_module.rst b/docs/kubernetes.core.helm_registry_auth_module.rst new file mode 100644 index 00000000..cd4cbd05 --- /dev/null +++ b/docs/kubernetes.core.helm_registry_auth_module.rst @@ -0,0 +1,346 @@ +.. _kubernetes.core.helm_registry_auth_module: + + +********************************** +kubernetes.core.helm_registry_auth +********************************** + +**Helm registry authentication module** + + +Version added: 5.1.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- Helm registry authentication module allows you to login ``helm registry login`` and logout ``helm registry logout`` from a Helm registry. + + + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- helm (https://github.com/helm/helm/releases) + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+
+ binary_path + +
+ path +
+
+ +
The path of a helm binary to use.
+
+
+ ca_file + +
+ path +
+
+ +
Path to the CA certificate SSL file for verify registry server certificate.
+
+
+ cert_file + +
+ path +
+
+ +
Path to the client certificate SSL file for identify registry client using this certificate file.
+
+
+ host + +
+ string + / required +
+
+ +
Provide a URL for accessing the registry.
+

aliases: registry_url
+
+
+ insecure + +
+ boolean +
+
+
    Choices: +
  • no ←
  • +
  • yes
  • +
+
+
Allow connections to SSL sites without certs.
+
+
+ key_file + +
+ path +
+
+ +
Path to the client key SSL file for identify registry client using this key file.
+
+
+ password + +
+ string +
+
+ +
Password for the registry.
+

aliases: repo_password
+
+
+ state + +
+ string +
+
+
    Choices: +
  • present ←
  • +
  • absent
  • +
+
+
Desired state of the registry.
+
If set to present attempt to log in to the remote registry server using the URL specified in host.
+
If set to absent attempt to log out from the remote registry server using the URL specified in host.
+
+
+ username + +
+ string +
+
+ +
Username for the registry.
+

aliases: repo_username
+
+
+ + + + +Examples +-------- + +.. code-block:: yaml + + - name: Login to remote registry + kubernetes.core.helm_registry_auth: + username: admin + password: "sample_password" + host: localhost:5000 + + - name: Logout from remote registry + kubernetes.core.helm_registry_auth: + state: absent + host: localhost:5000 + + + +Return Values +------------- +Common return values are documented `here `_, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+
+ changed + +
+ boolean +
+
always +
+
+
+ command + +
+ string +
+
always +
Full `helm` command executed
+
+
Sample:
+
/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure
+
+
+ failed + +
+ boolean +
+
always +
Indicate if the `helm` command failed
+
+
+
+ stderr + +
+ string +
+
always +
Full `helm` command stderr, in case you want to display it or examine the event log. Please be note that helm binnary may print messages to stderr even if the command is successful.
+
+
Sample:
+
Login Succeeded\n
+
+
+ stderr_lines + +
+ list +
+
always +
Full `helm` command stderr, in case you want to display it or examine the event log
+
+
+
+ stdout + +
+ string +
+
always +
Full `helm` command stdout, in case you want to display it or examine the event log
+
+
+
+ stout_lines + +
+ list +
+
always +
Full `helm` command stdout, in case you want to display it or examine the event log
+
+
+

+ + +Status +------ + + +Authors +~~~~~~~ + +- Yuriy Novostavskiy (@yurnov) diff --git a/plugins/module_utils/helm.py b/plugins/module_utils/helm.py index 4318ff08..0f58267b 100644 --- a/plugins/module_utils/helm.py +++ b/plugins/module_utils/helm.py @@ -159,11 +159,11 @@ class AnsibleHelmModule(object): self.helm_env = self._prepare_helm_environment() return self.helm_env - def run_helm_command(self, command, fails_on_error=True): + def run_helm_command(self, command, fails_on_error=True, data=None): if not HAS_YAML: self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR) - rc, out, err = self.run_command(command, environ_update=self.env_update) + rc, out, err = self.run_command(command, environ_update=self.env_update, data=data) if fails_on_error and rc != 0: self.fail_json( msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format( diff --git a/plugins/modules/helm_registry_auth.py b/plugins/modules/helm_registry_auth.py new file mode 100644 index 00000000..52885d4d --- /dev/null +++ b/plugins/modules/helm_registry_auth.py @@ -0,0 +1,252 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Yuriy Novostavskiy <@yurnov> +# 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_registry_auth + +short_description: Helm registry authentication module + +version_added: 5.1.0 + +author: + - Yuriy Novostavskiy (@yurnov) + +requirements: + - "helm (https://github.com/helm/helm/releases)" + +description: + - Helm registry authentication module allows you to login C(helm registry login) and logout C(helm registry logout) from a Helm registry. + +options: + state: + description: + - Desired state of the registry. + - If set to C(present) attempt to log in to the remote registry server using the URL specified in I(host). + - If set to C(absent) attempt to log out from the remote registry server using the URL specified in I(host). + required: false + default: present + choices: ['present', 'absent'] + type: str + host: + description: + - Provide a URL for accessing the registry. + required: true + aliases: [ registry_url ] + type: str + insecure: + description: + - Allow connections to SSL sites without certs. + required: false + default: false + type: bool + username: + description: + - Username for the registry. + required: false + type: str + aliases: [ repo_username ] + password: + description: + - Password for the registry. + required: false + type: str + aliases: [ repo_password ] + key_file: + description: + - Path to the client key SSL file for identify registry client using this key file. + required: false + type: path + cert_file: + description: + - Path to the client certificate SSL file for identify registry client using this certificate file. + required: false + type: path + ca_file: + description: + - Path to the CA certificate SSL file for verify registry server certificate. + required: false + type: path + binary_path: + description: + - The path of a helm binary to use. + required: false + type: path +""" + +EXAMPLES = r""" +- name: Login to remote registry + kubernetes.core.helm_registry_auth: + username: admin + password: "sample_password" + host: localhost:5000 + +- name: Logout from remote registry + kubernetes.core.helm_registry_auth: + state: absent + host: localhost:5000 +""" + +RETURN = r""" +stdout: + type: str + description: Full `helm` command stdout, in case you want to display it or examine the event log + returned: always +stout_lines: + type: list + description: Full `helm` command stdout, in case you want to display it or examine the event log + returned: always +stderr: + type: str + description: Full `helm` command stderr, in case you want to display it or examine the event log. Please be note that helm binnary may print messages to stderr even if the command is successful. + returned: always + sample: 'Login Succeeded\n' +stderr_lines: + type: list + description: Full `helm` command stderr, in case you want to display it or examine the event log + returned: always +command: + type: str + description: Full `helm` command executed + returned: always + sample: '/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure' +failed: + type: bool + description: Indicate if the `helm` command failed + returned: always + sample: false +changed: + type: bool + returned: always +""" + +import copy +import traceback + + +from ansible.module_utils.basic import missing_required_lib +from ansible.module_utils.common.process import get_bin_path +from ansible_collections.kubernetes.core.plugins.module_utils.helm import ( + AnsibleHelmModule, +) +from ansible_collections.kubernetes.core.plugins.module_utils.helm_args_common import ( + HELM_AUTH_ARG_SPEC, + HELM_AUTH_MUTUALLY_EXCLUSIVE, +) + + +def argument_spec(): + arg_spec = copy.deepcopy(HELM_AUTH_ARG_SPEC) + arg_spec.update( + dict( + host=dict(type="str", aliases=["registry_url"], required=True), + state=dict( + default="present", choices=["present", "absent"], required=False + ), + insecure=dict(type="bool", default=False, required=False), + username=dict(type="str", aliases=["repo_username"], required=False), + password=dict( + type="str", aliases=["repo_password"], no_log=True, required=False + ), + key_file=dict(type="path", required=False), + cert_file=dict(type="path", required=False), + ca_file=dict(type="path", required=False), + ) + ) + return arg_spec + + +def login( + command, + host, + insecure, + username, + password, + key_file, + cert_file, + ca_file, +): + login_command = command + " registry login " + host + + if username is not None and password is not None: + login_command += " --username=" + username + " --password-stdin" + + if insecure: + login_command += " --insecure" + + if key_file is not None: + login_command += " --key-file=" + key_file + + if cert_file is not None: + login_command += " --cert-file=" + cert_file + + if ca_file is not None: + login_command += " --ca-file=" + ca_file + + return login_command + + +def logout(command, host): + return command + " registry logout " + host + + +def main(): + global module + + module = AnsibleHelmModule( + argument_spec=argument_spec(), + required_together=[["username", "password"]], + mutually_exclusive=HELM_AUTH_MUTUALLY_EXCLUSIVE, + supports_check_mode=True, + ) + + changed = False + + host = module.params.get("host") + state = module.params.get("state") + insecure = module.params.get("insecure") + username = module.params.get("username") + password = module.params.get("password") + key_file = module.params.get("key_file") + cert_file = module.params.get("cert_file") + ca_file = module.params.get("ca_file") + + helm_cmd = module.get_helm_binary() + + if state == "absent": + helm_cmd = logout(helm_cmd, host) + changed = True + elif state == "present": + helm_cmd = login( + helm_cmd, host, insecure, username, password, key_file, cert_file, ca_file + ) + changed = True + + if module.check_mode: + module.exit_json(changed=changed) + # This one is reduntant, but it's here for clarity + elif not changed: + module.exit_json(changed=False) + + rc, out, err = module.run_helm_command(helm_cmd, data=password) + + if rc != 0: + module.fail_json( + msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format( + rc, out, err + ), + command=helm_cmd, + ) + + module.exit_json(changed=changed, stdout=out, stderr=err, command=helm_cmd) + + +if __name__ == "__main__": + main()