-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add support for helm registry login/logout #601
Changes from all commits
cfa4818
ed90f37
3091c41
bd3c8c1
ffff534
b8dd52c
f7ae788
5f28b2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,178 @@ | ||||||
#!/usr/bin/python | ||||||
# -*- coding: utf-8 -*- | ||||||
|
||||||
# Copyright: (c) 2023, 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_registry_auth | ||||||
|
||||||
short_description: login or logout to a registry. | ||||||
|
||||||
version_added: "2.5.0" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it should be 3.3.0 or even 5.1.0 |
||||||
|
||||||
author: | ||||||
- Aubin Bikouo (@abikouo) | ||||||
|
||||||
requirements: | ||||||
- "helm (https://github.com/helm/helm/releases)" | ||||||
|
||||||
description: | ||||||
- Authenticate to a remote registry analogous to C(helm registry login) | ||||||
or Remove credentials stored for a remote registry analogous to C(helm registry logout). | ||||||
|
||||||
options: | ||||||
state: | ||||||
description: | ||||||
- If set to I(present) attempt to log in to the remote registry server using the URL specified in C(host). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
- If set to I(absent) attempt to log out by removing credentials stored for the remote registry server specified in C(host). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
default: present | ||||||
choices: | ||||||
- present | ||||||
- absent | ||||||
type: str | ||||||
host: | ||||||
description: | ||||||
- Provide a URL for accessing the remote registry. | ||||||
type: str | ||||||
required: True | ||||||
validate_certs: | ||||||
description: | ||||||
- Whether or not to verify the Registry server's SSL certificates. | ||||||
type: bool | ||||||
aliases: [ verify_ssl ] | ||||||
default: True | ||||||
username: | ||||||
description: | ||||||
- Provide a username for authenticating with the remote registry. | ||||||
- Required when C(state) is set to I(present). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
type: str | ||||||
password: | ||||||
description: | ||||||
- Provide a password for authenticating with the remote registry. | ||||||
- Required when C(state) is set to I(present). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
type: str | ||||||
binary_path: | ||||||
description: | ||||||
- The path of a helm binary to use. | ||||||
type: path | ||||||
""" | ||||||
|
||||||
EXAMPLES = r""" | ||||||
# Login to helm registry | ||||||
- name: Login to remote registry | ||||||
kubernetes.core.helm_registry_auth: | ||||||
username: admin | ||||||
password: "sample_password" | ||||||
host: localhost:5000 | ||||||
|
||||||
# Logout from helm registry | ||||||
- name: Logout to Remote registry | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
kubernetes.core.helm_registry_auth: | ||||||
host: localhost:5000 | ||||||
state: absent | ||||||
""" | ||||||
|
||||||
RETURN = r""" | ||||||
stdout: | ||||||
type: str | ||||||
description: Full `helm` command stdout, in case you want to display it or examine the event log | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
returned: always | ||||||
sample: '' | ||||||
stderr: | ||||||
type: str | ||||||
description: Full `helm` command stderr, in case you want to display it or examine the event log | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
returned: always | ||||||
sample: '' | ||||||
command: | ||||||
type: str | ||||||
description: Full `helm` 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 registry login... | ||||||
""" | ||||||
|
||||||
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import ( | ||||||
AnsibleHelmModule, | ||||||
) | ||||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import ( | ||||||
LooseVersion, | ||||||
) | ||||||
|
||||||
|
||||||
def argument_spec(): | ||||||
arg_spec = { | ||||||
"state": { | ||||||
"type": "str", | ||||||
"default": "present", | ||||||
"choices": ["present", "absent"], | ||||||
}, | ||||||
"host": {"type": "str", "required": True}, | ||||||
"validate_certs": {"type": "bool", "default": True, "aliases": ["verify_ssl"]}, | ||||||
"username": {}, | ||||||
"password": {"no_log": True}, | ||||||
"binary_path": {"type": "path"}, | ||||||
} | ||||||
|
||||||
return arg_spec | ||||||
|
||||||
|
||||||
def main(): | ||||||
module = AnsibleHelmModule( | ||||||
argument_spec=argument_spec(), | ||||||
required_if=[ | ||||||
("state", "present", ["username", "password"]), | ||||||
], | ||||||
supports_check_mode=True, | ||||||
) | ||||||
|
||||||
state = module.params.get("state") | ||||||
command = [module.get_helm_binary(), "registry"] | ||||||
if state == "present": | ||||||
command.extend( | ||||||
[ | ||||||
"login", | ||||||
"--username", | ||||||
module.params.get("username"), | ||||||
"--password", | ||||||
module.params.get("password"), | ||||||
] | ||||||
) | ||||||
else: | ||||||
command.append("logout") | ||||||
|
||||||
command.append(module.params.get("host")) | ||||||
command = " ".join(command) | ||||||
out, err = "", "" | ||||||
changed = True | ||||||
if not module.check_mode: | ||||||
env_update = {} | ||||||
if LooseVersion(module.get_helm_version()) < LooseVersion("3.0.0"): | ||||||
env_update["HELM_EXPERIMENTAL_OCI"] = "1" | ||||||
rc, out, err = module.run_helm_command( | ||||||
command, fails_on_error=False, add_env_update=env_update | ||||||
) | ||||||
if rc != 0: | ||||||
if state == "absent" and "Error: not logged in" in err: | ||||||
err = err.replace("Error: ", "") | ||||||
changed = False | ||||||
else: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the value of |
||||||
module.fail_json( | ||||||
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format( | ||||||
rc, out, err | ||||||
), | ||||||
stdout=out, | ||||||
stderr=err, | ||||||
command=command, | ||||||
) | ||||||
|
||||||
module.exit_json(changed=changed, stdout=out, stderr=err, command=command) | ||||||
|
||||||
|
||||||
if __name__ == "__main__": | ||||||
main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
time=16 | ||
helm_registry_auth |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
# user: testuser, password: pass123! | ||
registry_credentials: testuser:$2y$05$d8tw6L1hojRFW.FjHOAnIOihJWAvFb0/Pu/30hLbQNJIYzCmlyBCi | ||
registry_name: helm_registry | ||
registry_port: 6035 | ||
test_namespace: | ||
- "helm-registry-auth-1" | ||
- "helm-registry-auth-2" | ||
helm_version: v3.8.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
apiVersion: v2 | ||
name: python-app | ||
description: | | ||
A Helm chart used to test OCI registry login for Kubernetes.core Ansible collection | ||
type: application | ||
version: 0.1.0 | ||
appVersion: "default" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: test-python-deployment | ||
labels: | ||
app: python | ||
spec: | ||
replicas: {{ .Values.replicaCount }} | ||
selector: | ||
matchLabels: | ||
app: python | ||
template: | ||
metadata: | ||
labels: | ||
app: python | ||
spec: | ||
containers: | ||
- name: {{ .Values.container.name }} | ||
image: {{ .Values.container.image }} | ||
imagePullPolicy: {{ .Values.container.imagePullPolicy }} | ||
args: ['/bin/sh', '-c', 'while true; do echo $(date); sleep 10; done'] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
replicaCount: 1 | ||
container: | ||
name: "python3" | ||
image: "python:3.7-alpine" | ||
imagePullPolicy: "IfNotPresent" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
- name: teardown registry | ||
include_tasks: teardown_registry.yml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
dependencies: | ||
- remove_namespace | ||
- role: install_helm | ||
helm_version: v3.8.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
- include_tasks: setup_registry.yml | ||
- include_tasks: tests.yml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
- name: Inspect docker container | ||
command: docker container inspect {{ registry_name }} -f '{{ '{{' }} .State.Running {{ '}}' }}' | ||
register: _inspect | ||
ignore_errors: true | ||
|
||
- name: Remove container | ||
when: _inspect.rc == 0 | ||
block: | ||
- name: Stop running container | ||
command: docker container stop {{ registry_name }} | ||
when: _inspect.stdout == "true" | ||
|
||
- name: Remove container | ||
command: docker container rm {{ registry_name }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
--- | ||
- name: Ensure we can talk to docker daemon | ||
ansible.builtin.shell: | ||
cmd: docker ps | ||
|
||
- name: Setup OCI registry | ||
block: | ||
- name: create docker registry | ||
tempfile: | ||
state: directory | ||
suffix: .auth | ||
register: _tmpfile | ||
notify: | ||
- teardown registry | ||
|
||
- name: create auth file | ||
copy: | ||
content: "{{ registry_credentials }}" | ||
dest: "{{ _tmpfile.path }}/htpasswd" | ||
|
||
- include_tasks: remove_docker_container.yml | ||
|
||
- name: Create registry container | ||
command: >- | ||
docker run -d | ||
-p {{ registry_port }}:5000 | ||
--restart=always | ||
--name "{{ registry_name }}" | ||
-v "{{ _tmpfile.path }}:/auth" | ||
-e "REGISTRY_AUTH=htpasswd" | ||
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" | ||
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd | ||
registry:2 | ||
|
||
- name: try login to OCI registry | ||
command: >- | ||
{{ helm_binary_path }} registry login | ||
-u testuser | ||
-p 'pass123!' | ||
localhost:{{ registry_port }} | ||
|
||
- name: Package helm chart | ||
command: >- | ||
{{ helm_binary_path }} package | ||
"{{ role_path }}/files/python-chart" | ||
--destination {{ _tmpfile.path }} | ||
|
||
- name: Helm push chart to the registry | ||
command: >- | ||
{{ helm_binary_path }} push | ||
{{ _tmpfile.path }}/python-app-0.1.0.tgz | ||
oci://localhost:{{ registry_port }}/helm-charts | ||
|
||
- name: Show chart from registry | ||
command: >- | ||
{{ helm_binary_path }} show all oci://localhost:{{ registry_port }}/helm-charts/python-app | ||
|
||
- name: Logout from registry | ||
command: >- | ||
{{ helm_binary_path }} registry logout localhost:{{ registry_port }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
- name: Remove Docker container | ||
include_tasks: remove_docker_container.yml | ||
|
||
- name: Delete temporary directory | ||
file: | ||
state: absent | ||
path: '{{ _tmpfile.path }}' | ||
ignore_errors: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.