Skip to content

Commit

Permalink
Add idempotency for podman_secret
Browse files Browse the repository at this point in the history
Fix #692
Signed-off-by: Sagi Shnaidman <[email protected]>
  • Loading branch information
sshnaidm committed Dec 23, 2023
1 parent 5ee4dd1 commit 09b57aa
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 10 deletions.
12 changes: 12 additions & 0 deletions plugins/module_utils/podman/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
77 changes: 67 additions & 10 deletions plugins/modules/podman_secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
choices:
- absent
- present
debug:
description:
- Enable debug mode for module.
type: bool
default: False
'''

EXAMPLES = r"""
Expand Down Expand Up @@ -91,19 +96,68 @@
"""

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_create(module, executable, name, data, force, skip,
driver, driver_opts):
if force:
module.run_command([executable, 'secret', 'rm', name])
if skip:

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}}"])
if name in [i.strip() for i in out.splitlines()]:
return {
"changed": False,
}
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, 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:
Expand All @@ -121,6 +175,7 @@ def podman_secret_create(module, executable, name, data, force, skip,

return {
"changed": True,
"diff": diff,
}


Expand Down Expand Up @@ -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),
),
)

Expand All @@ -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)

Expand Down
112 changes: 112 additions & 0 deletions tests/integration/targets/podman_secret/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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') }}"
Expand All @@ -11,6 +23,7 @@
containers.podman.podman_secret:
executable: "{{ test_executable | default('podman') }}"
name: mysecret
debug: true
data: secret content

- name: Recreate secret
Expand All @@ -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:
Expand Down Expand Up @@ -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') }}"
Expand Down

0 comments on commit 09b57aa

Please sign in to comment.