Example #1
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(),
            product=dict(),
            label=dict(),
            repositories=dict(required=True, type='list', elements='dict'),
            state=dict(default='enabled', choices=['disabled', 'enabled']),
        ),
        required_one_of=[['label', 'name']],
    )

    module_params = module.clean_params()

    module.connect()

    module_params['organization'] = module.find_resource_by_name('organizations', name=module_params['organization'], thin=True)
    scope = {'organization_id': module_params['organization']['id']}
    if 'product' in module_params:
        module_params['product'] = module.find_resource_by_name('products', name=module_params['product'], params=scope, thin=True)
        scope['product_id'] = module_params['product']['id']

    if 'label' in module_params:
        search = 'label="{0}"'.format(module_params['label'])
        repo_set = module.find_resource('repository_sets', search=search, params=scope)
    else:
        repo_set = module.find_resource_by_name('repository_sets', name=module_params['name'], params=scope)
    repo_set_scope = {'id': repo_set['id'], 'product_id': repo_set['product']['id']}
    repo_set_scope.update(scope)

    _available_repos_changed, available_repos = module.resource_action('repository_sets', 'available_repositories', params=repo_set_scope)
    available_repos = available_repos['results']
    current_repos = repo_set['repositories']
    desired_repos = get_desired_repos(module_params['repositories'], available_repos)

    available_repo_names = set(map(lambda repo: repo['repo_name'], available_repos))
    current_repo_names = set(map(lambda repo: repo['name'], current_repos))
    desired_repo_names = set(map(lambda repo: repo['repo_name'], desired_repos))

    if len(desired_repo_names - available_repo_names) > 0:
        module.fail_json(msg="Desired repositories are not available on the repository set {0}. Desired: {1} Available: {2}"
                         .format(module_params['name'], desired_repo_names, available_repo_names))

    changed = False
    if module.state == 'enabled':
        for repo in desired_repo_names - current_repo_names:
            repo_to_enable = next((r for r in available_repos if r['repo_name'] == repo))
            repo_change_params = repo_to_enable['substitutions'].copy()
            repo_change_params.update(repo_set_scope)
            if not module.check_mode:
                module.resource_action('repository_sets', 'enable', params=repo_change_params)
            changed = True
    elif module.state == 'disabled':
        for repo in current_repo_names & desired_repo_names:
            repo_to_disable = next((r for r in available_repos if r['repo_name'] == repo))
            repo_change_params = repo_to_disable['substitutions'].copy()
            repo_change_params.update(repo_set_scope)
            if not module.check_mode:
                module.resource_action('repository_sets', 'disable', params=repo_change_params)
            changed = True

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            content_view=dict(type='entity', flat_name='content_view_id', required=True),
            description=dict(),
            version=dict(),
            lifecycle_environments=dict(type='list'),
            force_promote=dict(type='bool', aliases=['force'], default=False),
            force_yum_metadata_regeneration=dict(type='bool', default=False),
            synchronous=dict(type='bool', default=True),
            current_lifecycle_environment=dict(),
        ),
        mutually_exclusive=[['current_lifecycle_environment', 'version']],
    )

    module.task_timeout = 60 * 60

    entity_dict = module.clean_params()

    # Do an early (not exhaustive) sanity check, whether we can perform this non-synchronous
    if (
        not module.desired_absent and 'lifecycle_environments' in entity_dict
        and 'version' not in entity_dict and 'current_lifecycle_environment' not in entity_dict
        and not entity_dict['synchronous']
    ):
        module.fail_json(msg="Cannot perform non-blocking publishing and promoting in the same module call.")

    module.connect()

    entity_dict['organization'] = module.find_resource_by_name('organizations', entity_dict['organization'], thin=True)
    scope = {'organization_id': entity_dict['organization']['id']}

    content_view = module.find_resource_by_name('content_views', name=entity_dict['content_view'], params=scope)

    if 'current_lifecycle_environment' in entity_dict:
        entity_dict['current_lifecycle_environment'] = module.find_resource_by_name(
            'lifecycle_environments', name=entity_dict['current_lifecycle_environment'], params=scope)
        search_scope = {'content_view_id': content_view['id'], 'environment_id': entity_dict['current_lifecycle_environment']['id']}
        content_view_version = module.find_resource('content_view_versions', search=None, params=search_scope)
    elif 'version' in entity_dict:
        search = "content_view_id={0},version={1}".format(content_view['id'], entity_dict['version'])
        content_view_version = module.find_resource('content_view_versions', search=search, failsafe=True)
    else:
        content_view_version = None

    changed = False
    le_changed = False
    if module.desired_absent:
        changed = module.ensure_entity_state('content_view_versions', None, content_view_version, params=scope)
    else:
        if content_view_version is None:
            # Do a sanity check, whether we can perform this non-synchronous
            if 'lifecycle_environments' in entity_dict and not entity_dict['synchronous']:
                module.fail_json(msg="Cannot perform non-blocking publishing and promoting in the same module call.")

            payload = {
                'id': content_view['id'],
            }
            if 'description' in entity_dict:
                payload['description'] = entity_dict['description']
            if 'force_yum_metadata_regeneration' in entity_dict:
                payload['force_yum_metadata_regeneration'] = entity_dict['force_yum_metadata_regeneration']
            if 'version' in entity_dict:
                split_version = list(map(int, str(entity_dict['version']).split('.')))
                payload['major'] = split_version[0]
                payload['minor'] = split_version[1]

            changed, response = module.resource_action('content_views', 'publish', params=payload, synchronous=entity_dict['synchronous'])
            content_view_version = module.show_resource('content_view_versions', response['output']['content_view_version_id'])

        if 'lifecycle_environments' in entity_dict:
            lifecycle_environments = module.find_resources_by_name('lifecycle_environments', names=entity_dict['lifecycle_environments'], params=scope)
            le_changed = promote_content_view_version(
                module, content_view_version, lifecycle_environments, synchronous=entity_dict['synchronous'],
                force=entity_dict['force_promote'],
                force_yum_metadata_regeneration=entity_dict['force_yum_metadata_regeneration'],
            )

    module.exit_json(changed=changed or le_changed)
