def main():
    module = ForemanProvisioningTemplateModule(
        argument_spec=dict(
            audit_comment=dict(),
            file_name=dict(type='path'),
            state=dict(default='present',
                       choices=['absent', 'present_with_defaults', 'present']),
            updated_name=dict(),
        ),
        foreman_spec=dict(
            kind=dict(choices=[
                'Bootdisk',
                'cloud-init',
                'finish',
                'iPXE',
                'job_template',
                'kexec',
                'POAP',
                'provision',
                'ptable',
                'PXEGrub',
                'PXEGrub2',
                'PXELinux',
                'registration',
                'script',
                'snippet',
                'user_data',
                'ZTP',
            ],
                      type='entity',
                      flat_name='template_kind_id',
                      resolve=False),
            template=dict(),
            locked=dict(type='bool'),
            name=dict(),
            operatingsystems=dict(type='entity_list'),
            snippet=dict(invisible=True),
        ),
        mutually_exclusive=[
            ['file_name', 'template'],
        ],
        required_one_of=[
            ['name', 'file_name', 'template'],
        ],
    )

    # We do not want a template text for bulk operations
    if module.foreman_params.get('name') == '*':
        if module.foreman_params.get('file_name') or module.foreman_params.get(
                'template') or module.foreman_params.get('updated_name'):
            module.fail_json(
                msg=
                "Neither file_name nor template nor updated_name allowed if 'name: *'!"
            )

    entity = None
    file_name = module.foreman_params.pop('file_name', None)

    if file_name or 'template' in module.foreman_params:
        if file_name:
            parsed_dict = parse_template_from_file(file_name, module)
        else:
            parsed_dict = parse_template(module.foreman_params['template'],
                                         module)
        # sanitize name from template data
        # The following condition can actually be hit, when someone is trying to import a
        # template with the name set to '*'.
        # Besides not being sensible, this would go horribly wrong in this module.
        if parsed_dict.get('name') == '*':
            module.fail_json(msg="Cannot use '*' as a template name!")
        # module params are priorized
        parsed_dict.update(module.foreman_params)
        module.foreman_params = parsed_dict

    # make sure, we have a name
    if 'name' not in module.foreman_params:
        if file_name:
            module.foreman_params['name'] = os.path.splitext(
                os.path.basename(file_name))[0]
        else:
            module.fail_json(
                msg='No name specified and no filename to infer it.')

    affects_multiple = module.foreman_params['name'] == '*'
    # sanitize user input, filter unuseful configuration combinations with 'name: *'
    if affects_multiple:
        if module.foreman_params.get('updated_name'):
            module.fail_json(msg="updated_name not allowed if 'name: *'!")
        if module.state == 'present_with_defaults':
            module.fail_json(
                msg=
                "'state: present_with_defaults' and 'name: *' cannot be used together"
            )
        if module.desired_absent:
            further_params = set(
                module.foreman_params.keys()) - {'name', 'entity'}
            if further_params:
                module.fail_json(
                    msg=
                    'When deleting all templates, there is no need to specify further parameters: %s '
                    % further_params)

    with module.api_connection():
        if 'audit_comment' in module.foreman_params:
            extra_params = {
                'audit_comment': module.foreman_params['audit_comment']
            }
        else:
            extra_params = {}

        if affects_multiple:
            module.set_entity('entity', None)  # prevent lookup
            entities = module.list_resource('provisioning_templates')
            if not entities:
                # Nothing to do; shortcut to exit
                module.exit_json()
            if not module.desired_absent:  # not 'thin'
                entities = [
                    module.show_resource('provisioning_templates',
                                         entity['id']) for entity in entities
                ]
                module.auto_lookup_entities()
            module.foreman_params.pop('name')
            for entity in entities:
                module.ensure_entity('provisioning_templates',
                                     module.foreman_params,
                                     entity,
                                     params=extra_params)
        else:
            # The name could have been determined to late, so copy it again
            module.foreman_params['entity'] = module.foreman_params['name']

            module.foreman_params = find_template_kind(module,
                                                       module.foreman_params)

            module.run(params=extra_params)
