mirror of
https://github.com/containers/ansible-podman-collections.git
synced 2026-02-04 07:11:49 +00:00
Add idempotency for podman_secret
Fix #692 Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
This commit is contained in:
parent
5ee4dd1eda
commit
dcdf7424b0
3 changed files with 192 additions and 11 deletions
|
|
@ -306,3 +306,15 @@ def normalize_signal(signal_name_or_number):
|
|||
if signal_name not in _signal_map:
|
||||
raise RuntimeError("Unknown signal '{0}'".format(signal_name_or_number))
|
||||
return str(_signal_map[signal_name])
|
||||
|
||||
|
||||
def get_podman_version(module, fail=True):
|
||||
executable = module.params['executable'] if module.params['executable'] else 'podman'
|
||||
rc, out, err = module.run_command(
|
||||
[executable, b'--version'])
|
||||
if rc != 0 or not out or "version" not in out:
|
||||
if fail:
|
||||
module.fail_json(msg="'%s --version' run failed! Error: %s" %
|
||||
(executable, err))
|
||||
return None
|
||||
return out.split("version")[1].strip()
|
||||
|
|
|
|||
|
|
@ -61,6 +61,11 @@ options:
|
|||
choices:
|
||||
- absent
|
||||
- present
|
||||
debug:
|
||||
description:
|
||||
- Enable debug mode for module.
|
||||
type: bool
|
||||
default: False
|
||||
'''
|
||||
|
||||
EXAMPLES = r"""
|
||||
|
|
@ -91,19 +96,68 @@ EXAMPLES = r"""
|
|||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import LooseVersion
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import get_podman_version
|
||||
|
||||
diff = {"before": '', "after": ''}
|
||||
|
||||
|
||||
def podman_secret_exists(module, executable, name, version):
|
||||
if version is None or LooseVersion(version) < LooseVersion('4.5.0'):
|
||||
rc, out, err = module.run_command(
|
||||
[executable, 'secret', 'ls', "--format", "{{.Name}}"])
|
||||
return name in [i.strip() for i in out.splitlines()]
|
||||
rc, out, err = module.run_command(
|
||||
[executable, 'secret', 'exists', name])
|
||||
return rc == 0
|
||||
|
||||
|
||||
def need_update(module, executable, name, data, driver, driver_opts, debug):
|
||||
|
||||
cmd = [executable, 'secret', 'inspect', '--showsecret', name]
|
||||
rc, out, err = module.run_command(cmd)
|
||||
if rc != 0:
|
||||
if debug:
|
||||
module.log("PODMAN-SECRET-DEBUG: Unable to get secret info: %s" % err)
|
||||
return True
|
||||
try:
|
||||
secret = module.from_json(out)[0]
|
||||
# We support only file driver for now
|
||||
if (driver and driver != 'file') or secret['Spec']['Driver']['Name'] != 'file':
|
||||
if debug:
|
||||
module.log("PODMAN-SECRET-DEBUG: Idempotency of driver %s is not supported" % driver)
|
||||
return True
|
||||
if secret['SecretData'] != data:
|
||||
diff['after'] = "<different-secret>"
|
||||
diff['before'] = "<secret>"
|
||||
return True
|
||||
if driver_opts:
|
||||
for k, v in driver_opts.items():
|
||||
if secret['Spec']['Driver']['Options'].get(k) != v:
|
||||
diff['after'] = "=".join([k, v])
|
||||
diff['before'] = "=".join(
|
||||
[k, secret['Spec']['Driver']['Options'].get(k)])
|
||||
return True
|
||||
except Exception:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def podman_secret_create(module, executable, name, data, force, skip,
|
||||
driver, driver_opts):
|
||||
if force:
|
||||
module.run_command([executable, 'secret', 'rm', name])
|
||||
if skip:
|
||||
rc, out, err = module.run_command(
|
||||
[executable, 'secret', 'ls', "--format", "{{.Name}}"])
|
||||
if name in [i.strip() for i in out.splitlines()]:
|
||||
return {
|
||||
"changed": False,
|
||||
}
|
||||
driver, driver_opts, debug):
|
||||
podman_version = get_podman_version(module, fail=False)
|
||||
if (podman_version is not None and
|
||||
LooseVersion(podman_version) >= LooseVersion('4.7.0')
|
||||
and (driver is None or driver == 'file')):
|
||||
if not skip and need_update(module, executable, name, data, driver, driver_opts, debug):
|
||||
podman_secret_remove(module, executable, name)
|
||||
else:
|
||||
return {"changed": False}
|
||||
else:
|
||||
if force:
|
||||
podman_secret_remove(module, executable, name)
|
||||
if skip and podman_secret_exists(module, executable, name, podman_version):
|
||||
return {"changed": False}
|
||||
|
||||
cmd = [executable, 'secret', 'create']
|
||||
if driver:
|
||||
|
|
@ -121,6 +175,7 @@ def podman_secret_create(module, executable, name, data, force, skip,
|
|||
|
||||
return {
|
||||
"changed": True,
|
||||
"diff": diff,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -150,6 +205,7 @@ def main():
|
|||
skip_existing=dict(type='bool', default=False),
|
||||
driver=dict(type='str'),
|
||||
driver_opts=dict(type='dict'),
|
||||
debug=dict(type='bool', default=False),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -165,9 +221,10 @@ def main():
|
|||
skip = module.params['skip_existing']
|
||||
driver = module.params['driver']
|
||||
driver_opts = module.params['driver_opts']
|
||||
debug = module.params['debug']
|
||||
results = podman_secret_create(module, executable,
|
||||
name, data, force, skip,
|
||||
driver, driver_opts)
|
||||
driver, driver_opts, debug)
|
||||
else:
|
||||
results = podman_secret_remove(module, executable, name)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
- name: Test podman_secret
|
||||
block:
|
||||
|
||||
- name: Discover podman version
|
||||
shell: podman version | grep "^Version:" | awk {'print $2'}
|
||||
register: podman_v
|
||||
|
||||
- name: Set podman version fact
|
||||
set_fact:
|
||||
podman_version: "{{ podman_v.stdout | string }}"
|
||||
|
||||
- name: Set podman version fact to gt than 4.7.0 if so
|
||||
set_fact:
|
||||
podman_version_gt470: "{{ podman_version is version('4.7.0', '>=') }}"
|
||||
|
||||
- name: Make sure secret doesn't exist
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
|
|
@ -11,6 +23,7 @@
|
|||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
debug: true
|
||||
data: secret content
|
||||
|
||||
- name: Recreate secret
|
||||
|
|
@ -27,13 +40,33 @@
|
|||
name: mysecret
|
||||
data: super secret content
|
||||
skip_existing: true
|
||||
debug: true
|
||||
register: skipped
|
||||
|
||||
- name: Force secret to same
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: super secret content
|
||||
force: true
|
||||
debug: true
|
||||
register: forced2
|
||||
|
||||
- name: Check assertions
|
||||
assert:
|
||||
that:
|
||||
- forced is changed
|
||||
- skipped is not changed
|
||||
- forced2 is changed
|
||||
when: not podman_version_gt470
|
||||
|
||||
- name: Check assertions for podman >= 4.7.0
|
||||
assert:
|
||||
that:
|
||||
- forced is changed
|
||||
- skipped is not changed
|
||||
- forced2 is not changed
|
||||
when: podman_version_gt470
|
||||
|
||||
- name: Create container that uses secret
|
||||
containers.podman.podman_container:
|
||||
|
|
@ -103,6 +136,85 @@
|
|||
a: b
|
||||
c: d
|
||||
|
||||
- when: podman_version_gt470
|
||||
block:
|
||||
|
||||
- name: Create secret with file driver and different options
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: secret content
|
||||
driver: file
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: opts_changed
|
||||
|
||||
- name: Create secret with file driver and different options again
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: secret content
|
||||
driver: file
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: opts_changed2
|
||||
|
||||
- name: Create secret with different content
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: other secret content
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: secret_changed
|
||||
|
||||
- name: Create secret with different content again
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: other secret content
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: secret_changed2
|
||||
|
||||
- name: Create secret with different content but skipped
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: other secret content and skipped
|
||||
skip_existing: true
|
||||
debug: true
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: skip_secret_changed
|
||||
|
||||
- name: Create secret with different content but forced
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
name: mysecret
|
||||
data: other secret content and skipped
|
||||
force: true
|
||||
debug: true
|
||||
driver_opts:
|
||||
a: b
|
||||
c: e
|
||||
register: force_secret_changed
|
||||
|
||||
- name: Check opts changes
|
||||
assert:
|
||||
that:
|
||||
- opts_changed is changed
|
||||
- opts_changed2 is not changed
|
||||
- secret_changed is changed
|
||||
- secret_changed2 is not changed
|
||||
- skip_secret_changed is not changed
|
||||
- force_secret_changed is changed
|
||||
|
||||
- name: Remove secret
|
||||
containers.podman.podman_secret:
|
||||
executable: "{{ test_executable | default('podman') }}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue