mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-26 21:33:02 +00:00
helm_registry_auth module to authenticate in OCI registry (#800)
* new module helm_registry_auth
* Initial integration tests
* final update copyright and integration test before pr
* update link to pr in changelog fragment
* reformat plugins/module_utils/helm.py with black
to fix linters in actions
* attempt to fix unit test
unit test was missing initially
* fix https://pycqa.github.io/isort/ linter
* next attemp to fix unit-test
* remove unused and unsupported helm_args_common
* remove unused imports and fix other linters errors
* another fix for unit test
* fix issue introducied by commit ff02893a12a31f9c44b5c48f9a8bf85057295961
* add binary_path to arg_spec
* return helm_cmd in the output of check mode
remove changlog fragment
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* description suggestion from reviewer/maintainer
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* remove changed from module return
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* remove redundant code
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* Update plugins/modules/helm_registry_auth.py
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* consider support of logout when user is not logged in
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* consider support helm < 3.0.0
* Revert "consider support helm < 3.0.0"
This reverts commit f20004d196.
* reintroduce support of helm version less than 3.8.0
reference: https://helm.sh/docs/topics/registries/#enabling-oci-support-prior-to-v380
* revert reintroducing support of helm < 3.8.0
reason: didn't find a quick way to deal with tests
* update documentation with the recent module updates
* Update plugins/modules/helm_registry_auth.py
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* add test of logout impendency
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
* fix linters
* fix intendations in the integration tests
* create tests/integration/targets/helm_registry_auth/aliases
* fix integration test (typo)
* fix integration tests (test wrong cred)
* add stderr when module fail
* another attempt to fix integration test
* fix assertion in integration test to be not affceted by the #830
---------
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6609abdd5a
commit
aee847431a
2
tests/integration/targets/helm_registry_auth/aliases
Normal file
2
tests/integration/targets/helm_registry_auth/aliases
Normal file
@@ -0,0 +1,2 @@
|
||||
time=16
|
||||
helm_registry_auth
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Username and password for the registry
|
||||
# ../files/registry.password contains username and hashed password
|
||||
username: testuser
|
||||
password: testpassword
|
||||
wrong_password: 'WrongPassword'
|
||||
registry_name: oci_registry
|
||||
registry_port: 5000
|
||||
test_chart: https://github.com/grafana/helm-charts/releases/download/k8s-monitoring-1.6.8/k8s-monitoring-1.6.8.tgz
|
||||
@@ -0,0 +1 @@
|
||||
testuser:$2y$05$PmdUjSCJYdRUZlsYy8QGWuJDiwuHtWXa28YrELlN5haeHkZ1seZZG
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- install_helm
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Test helm_registry_auth module
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: true
|
||||
roles:
|
||||
- helm_registry_auth
|
||||
5
tests/integration/targets/helm_registry_auth/runme.sh
Executable file
5
tests/integration/targets/helm_registry_auth/runme.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
export ANSIBLE_CALLBACKS_ENABLED=profile_tasks
|
||||
export ANSIBLE_ROLES_PATH=../
|
||||
ansible-playbook playbook.yaml "$@"
|
||||
178
tests/integration/targets/helm_registry_auth/tasks/main.yaml
Normal file
178
tests/integration/targets/helm_registry_auth/tasks/main.yaml
Normal file
@@ -0,0 +1,178 @@
|
||||
---
|
||||
- name: Run module test
|
||||
# using a shell and command module to run the test as test can be non-idempotent
|
||||
# and it allow to not install any additional dependencies
|
||||
block:
|
||||
- name: Ensure that helm is installed
|
||||
ansible.builtin.shell: helm version --client --short | grep v3
|
||||
register: _helm_version
|
||||
failed_when: _helm_version.rc != 0
|
||||
|
||||
- name: Ensure that Docker demon is running
|
||||
ansible.builtin.command: "docker info"
|
||||
register: _docker_info
|
||||
failed_when: _docker_info.rc != 0
|
||||
|
||||
- name: Create a tmpfile htpasswd directory
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
suffix: .httppasswd
|
||||
register: _tmpfile
|
||||
|
||||
- name: Copy htpasswd to the tmpfile directory
|
||||
ansible.builtin.copy:
|
||||
src: registry.password
|
||||
dest: "{{ _tmpfile.path }}/registry.password"
|
||||
|
||||
- name: Setup the registry
|
||||
ansible.builtin.command: >-
|
||||
docker run -d --rm
|
||||
-p {{ registry_port }}:5000
|
||||
--name "{{ registry_name }}"
|
||||
-v "{{ _tmpfile.path }}:/auth"
|
||||
-e "REGISTRY_AUTH=htpasswd"
|
||||
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
|
||||
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password
|
||||
registry:2
|
||||
register: _setup_registry
|
||||
failed_when: _setup_registry.rc != 0
|
||||
|
||||
- name: Ensure that the registry is running and rechable
|
||||
ansible.builtin.wait_for:
|
||||
host: localhost
|
||||
port: "{{ registry_port }}"
|
||||
|
||||
- name: Test the registry with correct credentials to ensure that the registry is running
|
||||
ansible.builtin.shell: >-
|
||||
echo {{ password | quote }} | helm registry login localhost:{{ registry_port }}
|
||||
-u {{ username }} --password-stdin
|
||||
register: _login_correct
|
||||
failed_when: _login_correct.rc != 0
|
||||
|
||||
- name: Clean up credentials to run test on clean environment
|
||||
ansible.builtin.shell: >-
|
||||
helm registry logout localhost:{{ registry_port }}
|
||||
register: _logout
|
||||
failed_when: _logout.rc != 0
|
||||
|
||||
- name: Create directory for helm chart
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
suffix: ".helm"
|
||||
register: _destination
|
||||
|
||||
- name: Pull test helm chart
|
||||
ansible.builtin.uri:
|
||||
url: "{{ test_chart }}"
|
||||
dest: "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz"
|
||||
return_content: no
|
||||
status_code: 200
|
||||
|
||||
- name: Test module helm_registry_auth with correct credentials
|
||||
helm_registry_auth:
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
host: localhost:{{ registry_port }}
|
||||
state: present
|
||||
register: _helm_registry_auth_correct
|
||||
|
||||
- name: Assert that the registry is logged in
|
||||
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
|
||||
assert:
|
||||
that:
|
||||
- "'Login Succeeded' in _helm_registry_auth_correct.stderr"
|
||||
- "'{{ password }}' not in _helm_registry_auth_correct.command"
|
||||
- "'{{ password }}' not in _helm_registry_auth_correct.stdout"
|
||||
- "'{{ password }}' not in _helm_registry_auth_correct.stderr"
|
||||
|
||||
- name: Ensure that push to the registry is working
|
||||
ansible.builtin.shell: >-
|
||||
helm push "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
|
||||
register: _save_chart
|
||||
failed_when: _save_chart.rc != 0
|
||||
|
||||
- name: Assert that the chart is saved
|
||||
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
|
||||
assert:
|
||||
that: "'Pushed: localhost:{{ registry_port }}/test/k8s-monitoring' in _save_chart.stderr"
|
||||
|
||||
|
||||
- name: Test logout
|
||||
helm_registry_auth:
|
||||
host: localhost:{{ registry_port }}
|
||||
state: absent
|
||||
register: _helm_registry_auth_logout
|
||||
|
||||
- name: Assert logout
|
||||
# Helm binary prints the message to stderr
|
||||
assert:
|
||||
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
||||
|
||||
- name: Test logout idempotency
|
||||
helm_registry_auth:
|
||||
host: localhost:{{ registry_port }}
|
||||
state: absent
|
||||
register: _helm_registry_auth_logout_idempotency
|
||||
|
||||
- name: Assert logout operation did not report change
|
||||
ansible.builtin.assert:
|
||||
that: _helm_registry_auth_logout_idempotency is not changed
|
||||
|
||||
- name: Ensure that not able to push to the registry
|
||||
ansible.builtin.shell: >-
|
||||
helm push "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
|
||||
register: _save_chart
|
||||
failed_when: _save_chart.rc == 0
|
||||
|
||||
- name: Read content of ~/.config/helm/registry/config.json
|
||||
ansible.builtin.slurp:
|
||||
src: ~/.config/helm/registry/config.json
|
||||
register: _config_json
|
||||
|
||||
- name: Assert that auth data is remove and the chart is not saved
|
||||
# Helm binary prints the message to stderr
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'push access denied' in _save_chart.stderr"
|
||||
- "'authorization failed' in _save_chart.stderr"
|
||||
- "_save_chart.rc != 0"
|
||||
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
|
||||
|
||||
- name: Test module helm_registry_auth with wrong credentials
|
||||
helm_registry_auth:
|
||||
username: "{{ username }}"
|
||||
password: "{{ wrong_password }}"
|
||||
host: localhost:{{ registry_port }}
|
||||
state: present
|
||||
register: _helm_registry_auth_wrong
|
||||
ignore_errors: true
|
||||
|
||||
- name: Read content of ~/.config/helm/registry/config.json
|
||||
ansible.builtin.slurp:
|
||||
src: ~/.config/helm/registry/config.json
|
||||
register: _config_json
|
||||
|
||||
- name: Assert that the registry is not logged in and auth data is not saved
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'401 Unauthorized' in _helm_registry_auth_wrong.stderr"
|
||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.command"
|
||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stdout"
|
||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stderr"
|
||||
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
|
||||
|
||||
# Clean up
|
||||
always:
|
||||
- name: Stop and remove the registry
|
||||
ansible.builtin.command: docker stop {{ registry_name }}
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove the tmpfile
|
||||
ansible.builtin.file:
|
||||
state: absent
|
||||
path: "{{ item }}"
|
||||
force: true
|
||||
loop:
|
||||
- "{{ _tmpfile.path }}"
|
||||
- "{{ _destination.path }}"
|
||||
ignore_errors: true
|
||||
@@ -25,4 +25,6 @@ plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
|
||||
@@ -26,4 +26,5 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -29,4 +29,5 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -29,4 +29,5 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -26,4 +26,5 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -26,4 +26,5 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -242,7 +242,7 @@ def test_module_run_helm_command(_ansible_helm_module):
|
||||
assert (rc, out, err) == (0, output, error)
|
||||
|
||||
_ansible_helm_module.run_command.assert_called_once_with(
|
||||
command, environ_update=env_update
|
||||
command, environ_update=env_update, data=None
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
with self.assertRaises(AnsibleExitJson) as result:
|
||||
helm_template.main()
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm template /tmp/path", environ_update={}
|
||||
"/usr/bin/helm template /tmp/path", environ_update={}, data=None
|
||||
)
|
||||
assert result.exception.args[0]["command"] == "/usr/bin/helm template /tmp/path"
|
||||
|
||||
@@ -74,6 +74,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm template test --repo=https://charts.com/test",
|
||||
environ_update={},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -95,6 +96,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm template https://charts/example.tgz --dependency-update",
|
||||
environ_update={},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
|
||||
@@ -88,6 +88,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm upgrade -i --reset-values test '/tmp/path'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -118,6 +119,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm upgrade -i --reset-values test '/tmp/path'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -147,6 +149,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
call(
|
||||
"/usr/bin/helm upgrade -i --reset-values test '/tmp/path'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -181,6 +184,7 @@ class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||
call(
|
||||
"/usr/bin/helm upgrade -i --reset-values test '/tmp/path'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -251,6 +255,7 @@ class TestDependencyUpdateWithChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test 'chart1'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -280,6 +285,7 @@ class TestDependencyUpdateWithChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test 'chart1'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -338,6 +344,7 @@ class TestDependencyUpdateWithChartRepoUrlOption(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm --repo=http://repo.example/charts install --dependency-update --replace test 'chart1'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -405,6 +412,7 @@ class TestDependencyUpdateWithChartRefIsUrl(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm upgrade -i --reset-values test 'http://repo.example/charts/application.tgz'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -433,6 +441,7 @@ class TestDependencyUpdateWithChartRefIsUrl(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm upgrade -i --reset-values test 'http://repo.example/charts/application.tgz'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
@@ -489,6 +498,7 @@ class TestDependencyUpdateWithChartRefIsUrl(unittest.TestCase):
|
||||
mock_run_command.assert_called_once_with(
|
||||
"/usr/bin/helm install --dependency-update --replace test 'http://repo.example/charts/application.tgz'",
|
||||
environ_update={"HELM_NAMESPACE": "test"},
|
||||
data=None,
|
||||
)
|
||||
assert (
|
||||
result.exception.args[0]["command"]
|
||||
|
||||
Reference in New Issue
Block a user