def main():
    module = ForemanJobTemplateModule(
        foreman_spec=dict(
            description_format=dict(),
            job_category=dict(),
            locked=dict(type='bool', default=False),
            name=dict(),
            provider_type=dict(),
            snippet=dict(type='bool'),
            template=dict(),
            template_inputs=dict(
                type='nested_list',
                foreman_spec=template_input_foreman_spec,
                required_if=(
                    ['input_type', 'fact', ('fact_name', )],
                    ['input_type', 'variable', ('variable_name', )],
                    [
                        'input_type', 'puppet_parameter',
                        ('puppet_class_name', 'puppet_parameter_name')
                    ],
                ),
            ),
        ),
        argument_spec=dict(
            audit_comment=dict(),
            file_name=dict(type='path'),
            state=dict(default='present',
                       choices=['absent', 'present_with_defaults', 'present']),
        ),
        mutually_exclusive=[
            ['file_name', 'template'],
        ],
        required_one_of=[
            ['name', 'file_name', 'template'],
        ],
    )

    # We do not want a layout text for bulk operations
    if module.foreman_params.get('name') == '*':
        if module.foreman_params.get('file_name') or module.foreman_params.get(
                'template'):
            module.fail_json(
                msg="Neither file_name nor template allowed if 'name: *'!")

    entity = None
    file_name = module.foreman_params.pop('file_name', None)

    if file_name or 'template' in module.foreman_params:
        if file_name:
            parsed_dict = parse_template_from_file(file_name, module)
        else:
            parsed_dict = parse_template(module.foreman_params['template'],
                                         module)
        # sanitize name from template data
        # The following condition can actually be hit, when someone is trying to import a
        # template with the name set to '*'.
        # Besides not being sensible, this would go horribly wrong in this module.
        if parsed_dict.get('name') == '*':
            module.fail_json(msg="Cannot use '*' as a job template name!")
        # module params are priorized
        parsed_dict.update(module.foreman_params)
        # make sure certain values are set
        module.foreman_params = template_defaults.copy()
        module.foreman_params.update(parsed_dict)

    # make sure, we have a name
    if 'name' not in module.foreman_params:
        if file_name:
            module.foreman_params['name'] = os.path.splitext(
                os.path.basename(file_name))[0]
        else:
            module.fail_json(
                msg='No name specified and no filename to infer it.')

    affects_multiple = module.foreman_params['name'] == '*'
    # sanitize user input, filter unuseful configuration combinations with 'name: *'
    if affects_multiple:
        if module.state == 'present_with_defaults':
            module.fail_json(
                msg=
                "'state: present_with_defaults' and 'name: *' cannot be used together"
            )
        if module.desired_absent:
            further_params = set(
                module.foreman_params.keys()) - {'name', 'entity'}
            if further_params:
                module.fail_json(
                    msg=
                    'When deleting all job templates, there is no need to specify further parameters: %s '
                    % further_params)

    with module.api_connection():
        if 'audit_comment' in module.foreman_params:
            extra_params = {
                'audit_comment': module.foreman_params['audit_comment']
            }
        else:
            extra_params = {}

        if affects_multiple:
            module.set_entity('entity', None)  # prevent lookup
            entities = module.list_resource('job_templates')
            if not entities:
                # Nothing to do; shortcut to exit
                module.exit_json()
            if not module.desired_absent:  # not 'thin'
                entities = [
                    module.show_resource('job_templates', entity['id'])
                    for entity in entities
                ]
                module.auto_lookup_entities()
            module.foreman_params.pop('name')
            for entity in entities:
                module.ensure_entity('job_templates',
                                     module.foreman_params,
                                     entity,
                                     params=extra_params)
        else:
            # The name could have been determined to late, so copy it again
            module.foreman_params['entity'] = module.foreman_params['name']
            entity = module.lookup_entity('entity')
            # TemplateInputs need to be added as separate entities later
            template_inputs = module.foreman_params.get('template_inputs')

            job_template = module.run(params=extra_params)

            update_dependent_entities = (
                module.state == 'present' or
                (module.state == 'present_with_defaults' and module.changed))
            if update_dependent_entities and template_inputs is not None:
                scope = {'template_id': job_template['id']}

                # Manage TemplateInputs here
                current_template_input_list = module.list_resource(
                    'template_inputs', params=scope) if entity else []
                current_template_inputs = {
                    item['name']: item
                    for item in current_template_input_list
                }
                for template_input_dict in template_inputs:
                    template_input_entity = current_template_inputs.pop(
                        template_input_dict['name'], None)

                    module.ensure_entity(
                        'template_inputs',
                        template_input_dict,
                        template_input_entity,
                        params=scope,
                        foreman_spec=template_input_foreman_spec,
                    )

                # At this point, desired template inputs have been removed from the dict.
                for template_input_entity in current_template_inputs.values():
                    module.ensure_entity(
                        'template_inputs',
                        None,
                        template_input_entity,
                        state="absent",
                        params=scope,
                        foreman_spec=template_input_foreman_spec,
                    )
