From b107dcf80beb345ae2afae3f66423e93e2cf17d1 Mon Sep 17 00:00:00 2001 From: Guillaume Abrioux Date: Tue, 17 Mar 2020 15:34:11 +0100 Subject: [PATCH] ceph_key: remove 'update' state With this change, the state `present` is enough to update a keyring. If the keyring already exist, it will be updated if caps or secret passed to the module are different. If the keyring doen't exist, it will be created. Closes: https://bugzilla.redhat.com/show_bug.cgi?id=1808367 Signed-off-by: Guillaume Abrioux (cherry picked from commit 553584cbd0d014429e665f998776e8d198f72d2b) --- library/ceph_key.py | 108 ++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/library/ceph_key.py b/library/ceph_key.py index db9a42a09..ce23b9587 100644 --- a/library/ceph_key.py +++ b/library/ceph_key.py @@ -57,12 +57,10 @@ options: If 'absent' is used, the module will simply delete the keyring. If 'list' is used, the module will list all the keys and will return a json output. - If 'update' is used, the module will **only** update - the capabilities of a given keyring. If 'info' is used, the module will return in a json format the description of a given keyring. required: true - choices: ['present', 'absent', 'list', 'update', 'info'] + choices: ['present', 'absent', 'list', 'info'] default: list caps: description: @@ -154,12 +152,6 @@ caps: caps: "{{ caps }}" import_key: False -- name: update cephx key - ceph_key: - name: "my_key" - state: update - caps: "{{ caps }}" - - name: delete cephx key ceph_key: name: "my_key" @@ -318,29 +310,7 @@ def create_key(module, result, cluster, name, secret, caps, import_key, auid, de return cmd_list -def update_key(cluster, name, caps, containerized=None): - ''' - Update a CephX key's capabilities - ''' - - cmd_list = [] - - args = [ - 'caps', - name, - ] - - args = generate_caps(args, "ceph", caps) - user = "client.admin" - user_key = os.path.join( - "/etc/ceph/" + cluster + ".client.admin.keyring") - cmd_list.append(generate_ceph_cmd( - cluster, args, user, user_key, containerized)) - - return cmd_list - - -def delete_key(cluster, name, containerized=None): +def delete_key(cluster, name, container_image=None): ''' Delete a CephX key ''' @@ -518,8 +488,10 @@ def run_module(): auid = module.params.get('auid') dest = module.params.get('dest') + changed = False + result = dict( - changed=False, + changed=changed, stdout='', stderr='', rc='', @@ -536,17 +508,33 @@ def run_module(): # Test if the key exists, if it does we skip its creation # We only want to run this check when a key needs to be added # There is no guarantee that any cluster is running and we don't need one - if import_key: + key_exist = 1 + _secret = secret + _caps = caps + if (state in ["present", "update"] and import_key) or state == "info": user = "client.admin" user_key = os.path.join( "/etc/ceph/" + cluster + ".client.admin.keyring") output_format = "json" + _info_key = [] rc, cmd, out, err = exec_commands( module, info_key(cluster, name, user, user_key, output_format, containerized)) # noqa E501 + key_exist = rc + if key_exist == 0: + _info_key = json.loads(out) + _secret = _info_key[0]['key'] + _caps = _info_key[0]['caps'] + if import_key and secret == _secret and caps == _caps: + result["stdout"] = "{0} already exists and doesn't need to be updated.".format(name) # noqa E501 + result["rc"] = 0 + module.exit_json(**result) - if state == "present": - if not caps: + # "update" is here only for backward compatibility + if state in ["present", "update"]: + if not caps and import_key and rc != 0: fatal("Capabilities must be provided when state is 'present'", module) # noqa E501 + if import_key and key_exist != 0 and secret is None and caps is None: + fatal("Keyring doesn't exist, you must provide 'secret' and 'caps'", module) # noqa E501 # Build a different path for bootstrap keys as there are stored as # /var/lib/ceph/bootstrap-rbd/ceph.keyring @@ -558,36 +546,28 @@ def run_module(): file_args['path'] = file_path - # We allow 'present' to override any existing key - # ONLY if a secret is provided - # if not we skip the creation - if import_key: - if rc == 0 and not secret: - # If the key exists in Ceph we must fetch it on the system - # because nothing tells us it exists on the fs or not - rc, cmd, out, err = exec_commands(module, get_key(cluster, name, file_path, containerized)) # noqa E501 - result["stdout"] = "skipped, since {0} already exists, we only fetched the key at {1}. If you want to update a key use 'state: update'".format( # noqa E501 + # There's no need to run create_key() if neither secret nor caps have changed + if (key_exist == 0 and (secret != _secret or caps != _caps)) or key_exist != 0: + rc, cmd, out, err = exec_commands(module, create_key( + module, result, cluster, name, secret, caps, import_key, auid, file_path, containerized)) # noqa E501 + if rc != 0: + result["stdout"] = "Couldn't create or update {0}".format(name) + result["stderr"] = err + module.exit_json(**result) + changed = True + # fetch the key on the system + if key_exist != 1 and not import_key: + rc, cmd, out, err = exec_commands(module, get_key(cluster, name, file_path, containerized)) # noqa E501 + result["rc"] = rc + if rc != 0: + result["stdout"] = "Couldn't fetch the key {0} at {1}.".format( # noqa E501 name, file_path) - result['rc'] = rc - module.set_fs_attributes_if_different(file_args, False) module.exit_json(**result) - rc, cmd, out, err = exec_commands(module, create_key( - module, result, cluster, name, secret, caps, import_key, auid, file_path, containerized)) # noqa E501 + result["stdout"] = "fetched the key {0} at {1}.".format( # noqa E501 + name, file_path) + module.set_fs_attributes_if_different(file_args, False) - elif state == "update": - if not caps: - fatal("Capabilities must be provided when state is 'update'", module) # noqa E501 - - if rc != 0: - result["stdout"] = "skipped, since {0} does not exist".format(name) - result['rc'] = 0 - module.exit_json(**result) - - rc, cmd, out, err = exec_commands( - module, update_key(cluster, name, caps, containerized)) - # After the update we don't need to overwrite the key on the filesystem - # since the secret has not changed elif state == "absent": rc, cmd, out, err = exec_commands( @@ -669,7 +649,7 @@ def run_module(): else: module.fail_json( - msg='State must either be "present" or "absent" or "update" or "list" or "info" or "fetch_initial_keys".', changed=False, rc=1) # noqa E501 + msg='State must either be "present" or "absent" or "list" or "info" or "fetch_initial_keys".', changed=False, rc=1) # noqa E501 endd = datetime.datetime.now() delta = endd - startd @@ -682,7 +662,7 @@ def run_module(): rc=rc, stdout=out.rstrip("\r\n"), stderr=err.rstrip("\r\n"), - changed=True, + changed=changed, ) if rc != 0: