1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-04-21 19:29:05 +00:00

Reformat everything.

This commit is contained in:
Felix Fontein 2025-11-01 12:08:41 +01:00
parent 3f2213791a
commit 340ff8586d
1008 changed files with 61301 additions and 58309 deletions

View file

@ -744,16 +744,21 @@ end_state:
}
"""
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
keycloak_argument_spec, get_token, KeycloakError
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import (
KeycloakAPI,
camel,
keycloak_argument_spec,
get_token,
KeycloakError,
)
from ansible.module_utils.basic import AnsibleModule
import copy
PROTOCOL_OPENID_CONNECT = 'openid-connect'
PROTOCOL_SAML = 'saml'
PROTOCOL_DOCKER_V2 = 'docker-v2'
CLIENT_META_DATA = ['authorizationServicesEnabled']
PROTOCOL_OPENID_CONNECT = "openid-connect"
PROTOCOL_SAML = "saml"
PROTOCOL_DOCKER_V2 = "docker-v2"
CLIENT_META_DATA = ["authorizationServicesEnabled"]
def normalise_scopes_for_behavior(desired_client, before_client, clientScopesBehavior):
@ -785,16 +790,16 @@ def normalise_scopes_for_behavior(desired_client, before_client, clientScopesBeh
"""
desired_client = copy.deepcopy(desired_client)
before_client = copy.deepcopy(before_client)
if clientScopesBehavior == 'ignore':
desired_client['defaultClientScopes'] = copy.deepcopy(before_client['defaultClientScopes'])
desired_client['optionalClientScopes'] = copy.deepcopy(before_client['optionalClientScopes'])
elif clientScopesBehavior == 'patch':
for scope in before_client['defaultClientScopes']:
if scope not in desired_client['defaultClientScopes']:
desired_client['defaultClientScopes'].append(scope)
for scope in before_client['optionalClientScopes']:
if scope not in desired_client['optionalClientScopes']:
desired_client['optionalClientScopes'].append(scope)
if clientScopesBehavior == "ignore":
desired_client["defaultClientScopes"] = copy.deepcopy(before_client["defaultClientScopes"])
desired_client["optionalClientScopes"] = copy.deepcopy(before_client["optionalClientScopes"])
elif clientScopesBehavior == "patch":
for scope in before_client["defaultClientScopes"]:
if scope not in desired_client["defaultClientScopes"]:
desired_client["defaultClientScopes"].append(scope)
for scope in before_client["optionalClientScopes"]:
if scope not in desired_client["optionalClientScopes"]:
desired_client["optionalClientScopes"].append(scope)
return desired_client, before_client
@ -823,15 +828,15 @@ def check_optional_scopes_not_default(desired_client, clientScopesBehavior, modu
type: None
description: Returns None. Fails the module if a scope is both default and optional.
"""
if clientScopesBehavior == 'ignore':
if clientScopesBehavior == "ignore":
return
for scope in desired_client['optionalClientScopes']:
if scope in desired_client['defaultClientScopes']:
module.fail_json(msg=f'Client scope {scope} cannot be both default and optional')
for scope in desired_client["optionalClientScopes"]:
if scope in desired_client["defaultClientScopes"]:
module.fail_json(msg=f"Client scope {scope} cannot be both default and optional")
def normalise_cr(clientrep, remove_ids=False):
""" Re-sorts any properties where the order so that diff's is minimised, and adds default values where appropriate so that the
"""Re-sorts any properties where the order so that diff's is minimised, and adds default values where appropriate so that the
the change detection is more effective.
:param clientrep: the clientrep dict to be sanitized
@ -843,57 +848,59 @@ def normalise_cr(clientrep, remove_ids=False):
clientrep = copy.deepcopy(clientrep)
if remove_ids:
clientrep.pop('id', None)
clientrep.pop("id", None)
if 'defaultClientScopes' in clientrep:
clientrep['defaultClientScopes'] = list(sorted(clientrep['defaultClientScopes']))
if "defaultClientScopes" in clientrep:
clientrep["defaultClientScopes"] = list(sorted(clientrep["defaultClientScopes"]))
else:
clientrep['defaultClientScopes'] = []
clientrep["defaultClientScopes"] = []
if 'optionalClientScopes' in clientrep:
clientrep['optionalClientScopes'] = list(sorted(clientrep['optionalClientScopes']))
if "optionalClientScopes" in clientrep:
clientrep["optionalClientScopes"] = list(sorted(clientrep["optionalClientScopes"]))
else:
clientrep['optionalClientScopes'] = []
clientrep["optionalClientScopes"] = []
if 'redirectUris' in clientrep:
clientrep['redirectUris'] = list(sorted(clientrep['redirectUris']))
if "redirectUris" in clientrep:
clientrep["redirectUris"] = list(sorted(clientrep["redirectUris"]))
else:
clientrep['redirectUris'] = []
clientrep["redirectUris"] = []
if 'protocolMappers' in clientrep:
clientrep['protocolMappers'] = sorted(clientrep['protocolMappers'], key=lambda x: (x.get('name'), x.get('protocol'), x.get('protocolMapper')))
for mapper in clientrep['protocolMappers']:
if "protocolMappers" in clientrep:
clientrep["protocolMappers"] = sorted(
clientrep["protocolMappers"], key=lambda x: (x.get("name"), x.get("protocol"), x.get("protocolMapper"))
)
for mapper in clientrep["protocolMappers"]:
if remove_ids:
mapper.pop('id', None)
mapper.pop("id", None)
# Convert bool to string
if 'config' in mapper:
for key, value in mapper['config'].items():
if "config" in mapper:
for key, value in mapper["config"].items():
if isinstance(value, bool):
mapper['config'][key] = str(value).lower()
mapper["config"][key] = str(value).lower()
# Set to a default value.
mapper['consentRequired'] = mapper.get('consentRequired', False)
mapper["consentRequired"] = mapper.get("consentRequired", False)
else:
clientrep['protocolMappers'] = []
clientrep["protocolMappers"] = []
if 'attributes' in clientrep:
for key, value in clientrep['attributes'].items():
if "attributes" in clientrep:
for key, value in clientrep["attributes"].items():
if isinstance(value, bool):
clientrep['attributes'][key] = str(value).lower()
clientrep['attributes'].pop('client.secret.creation.time', None)
clientrep["attributes"][key] = str(value).lower()
clientrep["attributes"].pop("client.secret.creation.time", None)
else:
clientrep['attributes'] = []
clientrep["attributes"] = []
if 'webOrigins' in clientrep:
clientrep['webOrigins'] = sorted(clientrep['webOrigins'])
if "webOrigins" in clientrep:
clientrep["webOrigins"] = sorted(clientrep["webOrigins"])
else:
clientrep['webOrigins'] = []
clientrep["webOrigins"] = []
if 'redirectUris' in clientrep:
clientrep['redirectUris'] = sorted(clientrep['redirectUris'])
if "redirectUris" in clientrep:
clientrep["redirectUris"] = sorted(clientrep["redirectUris"])
else:
clientrep['redirectUris'] = []
clientrep["redirectUris"] = []
return clientrep
@ -901,31 +908,31 @@ def normalise_cr(clientrep, remove_ids=False):
def normalize_kc_resp(clientrep):
# kc drops the variable 'authorizationServicesEnabled' if set to false
# to minimize diff/changes we set it to false if not set by kc
if clientrep and 'authorizationServicesEnabled' not in clientrep:
clientrep['authorizationServicesEnabled'] = False
if clientrep and "authorizationServicesEnabled" not in clientrep:
clientrep["authorizationServicesEnabled"] = False
def sanitize_cr(clientrep):
""" Removes probably sensitive details from a client representation.
"""Removes probably sensitive details from a client representation.
:param clientrep: the clientrep dict to be sanitized
:return: sanitized clientrep dict
"""
result = copy.deepcopy(clientrep)
if 'secret' in result:
result['secret'] = 'no_log'
if 'attributes' in result:
attributes = result['attributes']
if "secret" in result:
result["secret"] = "no_log"
if "attributes" in result:
attributes = result["attributes"]
if isinstance(attributes, dict):
if 'saml.signing.private.key' in attributes:
attributes['saml.signing.private.key'] = 'no_log'
if 'saml.encryption.private.key' in attributes:
attributes['saml.encryption.private.key'] = 'no_log'
if "saml.signing.private.key" in attributes:
attributes["saml.signing.private.key"] = "no_log"
if "saml.encryption.private.key" in attributes:
attributes["saml.encryption.private.key"] = "no_log"
return normalise_cr(result)
def get_authentication_flow_id(flow_name, realm, kc):
""" Get the authentication flow ID based on the flow name, realm, and Keycloak client.
"""Get the authentication flow ID based on the flow name, realm, and Keycloak client.
Args:
flow_name (str): The name of the authentication flow.
@ -941,11 +948,11 @@ def get_authentication_flow_id(flow_name, realm, kc):
flow = kc.get_authentication_flow_by_alias(flow_name, realm)
if flow:
return flow["id"]
kc.module.fail_json(msg=f'Authentification flow {flow_name} not found in realm {realm}')
kc.module.fail_json(msg=f"Authentification flow {flow_name} not found in realm {realm}")
def flow_binding_from_dict_to_model(newClientFlowBinding, realm, kc):
""" Convert a dictionary representing client flow bindings to a model representation.
"""Convert a dictionary representing client flow bindings to a model representation.
Args:
newClientFlowBinding (dict): A dictionary containing client flow bindings.
@ -962,10 +969,7 @@ def flow_binding_from_dict_to_model(newClientFlowBinding, realm, kc):
"""
modelFlow = {
"browser": None,
"direct_grant": None
}
modelFlow = {"browser": None, "direct_grant": None}
for k, v in newClientFlowBinding.items():
if not v:
@ -1008,11 +1012,7 @@ def find_match(iterable, attribute, name):
"""
name_lower = str(name).lower()
return next(
(
value
for value in iterable
if attribute in value and str(value[attribute]).lower() == name_lower
),
(value for value in iterable if attribute in value and str(value[attribute]).lower() == name_lower),
None,
)
@ -1046,14 +1046,14 @@ def add_default_client_scopes(desired_client, before_client, realm, kc):
None
"""
desired_default_scope = desired_client["defaultClientScopes"]
missing_scopes = [item for item in desired_default_scope if item not in before_client['defaultClientScopes']]
missing_scopes = [item for item in desired_default_scope if item not in before_client["defaultClientScopes"]]
if not missing_scopes:
return
client_scopes = kc.get_clientscopes(realm)
for name in missing_scopes:
scope = find_match(client_scopes, "name", name)
if scope:
kc.add_default_clientscope(scope['id'], realm, desired_client['clientId'])
kc.add_default_clientscope(scope["id"], realm, desired_client["clientId"])
def add_optional_client_scopes(desired_client, before_client, realm, kc):
@ -1085,14 +1085,14 @@ def add_optional_client_scopes(desired_client, before_client, realm, kc):
None
"""
desired_optional_scope = desired_client["optionalClientScopes"]
missing_scopes = [item for item in desired_optional_scope if item not in before_client['optionalClientScopes']]
missing_scopes = [item for item in desired_optional_scope if item not in before_client["optionalClientScopes"]]
if not missing_scopes:
return
client_scopes = kc.get_clientscopes(realm)
for name in missing_scopes:
scope = find_match(client_scopes, "name", name)
if scope:
kc.add_optional_clientscope(scope['id'], realm, desired_client['clientId'])
kc.add_optional_clientscope(scope["id"], realm, desired_client["clientId"])
def remove_default_client_scopes(desired_client, before_client, realm, kc):
@ -1124,14 +1124,14 @@ def remove_default_client_scopes(desired_client, before_client, realm, kc):
None
"""
before_default_scope = before_client["defaultClientScopes"]
missing_scopes = [item for item in before_default_scope if item not in desired_client['defaultClientScopes']]
missing_scopes = [item for item in before_default_scope if item not in desired_client["defaultClientScopes"]]
if not missing_scopes:
return
client_scopes = kc.get_default_clientscopes(realm, desired_client['clientId'])
client_scopes = kc.get_default_clientscopes(realm, desired_client["clientId"])
for name in missing_scopes:
scope = find_match(client_scopes, "name", name)
if scope:
kc.delete_default_clientscope(scope['id'], realm, desired_client['clientId'])
kc.delete_default_clientscope(scope["id"], realm, desired_client["clientId"])
def remove_optional_client_scopes(desired_client, before_client, realm, kc):
@ -1163,14 +1163,14 @@ def remove_optional_client_scopes(desired_client, before_client, realm, kc):
None
"""
before_optional_scope = before_client["optionalClientScopes"]
missing_scopes = [item for item in before_optional_scope if item not in desired_client['optionalClientScopes']]
missing_scopes = [item for item in before_optional_scope if item not in desired_client["optionalClientScopes"]]
if not missing_scopes:
return
client_scopes = kc.get_optional_clientscopes(realm, desired_client['clientId'])
client_scopes = kc.get_optional_clientscopes(realm, desired_client["clientId"])
for name in missing_scopes:
scope = find_match(client_scopes, "name", name)
if scope:
kc.delete_optional_clientscope(scope['id'], realm, desired_client['clientId'])
kc.delete_optional_clientscope(scope["id"], realm, desired_client["clientId"])
def main():
@ -1182,86 +1182,94 @@ def main():
argument_spec = keycloak_argument_spec()
protmapper_spec = dict(
consentRequired=dict(type='bool'),
consentText=dict(type='str'),
id=dict(type='str'),
name=dict(type='str'),
protocol=dict(type='str', choices=[PROTOCOL_OPENID_CONNECT, PROTOCOL_SAML, PROTOCOL_DOCKER_V2]),
protocolMapper=dict(type='str'),
config=dict(type='dict'),
consentRequired=dict(type="bool"),
consentText=dict(type="str"),
id=dict(type="str"),
name=dict(type="str"),
protocol=dict(type="str", choices=[PROTOCOL_OPENID_CONNECT, PROTOCOL_SAML, PROTOCOL_DOCKER_V2]),
protocolMapper=dict(type="str"),
config=dict(type="dict"),
)
authentication_flow_spec = dict(
browser=dict(type='str'),
browser_name=dict(type='str', aliases=['browserName']),
direct_grant=dict(type='str', aliases=['directGrant']),
direct_grant_name=dict(type='str', aliases=['directGrantName']),
browser=dict(type="str"),
browser_name=dict(type="str", aliases=["browserName"]),
direct_grant=dict(type="str", aliases=["directGrant"]),
direct_grant_name=dict(type="str", aliases=["directGrantName"]),
)
meta_args = dict(
state=dict(default='present', choices=['present', 'absent']),
realm=dict(type='str', default='master'),
id=dict(type='str'),
client_id=dict(type='str', aliases=['clientId']),
name=dict(type='str'),
description=dict(type='str'),
root_url=dict(type='str', aliases=['rootUrl']),
admin_url=dict(type='str', aliases=['adminUrl']),
base_url=dict(type='str', aliases=['baseUrl']),
surrogate_auth_required=dict(type='bool', aliases=['surrogateAuthRequired']),
enabled=dict(type='bool'),
client_authenticator_type=dict(type='str', choices=['client-secret', 'client-jwt', 'client-x509'], aliases=['clientAuthenticatorType']),
secret=dict(type='str', no_log=True),
registration_access_token=dict(type='str', aliases=['registrationAccessToken'], no_log=True),
default_roles=dict(type='list', elements='str', aliases=['defaultRoles']),
redirect_uris=dict(type='list', elements='str', aliases=['redirectUris']),
web_origins=dict(type='list', elements='str', aliases=['webOrigins']),
not_before=dict(type='int', aliases=['notBefore']),
bearer_only=dict(type='bool', aliases=['bearerOnly']),
consent_required=dict(type='bool', aliases=['consentRequired']),
standard_flow_enabled=dict(type='bool', aliases=['standardFlowEnabled']),
implicit_flow_enabled=dict(type='bool', aliases=['implicitFlowEnabled']),
direct_access_grants_enabled=dict(type='bool', aliases=['directAccessGrantsEnabled']),
service_accounts_enabled=dict(type='bool', aliases=['serviceAccountsEnabled']),
authorization_services_enabled=dict(type='bool', aliases=['authorizationServicesEnabled']),
public_client=dict(type='bool', aliases=['publicClient']),
frontchannel_logout=dict(type='bool', aliases=['frontchannelLogout']),
protocol=dict(type='str', choices=[PROTOCOL_OPENID_CONNECT, PROTOCOL_SAML, PROTOCOL_DOCKER_V2]),
attributes=dict(type='dict'),
full_scope_allowed=dict(type='bool', aliases=['fullScopeAllowed']),
node_re_registration_timeout=dict(type='int', aliases=['nodeReRegistrationTimeout']),
registered_nodes=dict(type='dict', aliases=['registeredNodes']),
client_template=dict(type='str', aliases=['clientTemplate']),
use_template_config=dict(type='bool', aliases=['useTemplateConfig']),
use_template_scope=dict(type='bool', aliases=['useTemplateScope']),
use_template_mappers=dict(type='bool', aliases=['useTemplateMappers']),
always_display_in_console=dict(type='bool', aliases=['alwaysDisplayInConsole']),
authentication_flow_binding_overrides=dict(
type='dict',
aliases=['authenticationFlowBindingOverrides'],
options=authentication_flow_spec,
required_one_of=[['browser', 'direct_grant', 'browser_name', 'direct_grant_name']],
mutually_exclusive=[['browser', 'browser_name'], ['direct_grant', 'direct_grant_name']],
state=dict(default="present", choices=["present", "absent"]),
realm=dict(type="str", default="master"),
id=dict(type="str"),
client_id=dict(type="str", aliases=["clientId"]),
name=dict(type="str"),
description=dict(type="str"),
root_url=dict(type="str", aliases=["rootUrl"]),
admin_url=dict(type="str", aliases=["adminUrl"]),
base_url=dict(type="str", aliases=["baseUrl"]),
surrogate_auth_required=dict(type="bool", aliases=["surrogateAuthRequired"]),
enabled=dict(type="bool"),
client_authenticator_type=dict(
type="str", choices=["client-secret", "client-jwt", "client-x509"], aliases=["clientAuthenticatorType"]
),
protocol_mappers=dict(type='list', elements='dict', options=protmapper_spec, aliases=['protocolMappers']),
authorization_settings=dict(type='dict', aliases=['authorizationSettings']),
client_scopes_behavior=dict(type='str', aliases=['clientScopesBehavior'], choices=['ignore', 'patch', 'idempotent'], default='ignore'),
default_client_scopes=dict(type='list', elements='str', aliases=['defaultClientScopes']),
optional_client_scopes=dict(type='list', elements='str', aliases=['optionalClientScopes']),
secret=dict(type="str", no_log=True),
registration_access_token=dict(type="str", aliases=["registrationAccessToken"], no_log=True),
default_roles=dict(type="list", elements="str", aliases=["defaultRoles"]),
redirect_uris=dict(type="list", elements="str", aliases=["redirectUris"]),
web_origins=dict(type="list", elements="str", aliases=["webOrigins"]),
not_before=dict(type="int", aliases=["notBefore"]),
bearer_only=dict(type="bool", aliases=["bearerOnly"]),
consent_required=dict(type="bool", aliases=["consentRequired"]),
standard_flow_enabled=dict(type="bool", aliases=["standardFlowEnabled"]),
implicit_flow_enabled=dict(type="bool", aliases=["implicitFlowEnabled"]),
direct_access_grants_enabled=dict(type="bool", aliases=["directAccessGrantsEnabled"]),
service_accounts_enabled=dict(type="bool", aliases=["serviceAccountsEnabled"]),
authorization_services_enabled=dict(type="bool", aliases=["authorizationServicesEnabled"]),
public_client=dict(type="bool", aliases=["publicClient"]),
frontchannel_logout=dict(type="bool", aliases=["frontchannelLogout"]),
protocol=dict(type="str", choices=[PROTOCOL_OPENID_CONNECT, PROTOCOL_SAML, PROTOCOL_DOCKER_V2]),
attributes=dict(type="dict"),
full_scope_allowed=dict(type="bool", aliases=["fullScopeAllowed"]),
node_re_registration_timeout=dict(type="int", aliases=["nodeReRegistrationTimeout"]),
registered_nodes=dict(type="dict", aliases=["registeredNodes"]),
client_template=dict(type="str", aliases=["clientTemplate"]),
use_template_config=dict(type="bool", aliases=["useTemplateConfig"]),
use_template_scope=dict(type="bool", aliases=["useTemplateScope"]),
use_template_mappers=dict(type="bool", aliases=["useTemplateMappers"]),
always_display_in_console=dict(type="bool", aliases=["alwaysDisplayInConsole"]),
authentication_flow_binding_overrides=dict(
type="dict",
aliases=["authenticationFlowBindingOverrides"],
options=authentication_flow_spec,
required_one_of=[["browser", "direct_grant", "browser_name", "direct_grant_name"]],
mutually_exclusive=[["browser", "browser_name"], ["direct_grant", "direct_grant_name"]],
),
protocol_mappers=dict(type="list", elements="dict", options=protmapper_spec, aliases=["protocolMappers"]),
authorization_settings=dict(type="dict", aliases=["authorizationSettings"]),
client_scopes_behavior=dict(
type="str", aliases=["clientScopesBehavior"], choices=["ignore", "patch", "idempotent"], default="ignore"
),
default_client_scopes=dict(type="list", elements="str", aliases=["defaultClientScopes"]),
optional_client_scopes=dict(type="list", elements="str", aliases=["optionalClientScopes"]),
)
argument_spec.update(meta_args)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True,
required_one_of=([['client_id', 'id'],
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
required_together=([['auth_username', 'auth_password']]),
required_by={'refresh_token': 'auth_realm'},
)
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_one_of=(
[
["client_id", "id"],
["token", "auth_realm", "auth_username", "auth_password", "auth_client_id", "auth_client_secret"],
]
),
required_together=([["auth_username", "auth_password"]]),
required_by={"refresh_token": "auth_realm"},
)
result = dict(changed=False, msg='', diff={}, proposed={}, existing={}, end_state={})
result = dict(changed=False, msg="", diff={}, proposed={}, existing={}, end_state={})
# Obtain access token, initialize API
try:
@ -1271,21 +1279,23 @@ def main():
kc = KeycloakAPI(module, connection_header)
realm = module.params.get('realm')
cid = module.params.get('id')
clientScopesBehavior = module.params.get('client_scopes_behavior')
state = module.params.get('state')
realm = module.params.get("realm")
cid = module.params.get("id")
clientScopesBehavior = module.params.get("client_scopes_behavior")
state = module.params.get("state")
# Filter and map the parameters names that apply to the client
client_params = [x for x in module.params
if x not in list(keycloak_argument_spec().keys()) + ['state', 'realm'] and
module.params.get(x) is not None]
client_params = [
x
for x in module.params
if x not in list(keycloak_argument_spec().keys()) + ["state", "realm"] and module.params.get(x) is not None
]
# See if it already exists in Keycloak
if cid is None:
before_client = kc.get_client_by_clientid(module.params.get('client_id'), realm=realm)
before_client = kc.get_client_by_clientid(module.params.get("client_id"), realm=realm)
if before_client is not None:
cid = before_client['id']
cid = before_client["id"]
else:
before_client = kc.get_client_by_id(cid, realm=realm)
@ -1302,15 +1312,15 @@ def main():
# Unfortunately, the ansible argument spec checker introduces variables with null values when
# they are not specified
if client_param == 'protocol_mappers':
if client_param == "protocol_mappers":
new_param_value = [{k: v for k, v in x.items() if v is not None} for x in new_param_value]
elif client_param == 'authentication_flow_binding_overrides':
elif client_param == "authentication_flow_binding_overrides":
new_param_value = flow_binding_from_dict_to_model(new_param_value, realm, kc)
elif client_param == 'attributes' and 'attributes' in before_client:
attributes_copy = copy.deepcopy(before_client['attributes'])
elif client_param == "attributes" and "attributes" in before_client:
attributes_copy = copy.deepcopy(before_client["attributes"])
attributes_copy.update(new_param_value)
new_param_value = attributes_copy
elif client_param in ['clientScopesBehavior', 'client_scopes_behavior']:
elif client_param in ["clientScopesBehavior", "client_scopes_behavior"]:
continue
changeset[camel(client_param)] = new_param_value
@ -1319,65 +1329,66 @@ def main():
desired_client = copy.deepcopy(before_client)
desired_client.update(changeset)
result['proposed'] = sanitize_cr(changeset)
result['existing'] = sanitize_cr(before_client)
result["proposed"] = sanitize_cr(changeset)
result["existing"] = sanitize_cr(before_client)
# Cater for when it doesn't exist (an empty dict)
if not before_client:
if state == 'absent':
if state == "absent":
# Do nothing and exit
if module._diff:
result['diff'] = dict(before='', after='')
result['changed'] = False
result['end_state'] = {}
result['msg'] = 'Client does not exist; doing nothing.'
result["diff"] = dict(before="", after="")
result["changed"] = False
result["end_state"] = {}
result["msg"] = "Client does not exist; doing nothing."
module.exit_json(**result)
# Process a creation
result['changed'] = True
result["changed"] = True
if 'clientId' not in desired_client:
module.fail_json(msg='client_id needs to be specified when creating a new client')
if 'protocol' not in desired_client:
desired_client['protocol'] = PROTOCOL_OPENID_CONNECT
if "clientId" not in desired_client:
module.fail_json(msg="client_id needs to be specified when creating a new client")
if "protocol" not in desired_client:
desired_client["protocol"] = PROTOCOL_OPENID_CONNECT
if module._diff:
result['diff'] = dict(before='', after=sanitize_cr(desired_client))
result["diff"] = dict(before="", after=sanitize_cr(desired_client))
if module.check_mode:
module.exit_json(**result)
# create it
kc.create_client(desired_client, realm=realm)
after_client = kc.get_client_by_clientid(desired_client['clientId'], realm=realm)
after_client = kc.get_client_by_clientid(desired_client["clientId"], realm=realm)
result['end_state'] = sanitize_cr(after_client)
result["end_state"] = sanitize_cr(after_client)
result['msg'] = f"Client {desired_client['clientId']} has been created."
result["msg"] = f"Client {desired_client['clientId']} has been created."
module.exit_json(**result)
else:
if state == 'present':
if state == "present":
# We can only compare the current client with the proposed updates we have
desired_client_with_scopes, before_client_with_scopes = normalise_scopes_for_behavior(desired_client, before_client, clientScopesBehavior)
desired_client_with_scopes, before_client_with_scopes = normalise_scopes_for_behavior(
desired_client, before_client, clientScopesBehavior
)
check_optional_scopes_not_default(desired_client, clientScopesBehavior, module)
before_norm = normalise_cr(before_client_with_scopes, remove_ids=True)
desired_norm = normalise_cr(desired_client_with_scopes, remove_ids=True)
# no changes
if before_norm == desired_norm:
result['changed'] = False
result['end_state'] = sanitize_cr(before_client)
result['msg'] = f"No changes required for Client {desired_client['clientId']}."
result["changed"] = False
result["end_state"] = sanitize_cr(before_client)
result["msg"] = f"No changes required for Client {desired_client['clientId']}."
module.exit_json(**result)
# Process an update
result['changed'] = True
result["changed"] = True
if module.check_mode:
result['end_state'] = sanitize_cr(desired_client_with_scopes)
result["end_state"] = sanitize_cr(desired_client_with_scopes)
if module._diff:
result['diff'] = dict(before=sanitize_cr(before_client),
after=sanitize_cr(desired_client))
result["diff"] = dict(before=sanitize_cr(before_client), after=sanitize_cr(desired_client))
module.exit_json(**result)
# do the update
@ -1392,34 +1403,33 @@ def main():
normalize_kc_resp(after_client)
if module._diff:
result['diff'] = dict(before=sanitize_cr(before_client),
after=sanitize_cr(after_client))
result["diff"] = dict(before=sanitize_cr(before_client), after=sanitize_cr(after_client))
result['end_state'] = sanitize_cr(after_client)
result["end_state"] = sanitize_cr(after_client)
result['msg'] = f"Client {desired_client['clientId']} has been updated."
result["msg"] = f"Client {desired_client['clientId']} has been updated."
module.exit_json(**result)
else:
# Process a deletion (because state was not 'present')
result['changed'] = True
result["changed"] = True
if module._diff:
result['diff'] = dict(before=sanitize_cr(before_client), after='')
result["diff"] = dict(before=sanitize_cr(before_client), after="")
if module.check_mode:
module.exit_json(**result)
# delete it
kc.delete_client(cid, realm=realm)
result['proposed'] = {}
result["proposed"] = {}
result['end_state'] = {}
result["end_state"] = {}
result['msg'] = f"Client {before_client['clientId']} has been deleted."
result["msg"] = f"Client {before_client['clientId']} has been deleted."
module.exit_json(**result)
if __name__ == '__main__':
if __name__ == "__main__":
main()