Example #3
0
def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            name=dict(required=True),
            description=dict(),
            composite=dict(type='bool', default=False),
            auto_publish=dict(type='bool', default=False),
            components=dict(type='nested_list', entity_spec=cvc_entity_spec),
            repositories=dict(type='entity_list',
                              flat_name='repository_ids',
                              elements='dict',
                              options=dict(
                                  name=dict(required=True),
                                  product=dict(required=True),
                              )),
        ),
        argument_spec=dict(state=dict(
            default='present',
            choices=['present_with_defaults', 'present', 'absent']), ),
        mutually_exclusive=[['repositories', 'components']],
    )

    entity_dict = module.clean_params()

    # components is None when we're managing a CCV but don't want to adjust its components
    components = entity_dict.pop('components', None)
    if components:
        for component in components:
            if not component['latest'] and component.get(
                    'content_view_version') is None:
                module.fail_json(
                    msg=
                    "Content View Component must either have latest=True or provide a Content View Version."
                )

    module.connect()

    entity_dict, scope = module.handle_organization_param(entity_dict)

    if not module.desired_absent:
        if 'repositories' in entity_dict:
            if entity_dict['composite']:
                module.fail_json(
                    msg=
                    "Repositories cannot be parts of a Composite Content View."
                )
            else:
                repositories = []
                for repository in entity_dict['repositories']:
                    product = module.find_resource_by_name(
                        'products',
                        repository['product'],
                        params=scope,
                        thin=True)
                    repositories.append(
                        module.find_resource_by_name(
                            'repositories',
                            repository['name'],
                            params={'product_id': product['id']},
                            thin=True))
                entity_dict['repositories'] = repositories

    entity = module.find_resource_by_name('content_views',
                                          name=entity_dict['name'],
                                          params=scope,
                                          failsafe=True)

    content_view_entity = module.ensure_entity('content_views',
                                               entity_dict,
                                               entity,
                                               params=scope)

    # only update CVC's of newly created or updated CV's that are composite if components are specified
    update_dependent_entities = (module.state == 'present'
                                 or (module.state == 'present_with_defaults'
                                     and module.changed))
    if update_dependent_entities and content_view_entity[
            'composite'] and components is not None:
        if not module.changed:
            content_view_entity['content_view_components'] = entity[
                'content_view_components']
        current_cvcs = content_view_entity.get('content_view_components', [])

        # only record a subset of data
        current_cvcs_record = [{
            "id":
            cvc['id'],
            "content_view_id":
            cvc['content_view']['id'],
            "content_view_version_id":
            cvc['content_view_version']['id'],
            "latest":
            cvc['latest']
        } for cvc in current_cvcs]
        module.record_before(
            'content_views/components', {
                'composite_content_view_id': content_view_entity['id'],
                'content_view_components': current_cvcs_record
            })
        final_cvcs_record = copy.deepcopy(current_cvcs_record)

        components_to_add = []
        ccv_scope = {'composite_content_view_id': content_view_entity['id']}
        for component in components:
            cvc = {
                'content_view':
                module.find_resource_by_name('content_views',
                                             name=component['content_view'],
                                             params=scope),
                'latest':
                component['latest'],
            }
            cvc_matched = next(
                (item for item in current_cvcs
                 if item['content_view']['id'] == cvc['content_view']['id']),
                None)
            if not cvc['latest']:
                search = "content_view_id={0},version={1}".format(
                    cvc['content_view']['id'],
                    component['content_view_version'])
                cvc['content_view_version'] = module.find_resource(
                    'content_view_versions', search=search, thin=True)
                cvc['latest'] = False
                if cvc_matched and cvc_matched['latest']:
                    # When changing to latest=False & version is the latest we must send 'content_view_version' to the server
                    # Let's fake, it wasn't there...
                    cvc_matched.pop('content_view_version', None)
                    cvc_matched.pop('content_view_version_id', None)
            if cvc_matched:
                module.ensure_entity('content_view_components',
                                     cvc,
                                     cvc_matched,
                                     state='present',
                                     entity_spec=cvc_entity_spec,
                                     params=ccv_scope)
                current_cvcs.remove(cvc_matched)
            else:
                cvc['content_view_id'] = cvc.pop('content_view')['id']
                if 'content_view_version' in cvc:
                    cvc['content_view_version_id'] = cvc.pop(
                        'content_view_version')['id']
                components_to_add.append(cvc)

        if components_to_add:
            payload = {
                'composite_content_view_id': content_view_entity['id'],
                'components': components_to_add,
            }
            module.resource_action('content_view_components', 'add_components',
                                   payload)

            final_cvcs_record.extend(components_to_add)

        # desired cvcs have already been updated and removed from `current_cvcs`
        components_to_remove = [item['id'] for item in current_cvcs]
        if components_to_remove:
            payload = {
                'composite_content_view_id': content_view_entity['id'],
                'component_ids': components_to_remove,
            }
            module.resource_action('content_view_components',
                                   'remove_components', payload)

            final_cvcs_record = [
                item for item in final_cvcs_record
                if item['id'] not in components_to_remove
            ]

        module.record_after(
            'content_views/components', {
                'composite_content_view_id': content_view_entity['id'],
                'content_view_components': final_cvcs_record
            })
        module.record_after_full(
            'content_views/components', {
                'composite_content_view_id': content_view_entity['id'],
                'content_view_components': final_cvcs_record
            })

    module.exit_json()