def main():
    module = ForemanPtableModule(
        argument_spec=dict(
            file_name=dict(type='path'),
            state=dict(default='present',
                       choices=['absent', 'present_with_defaults', 'present']),
            updated_name=dict(),
        ),
        foreman_spec=dict(
            layout=dict(),
            locked=dict(type='bool'),
            name=dict(),
            os_family=dict(choices=OS_LIST),
        ),
        mutually_exclusive=[
            ['file_name', 'layout'],
        ],
        required_one_of=[
            ['name', 'file_name', 'layout'],
        ],
    )

    # We do not want a layout text for bulk operations
    if module.foreman_params.get('name') == '*':
        if module.foreman_params.get('file_name') or module.foreman_params.get(
                'layout') or module.foreman_params.get('updated_name'):
            module.fail_json(
                msg=
                "Neither file_name nor layout nor updated_name allowed if 'name: *'!"
            )

    entity = None
    file_name = module.foreman_params.pop('file_name', None)

    if file_name or 'layout' in module.foreman_params:
        if file_name:
            parsed_dict = parse_template_from_file(file_name, module)
        else:
            parsed_dict = parse_template(module.foreman_params['layout'],
                                         module)
        parsed_dict['layout'] = parsed_dict.pop('template')
        if 'oses' in parsed_dict:
            parsed_dict['os_family'] = parsed_dict.pop('oses')
        # sanitize name from template data
        # The following condition can actually be hit, when someone is trying to import a
        # template with the name set to '*'.
        # Besides not being sensible, this would go horribly wrong in this module.
        if parsed_dict.get('name') == '*':
            module.fail_json(msg="Cannot use '*' as a partition table name!")
        # module params are priorized
        parsed_dict.update(module.foreman_params)
        module.foreman_params = parsed_dict

    # make sure, we have a name
    if 'name' not in module.foreman_params:
        if file_name:
            module.foreman_params['name'] = os.path.splitext(
                os.path.basename(file_name))[0]
        else:
            module.fail_json(
                msg='No name specified and no filename to infer it.')

    affects_multiple = module.foreman_params['name'] == '*'
    # sanitize user input, filter unuseful configuration combinations with 'name: *'
    if affects_multiple:
        if module.state == 'present_with_defaults':
            module.fail_json(
                msg=
                "'state: present_with_defaults' and 'name: *' cannot be used together"
            )
        if module.desired_absent:
            further_params = set(
                module.foreman_params.keys()) - {'name', 'entity'}
            if further_params:
                module.fail_json(
                    msg=
                    'When deleting all partition tables, there is no need to specify further parameters: %s '
                    % further_params)

    with module.api_connection():
        if affects_multiple:
            module.set_entity('entity', None)  # prevent lookup
            entities = module.list_resource('ptables')
            if not entities:
                # Nothing to do; shortcut to exit
                module.exit_json()
            if not module.desired_absent:  # not 'thin'
                entities = [
                    module.show_resource('ptables', entity['id'])
                    for entity in entities
                ]
                module.auto_lookup_entities()
            module.foreman_params.pop('name')
            for entity in entities:
                module.ensure_entity('ptables', module.foreman_params, entity)
        else:
            # The name could have been determined to late, so copy it again
            module.foreman_params['entity'] = module.foreman_params['name']

            module.run()