def main():
    """
    Module execution

    :return:
    """
    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=['openid-connect', 'saml']),
        protocolMapper=dict(type='str'),
        config=dict(type='dict'),
    )

    meta_args = dict(
        realm=dict(type='str', default='master'),
        state=dict(default='present', choices=['present', 'absent']),
        id=dict(type='str'),
        name=dict(type='str'),
        description=dict(type='str'),
        protocol=dict(type='str', choices=['openid-connect', 'saml']),
        attributes=dict(type='dict'),
        full_scope_allowed=dict(type='bool'),
        protocol_mappers=dict(type='list',
                              elements='dict',
                              options=protmapper_spec),
    )
    argument_spec.update(meta_args)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=([['id', 'name']]))

    result = dict(changed=False,
                  msg='',
                  diff={},
                  proposed={},
                  existing={},
                  end_state={})

    # Obtain access token, initialize API
    try:
        connection_header = get_token(
            base_url=module.params.get('auth_keycloak_url'),
            validate_certs=module.params.get('validate_certs'),
            auth_realm=module.params.get('auth_realm'),
            client_id=module.params.get('auth_client_id'),
            auth_username=module.params.get('auth_username'),
            auth_password=module.params.get('auth_password'),
            client_secret=module.params.get('auth_client_secret'),
        )
    except KeycloakError as e:
        module.fail_json(msg=str(e))
    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    cid = module.params.get('id')

    # convert module parameters to client representation parameters (if they belong in there)
    clientt_params = [
        x for x in module.params if x not in [
            'state', 'auth_keycloak_url', 'auth_client_id', 'auth_realm',
            'auth_client_secret', 'auth_username', 'auth_password',
            'validate_certs', 'realm'
        ] and module.params.get(x) is not None
    ]

    # See whether the client template already exists in Keycloak
    if cid is None:
        before_clientt = kc.get_client_template_by_name(
            module.params.get('name'), realm=realm)
        if before_clientt is not None:
            cid = before_clientt['id']
    else:
        before_clientt = kc.get_client_template_by_id(cid, realm=realm)

    if before_clientt is None:
        before_clientt = dict()

    result['existing'] = before_clientt

    # Build a proposed changeset from parameters given to this module
    changeset = dict()

    for clientt_param in clientt_params:
        # lists in the Keycloak API are sorted
        new_param_value = module.params.get(clientt_param)
        if isinstance(new_param_value, list):
            try:
                new_param_value = sorted(new_param_value)
            except TypeError:
                pass
        changeset[camel(clientt_param)] = new_param_value

    # Whether creating or updating a client, take the before-state and merge the changeset into it
    updated_clientt = before_clientt.copy()
    updated_clientt.update(changeset)

    result['proposed'] = changeset

    # If the client template does not exist yet, before_client is still empty
    if before_clientt == dict():
        if state == 'absent':
            # do nothing and exit
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['msg'] = 'Client template does not exist, doing nothing.'
            module.exit_json(**result)

        # create new client template
        result['changed'] = True
        if 'name' not in updated_clientt:
            module.fail_json(
                msg='name needs to be specified when creating a new client')

        if module._diff:
            result['diff'] = dict(before='', after=updated_clientt)

        if module.check_mode:
            module.exit_json(**result)

        kc.create_client_template(updated_clientt, realm=realm)
        after_clientt = kc.get_client_template_by_name(updated_clientt['name'],
                                                       realm=realm)

        result['end_state'] = after_clientt

        result[
            'msg'] = 'Client template %s has been created.' % updated_clientt[
                'name']
        module.exit_json(**result)
    else:
        if state == 'present':
            # update existing client template
            result['changed'] = True
            if module.check_mode:
                # We can only compare the current client template with the proposed updates we have
                if module._diff:
                    result['diff'] = dict(before=before_clientt,
                                          after=updated_clientt)

                module.exit_json(**result)

            kc.update_client_template(cid, updated_clientt, realm=realm)

            after_clientt = kc.get_client_template_by_id(cid, realm=realm)
            if before_clientt == after_clientt:
                result['changed'] = False
            if module._diff:
                result['diff'] = dict(before=before_clientt,
                                      after=after_clientt)
            result['end_state'] = after_clientt

            result[
                'msg'] = 'Client template %s has been updated.' % updated_clientt[
                    'name']
            module.exit_json(**result)
        else:
            # Delete existing client
            result['changed'] = True
            if module._diff:
                result['diff']['before'] = before_clientt
                result['diff']['after'] = ''

            if module.check_mode:
                module.exit_json(**result)

            kc.delete_client_template(cid, realm=realm)
            result['proposed'] = dict()
            result['end_state'] = dict()
            result[
                'msg'] = 'Client template %s has been deleted.' % before_clientt[
                    'name']
            module.exit_json(**result)

    module.exit_json(**result)