Example #4
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(),
            product=dict(),
            label=dict(),
            repositories=dict(required=True, type='list', elements='dict'),
            state=dict(default='enabled', choices=['disabled', 'enabled']),
        ),
        required_one_of=[['label', 'name']],
    )

    module_params = module.clean_params()

    module.connect()

    module_params, scope = module.handle_organization_param(module_params)

    record_data = {}
    if 'product' in module_params:
        module_params['product'] = module.find_resource_by_name(
            'products', name=module_params['product'], params=scope, thin=True)
        scope['product_id'] = module_params['product']['id']
        record_data['product'] = module_params['product']

    if 'label' in module_params:
        search = 'label="{0}"'.format(module_params['label'])
        repo_set = module.find_resource('repository_sets',
                                        search=search,
                                        params=scope)
        record_data['label'] = module_params['label']
    else:
        repo_set = module.find_resource_by_name('repository_sets',
                                                name=module_params['name'],
                                                params=scope)
        record_data['name'] = module_params['name']

    repo_set_scope = {
        'id': repo_set['id'],
        'product_id': repo_set['product']['id']
    }
    repo_set_scope.update(scope)

    available_repos = module.resource_action('repository_sets',
                                             'available_repositories',
                                             params=repo_set_scope,
                                             ignore_check_mode=True)
    available_repos = available_repos['results']
    current_repos = repo_set['repositories']
    desired_repos = get_desired_repos(module_params['repositories'],
                                      available_repos)

    available_repo_names = set(
        map(lambda repo: repo['repo_name'], available_repos))
    current_repo_names = set(map(lambda repo: repo['name'], current_repos))
    desired_repo_names = set(map(lambda repo: repo['repo_name'],
                                 desired_repos))

    if len(module_params['repositories']) != len(desired_repo_names):
        repo_set_identification = ' '.join(
            ['{0}: {1}'.format(k, v) for (k, v) in record_data.items()])

        error_msg = "Desired repositories are not available on the repository set {0}.\nSearched: {1}\nFound: {2}\nAvailable: {3}".format(
            repo_set_identification, module_params['repositories'],
            desired_repo_names, available_repo_names)

        module.fail_json(msg=error_msg)

    if module.state == 'enabled':
        for repo in desired_repo_names - current_repo_names:
            repo_to_enable = next(
                (r for r in available_repos if r['repo_name'] == repo))
            repo_change_params = repo_to_enable['substitutions'].copy()
            repo_change_params.update(repo_set_scope)

            record_repository_set_state(module, record_data, repo, 'disabled',
                                        'enabled')

            module.resource_action('repository_sets',
                                   'enable',
                                   params=repo_change_params)
    elif module.state == 'disabled':
        for repo in current_repo_names & desired_repo_names:
            repo_to_disable = next(
                (r for r in available_repos if r['repo_name'] == repo))
            repo_change_params = repo_to_disable['substitutions'].copy()
            repo_change_params.update(repo_set_scope)

            record_repository_set_state(module, record_data, repo, 'enabled',
                                        'disabled')

            module.resource_action('repository_sets',
                                   'disable',
                                   params=repo_change_params)

    module.exit_json()