Esempio n. 2
0
def main():
    """
    Module execution

    :return:
    """
    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=['openid-connect', 'saml']),
        protocolMapper=dict(type='str'),
        config=dict(type='dict'),
    )

    meta_args = dict(
        realm=dict(type='str', default='master'),
        state=dict(default='present', choices=['present', 'absent']),
        id=dict(type='str'),
        name=dict(type='str'),
        description=dict(type='str'),
        protocol=dict(type='str', choices=['openid-connect', 'saml']),
        attributes=dict(type='dict'),
        full_scope_allowed=dict(type='bool'),
        protocol_mappers=dict(type='list',
                              elements='dict',
                              options=protmapper_spec),
    )

    argument_spec.update(meta_args)

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_one_of=([['id', 'name'],
                          [
                              'token', 'auth_realm', 'auth_username',
                              'auth_password'
                          ]]),
        required_together=([['auth_realm', 'auth_username', 'auth_password']]))

    result = dict(changed=False,
                  msg='',
                  diff={},
                  proposed={},
                  existing={},
                  end_state={})

    # Obtain access token, initialize API
    try:
        connection_header = get_token(module.params)
    except KeycloakError as e:
        module.fail_json(msg=str(e))

    kc = KeycloakAPI(module, connection_header)

    realm = module.params.get('realm')
    state = module.params.get('state')
    cid = module.params.get('id')

    # Filter and map the parameters names that apply to the client template
    clientt_params = [
        x for x in module.params if x not in [
            'state', 'auth_keycloak_url', 'auth_client_id', 'auth_realm',
            'auth_client_secret', 'auth_username', 'auth_password',
            'validate_certs', 'realm'
        ] and module.params.get(x) is not None
    ]

    # See if it already exists in Keycloak
    if cid is None:
        before_clientt = kc.get_client_template_by_name(
            module.params.get('name'), realm=realm)
        if before_clientt is not None:
            cid = before_clientt['id']
    else:
        before_clientt = kc.get_client_template_by_id(cid, realm=realm)

    if before_clientt is None:
        before_clientt = {}

    result['existing'] = before_clientt

    # Build a proposed changeset from parameters given to this module
    changeset = {}

    for clientt_param in clientt_params:
        # lists in the Keycloak API are sorted
        new_param_value = module.params.get(clientt_param)
        if isinstance(new_param_value, list):
            try:
                new_param_value = sorted(new_param_value)
            except TypeError:
                pass
        changeset[camel(clientt_param)] = new_param_value

    # Prepare the desired values using the existing values (non-existence results in a dict that is save to use as a basis)
    desired_clientt = before_clientt.copy()
    desired_clientt.update(changeset)

    result['proposed'] = changeset

    # Cater for when it doesn't exist (an empty dict)
    if not before_clientt:
        if state == 'absent':
            # Do nothing and exit
            if module._diff:
                result['diff'] = dict(before='', after='')
            result['changed'] = False
            result['end_state'] = {}
            result['msg'] = 'Client template does not exist, doing nothing.'
            module.exit_json(**result)

        # Process a creation
        result['changed'] = True

        if 'name' not in desired_clientt:
            module.fail_json(
                msg='name needs to be specified when creating a new client')

        if module._diff:
            result['diff'] = dict(before='', after=desired_clientt)

        if module.check_mode:
            module.exit_json(**result)

        # create it
        kc.create_client_template(desired_clientt, realm=realm)
        after_clientt = kc.get_client_template_by_name(desired_clientt['name'],
                                                       realm=realm)

        result['end_state'] = after_clientt

        result[
            'msg'] = 'Client template %s has been created.' % desired_clientt[
                'name']
        module.exit_json(**result)

    else:
        if state == 'present':
            # Process an update

            result['changed'] = True
            if module.check_mode:
                # We can only compare the current client template with the proposed updates we have
                if module._diff:
                    result['diff'] = dict(before=before_clientt,
                                          after=desired_clientt)

                module.exit_json(**result)

            # do the update
            kc.update_client_template(cid, desired_clientt, realm=realm)

            after_clientt = kc.get_client_template_by_id(cid, realm=realm)
            if before_clientt == after_clientt:
                result['changed'] = False

            result['end_state'] = after_clientt

            if module._diff:
                result['diff'] = dict(before=before_clientt,
                                      after=after_clientt)

            result[
                'msg'] = 'Client template %s has been updated.' % desired_clientt[
                    'name']
            module.exit_json(**result)

        else:
            # Process a deletion (because state was not 'present')
            result['changed'] = True

            if module._diff:
                result['diff'] = dict(before=before_clientt, after='')

            if module.check_mode:
                module.exit_json(**result)

            # delete it
            kc.delete_client_template(cid, realm=realm)
            result['proposed'] = {}

            result['end_state'] = {}

            result[
                'msg'] = 'Client template %s has been deleted.' % before_clientt[
                    'name']

    module.exit_json(**result)