Example #5
0
def main():
    module = KatelloEntityAnsibleModule(
        foreman_spec=dict(
            content_view=dict(type='entity', required=True),
            description=dict(),
            version=dict(),
            lifecycle_environments=dict(type='list', elements='str'),
            force_promote=dict(type='bool', aliases=['force'], default=False),
            force_yum_metadata_regeneration=dict(type='bool', default=False),
            current_lifecycle_environment=dict(),
        ),
        mutually_exclusive=[['current_lifecycle_environment', 'version']],
    )

    module.task_timeout = 60 * 60

    module_params = module.clean_params()

    with module.api_connection():
        module_params, scope = module.handle_organization_param(module_params)

        content_view = module.find_resource_by_name(
            'content_views', name=module_params['content_view'], params=scope)

        if 'current_lifecycle_environment' in module_params:
            module_params[
                'current_lifecycle_environment'] = module.find_resource_by_name(
                    'lifecycle_environments',
                    name=module_params['current_lifecycle_environment'],
                    params=scope)
            search_scope = {
                'content_view_id':
                content_view['id'],
                'environment_id':
                module_params['current_lifecycle_environment']['id']
            }
            content_view_version = module.find_resource(
                'content_view_versions', search=None, params=search_scope)
        elif 'version' in module_params:
            search = "content_view_id={0},version={1}".format(
                content_view['id'], module_params['version'])
            content_view_version = module.find_resource(
                'content_view_versions', search=search, failsafe=True)
        else:
            content_view_version = None

        if module.desired_absent:
            module.ensure_entity('content_view_versions',
                                 None,
                                 content_view_version,
                                 params=scope)
        else:
            if content_view_version is None:
                payload = {
                    'id': content_view['id'],
                }
                if 'description' in module_params:
                    payload['description'] = module_params['description']
                if 'force_yum_metadata_regeneration' in module_params:
                    payload['force_yum_metadata_regeneration'] = module_params[
                        'force_yum_metadata_regeneration']
                if 'version' in module_params:
                    split_version = list(
                        map(int,
                            str(module_params['version']).split('.')))
                    payload['major'] = split_version[0]
                    payload['minor'] = split_version[1]

                response = module.resource_action('content_views',
                                                  'publish',
                                                  params=payload)
                # workaround for https://projects.theforeman.org/issues/28138
                if not module.check_mode:
                    content_view_version_id = response['output'].get(
                        'content_view_version_id') or response['input'].get(
                            'content_view_version_id')
                    content_view_version = module.show_resource(
                        'content_view_versions', content_view_version_id)
                else:
                    content_view_version = {'id': -1, 'environments': []}

            if 'lifecycle_environments' in module_params:
                lifecycle_environments = module.find_resources_by_name(
                    'lifecycle_environments',
                    names=module_params['lifecycle_environments'],
                    params=scope)
                promote_content_view_version(
                    module,
                    content_view_version,
                    lifecycle_environments,
                    force=module_params['force_promote'],
                    force_yum_metadata_regeneration=module_params[
                        'force_yum_metadata_regeneration'],
                )