def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            name=dict(required=True),
            label=dict(),
            description=dict(),
            prior=dict(type='entity', flat_name='prior_id'),
        ),
    )

    entity_dict = module.clean_params()

    module.connect()

    entity_dict['organization'] = module.find_resource_by_name('organizations', entity_dict['organization'], thin=True)
    scope = {'organization_id': entity_dict['organization']['id']}
    entity = module.find_resource_by_name('lifecycle_environments', name=entity_dict['name'], params=scope, failsafe=True)
    if not module.desired_absent:
        if 'prior' in entity_dict:
            entity_dict['prior'] = module.find_resource_by_name('lifecycle_environments', entity_dict['prior'], params=scope, thin=True)
        # Default to 'Library' for new env with no 'prior' provided
        elif not entity:
            entity_dict['prior'] = module.find_resource_by_name('lifecycle_environments', 'Library', params=scope, thin=True)

    if entity:
        if 'label' in entity_dict and entity_dict['label'] and entity['label'] != entity_dict['label']:
            module.fail_json(msg="Label cannot be updated on a lifecycle environment.")

        if 'prior' in entity_dict and entity['prior']['id'] != entity_dict['prior']['id']:
            module.fail_json(msg="Prior cannot be updated on a lifecycle environment.")

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

    module.exit_json()
Example #2
0
def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            name=dict(required=True),
            description=dict(),
            interval=dict(choices=['hourly', 'daily', 'weekly', 'custom cron'], required=True),
            enabled=dict(type='bool', required=True),
            sync_date=dict(required=True),
            cron_expression=dict(),
            state=dict(default='present', choices=['present_with_defaults', 'present', 'absent']),
        ),
        argument_spec=dict(
            products=dict(type='list'),
        ),
        required_if=[
            ['interval', 'custom cron', ['cron_expression']],
        ],
    )

    entity_dict = module.clean_params()

    if (entity_dict['interval'] != 'custom cron') and ('cron_expression' in entity_dict):
        module.fail_json(msg='"cron_expression" cannot be combined with "interval"!="custom cron".')

    module.connect()

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

    products = entity_dict.pop('products', None)

    changed, sync_plan = module.ensure_entity('sync_plans', entity_dict, entity, params=scope)

    if not (module.desired_absent or module.state == 'present_with_defaults') and products is not None:
        products = module.find_resources_by_name('products', products, params=scope, thin=True)
        desired_product_ids = set(product['id'] for product in products)
        current_product_ids = set(product['id'] for product in entity['products']) if entity else set()

        if desired_product_ids != current_product_ids:
            if not module.check_mode:
                product_ids_to_add = desired_product_ids - current_product_ids
                if product_ids_to_add:
                    payload = {
                        'id': sync_plan['id'],
                        'product_ids': list(product_ids_to_add),
                    }
                    payload.update(scope)
                    module.resource_action('sync_plans', 'add_products', payload)
                product_ids_to_remove = current_product_ids - desired_product_ids
                if product_ids_to_remove:
                    payload = {
                        'id': sync_plan['id'],
                        'product_ids': list(product_ids_to_remove),
                    }
                    payload.update(scope)
                    module.resource_action('sync_plans', 'remove_products', payload)
            changed = True

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            updated_name=dict(),
        ),
        entity_spec=dict(
            name=dict(required=True),
            description=dict(),
        ),
    )

    entity_dict = module.clean_params()

    module.connect()

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

    if entity and 'updated_name' in entity_dict:
        entity_dict['name'] = entity_dict.pop('updated_name')

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

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

    (module_params, state) = module.parse_params()
    name = module_params.get('name')
    product = module_params.get('product')
    label = module_params.get('label')
    organization = module_params.get('organization')
    repositories = module_params.get('repositories')

    module.connect()

    try:
        changed = repository_set(module, name, organization, product, label, state, repositories=repositories)
        module.exit_json(changed=changed)
    except Exception as e:
        module.fail_json(msg=e)
Example #5
0
def main():
    module = KatelloEntityAnsibleModule(entity_spec=dict(
        name=dict(required=True),
        content_type=dict(required=True, choices=['gpg_key', 'cert']),
        content=dict(required=True),
    ), )

    entity_dict = module.clean_params()

    module.connect()

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

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

    module.exit_json()
Example #6
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            product=dict(required=True),
            label=dict(),
            name=dict(required=True),
            content_type=dict(
                required=True,
                choices=['docker', 'ostree', 'yum', 'puppet', 'file', 'deb']),
            url=dict(),
            gpg_key=dict(),
            docker_upstream_name=dict(),
            download_policy=dict(
                choices=['background', 'immediate', 'on_demand']),
            mirror_on_sync=dict(type='bool', default=True),
            state=dict(default='present',
                       choices=['present_with_defaults', 'present', 'absent']),
        ),
        supports_check_mode=True,
    )

    (entity_dict, state) = module.parse_params()

    if entity_dict[
            'content_type'] != 'docker' and 'docker_upstream_name' in entity_dict:
        module.fail_json(
            msg=
            "docker_upstream_name should not be set unless content_type: docker"
        )

    module.connect()

    entity_dict['organization'] = find_organization(
        module, name=entity_dict['organization'])

    entity_dict['product'] = find_product(
        module,
        name=entity_dict['product'],
        organization=entity_dict['organization'])

    if 'gpg_key' in entity_dict:
        entity_dict['gpg_key'] = find_content_credential(
            module,
            name=entity_dict['gpg_key'],
            organization=entity_dict['organization'])

    entity = find_repository(module,
                             name=entity_dict['name'],
                             product=entity_dict['product'],
                             failsafe=True)

    entity_dict = sanitize_entity_dict(entity_dict, name_map)

    changed = naildown_entity_state(Repository, entity_dict, entity, state,
                                    module)

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            name=dict(required=True),
            updated_name=dict(),
            login=dict(),
            scc_account_password=dict(no_log=True, flat_name='password'),
            base_url=dict(),
            sync_date=dict(),
            interval=dict(choices=['never', 'daily', 'weekly', 'monthly']),
            state=dict(default='present', choices=['present', 'absent', 'synced']),
        ),
        argument_spec=dict(
            test_connection=dict(type='bool', default=False),
        ),
    )

    entity_dict = module.clean_params()

    module.task_timeout = 4 * 60

    module.connect()

    entity_dict, scope = module.handle_organization_param(entity_dict)

    failsafe = (module.state != 'synced')

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

    if not module.desired_absent:
        if not entity:
            if 'login' not in entity_dict:
                module.fail_json(msg="scc account login not provided")
            if 'scc_account_password' not in entity_dict:
                module.fail_json(msg="Scc account password not provided")

        if entity_dict['test_connection']:
            scc_account_credentials = {}
            if entity:
                scc_account_credentials['id'] = entity['id']
            if 'login' in entity_dict:
                scc_account_credentials['login'] = entity_dict['login']
            if 'scc_account_password' in entity_dict:
                scc_account_credentials['password'] = entity_dict['scc_account_password']
            if 'base_url' in entity_dict:
                scc_account_credentials['base_url'] = entity_dict['base_url']
            module.resource_action('scc_accounts', 'test_connection', scc_account_credentials, ignore_check_mode=True)

    if 'updated_name' in entity_dict:
        entity_dict['name'] = entity_dict.pop('updated_name')

    if module.state == 'synced':
        module.resource_action('scc_accounts', 'sync', {'id': entity['id']})
    else:
        module.ensure_entity('scc_accounts', entity_dict, entity, params=scope)

    module.exit_json()
Example #8
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(product=dict(required=True), ),
        entity_spec=dict(
            label=dict(),
            name=dict(required=True),
            content_type=dict(
                required=True,
                choices=['docker', 'ostree', 'yum', 'puppet', 'file', 'deb']),
            url=dict(),
            gpg_key=dict(type='entity', flat_name='gpg_key_id'),
            docker_upstream_name=dict(),
            download_policy=dict(
                choices=['background', 'immediate', 'on_demand']),
            mirror_on_sync=dict(type='bool', default=True),
            state=dict(default='present',
                       choices=['present_with_defaults', 'present', 'absent']),
        ),
    )

    entity_dict = module.clean_params()

    if entity_dict[
            'content_type'] != 'docker' and 'docker_upstream_name' in entity_dict:
        module.fail_json(
            msg=
            "docker_upstream_name should not be set unless content_type: docker"
        )

    module.connect()

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

    if not module.desired_absent:
        if 'gpg_key' in entity_dict:
            entity_dict['gpg_key'] = module.find_resource_by_name(
                'content_credentials',
                name=entity_dict['gpg_key'],
                params=scope,
                thin=True)

    scope['product_id'] = entity_dict['product']['id']
    entity = module.find_resource_by_name('repositories',
                                          name=entity_dict['name'],
                                          params=scope,
                                          failsafe=True)

    changed = module.ensure_entity_state('repositories',
                                         entity_dict,
                                         entity,
                                         params=scope)

    module.exit_json(changed=changed)
Example #9
0
def main():
    module = KatelloEntityAnsibleModule(entity_spec=dict(
        name=dict(required=True),
        label=dict(),
        gpg_key=dict(type='entity', flat_name='gpg_key_id'),
        sync_plan=dict(type='entity', flat_name='sync_plan_id'),
        description=dict(),
        state=dict(default='present',
                   choices=['present_with_defaults', 'present', 'absent']),
    ), )

    entity_dict = module.clean_params()

    module.connect()

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

    if not module.desired_absent:
        if 'gpg_key' in entity_dict:
            entity_dict['gpg_key'] = module.find_resource_by_name(
                'content_credentials',
                name=entity_dict['gpg_key'],
                params=scope,
                thin=True)

        if 'sync_plan' in entity_dict:
            entity_dict['sync_plan'] = module.find_resource_by_name(
                'sync_plans',
                name=entity_dict['sync_plan'],
                params=scope,
                thin=True)

    changed = module.ensure_entity_state('products',
                                         entity_dict,
                                         entity,
                                         params=scope)

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            label=dict(),
            gpg_key=dict(),
            sync_plan=dict(),
            description=dict(),
            state=dict(default='present',
                       choices=['present_with_defaults', 'present', 'absent']),
        ),
        supports_check_mode=True,
    )

    (entity_dict, state) = module.parse_params()

    module.connect()

    entity_dict['organization'] = find_organization(
        module, name=entity_dict['organization'])

    if 'gpg_key' in entity_dict:
        entity_dict['gpg_key'] = find_content_credential(
            module,
            name=entity_dict['gpg_key'],
            organization=entity_dict['organization'])

    if 'sync_plan' in entity_dict:
        entity_dict['sync_plan'] = find_sync_plan(
            module,
            name=entity_dict['sync_plan'],
            organization=entity_dict['organization'])

    entity = find_product(module,
                          name=entity_dict['name'],
                          organization=entity_dict['organization'],
                          failsafe=True)

    entity_dict = sanitize_entity_dict(entity_dict, name_map)

    changed = naildown_entity_state(Product, entity_dict, entity, state,
                                    module)

    module.exit_json(changed=changed)
Example #11
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            label=dict(),
            description=dict(),
            prior=dict(),
        ),
        supports_check_mode=True,
    )

    (module_params, state) = module.parse_params()
    name = module_params.get('name')
    label = module_params.get(
        'label') if module_params.get('label') != '' else None
    description = module_params.get('description')
    prior = None if module_params.get('prior') == '' else module_params.get(
        'prior')
    organization = module_params.get('organization')

    module.connect()

    validate_params(module,
                    state,
                    label=label,
                    description=description,
                    prior=prior)

    try:
        changed = lifecycle_environment(module,
                                        name,
                                        organization,
                                        state,
                                        label=label,
                                        description=description,
                                        prior=prior)
        module.exit_json(changed=changed)
    except Exception as e:
        module.fail_json(msg=e)
def main():
    module = KatelloEntityAnsibleModule(entity_spec=dict(
        name=dict(required=True),
        description=dict(),
    ), )

    entity_dict = module.clean_params()

    module.connect()

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

    changed = module.ensure_entity_state('host_collections',
                                         entity_dict,
                                         entity,
                                         params=scope)

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            composite=dict(type='bool', default=False),
            auto_publish=dict(type='bool', default=False),
            components=dict(type='list'),
            repositories=dict(type='list'),
            state=dict(default='present',
                       choices=['present_with_defaults', 'present', 'absent']),
        ),
        mutually_exclusive=[['repositories', 'components']],
    )

    (entity_dict, state) = module.parse_params()

    module.connect()

    entity_dict['organization'] = find_organization(
        module, name=entity_dict['organization'])
    if 'repositories' in entity_dict and not entity_dict['composite']:
        entity_dict['repositories'] = find_repositories(
            module, entity_dict['repositories'], entity_dict['organization'])

    content_view_entity = find_content_view(
        module,
        name=entity_dict['name'],
        organization=entity_dict['organization'],
        failsafe=True)
    content_view_dict = sanitize_entity_dict(entity_dict, name_map)

    changed, content_view_entity = naildown_entity(ContentView,
                                                   content_view_dict,
                                                   content_view_entity, state,
                                                   module)

    # only update CVC's of newly created or updated CCV's
    if state == 'present' or (state == 'present_with_defaults' and changed):
        current_cvcs = []
        if hasattr(content_view_entity, 'content_view_component'):
            current_cvcs = [
                cvc.read()
                for cvc in content_view_entity.content_view_component
            ]
        if 'components' in entity_dict and content_view_entity.composite:
            for component in entity_dict['components']:
                cvc = component.copy()
                cvc['content_view'] = find_content_view(
                    module,
                    name=component['content_view'],
                    organization=entity_dict['organization'])
                cvc_matched = None
                for _cvc in current_cvcs:
                    if _cvc.content_view.id == cvc['content_view'].id:
                        cvc_matched = _cvc
                force_update = list()
                if 'version' in component:
                    cvc['version'] = find_content_view_version(
                        module,
                        cvc['content_view'],
                        version=component['version'])
                    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
                        force_update.append('content_view_version')
                if cvc_matched:
                    cvc['composite_content_view'] = content_view_entity
                    cvc_dict = sanitize_entity_dict(cvc, cvc_map)
                    cvc_changed = naildown_entity_state(
                        ContentViewComponent,
                        cvc_dict,
                        cvc_matched,
                        'present',
                        module,
                        force_update=force_update)
                    current_cvcs.remove(cvc_matched)
                    if cvc_changed:
                        changed = cvc_changed
                else:
                    for attr in ['latest', 'version']:
                        if attr not in cvc:
                            cvc[attr] = None
                    ContentViewComponent(
                        composite_content_view=content_view_entity,
                        content_view=cvc['content_view'],
                        latest=cvc['latest'],
                        content_view_version=cvc['version']).add()
                    changed = True
        for cvc in current_cvcs:
            # desired cvcs have already been updated and removed from `current_cvcs`
            cvc.remove()
            changed = True

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        entity_spec=dict(
            name=dict(required=True),
            new_name=dict(),
            lifecycle_environment=dict(type='entity',
                                       flat_name='environment_id'),
            content_view=dict(type='entity', flat_name='content_view_id'),
            host_collections=dict(type='entity_list',
                                  flat_name='host_collection_ids'),
            auto_attach=dict(type='bool'),
            release_version=dict(),
            service_level=dict(
                choices=['Self-Support', 'Standard', 'Premium']),
        ),
        argument_spec=dict(
            subscriptions=dict(
                type='list',
                elements='dict',
                options=dict(
                    name=dict(),
                    pool_id=dict(),
                ),
                required_one_of=[['name', 'pool_id']],
                mutually_exclusive=[['name', 'pool_id']],
            ),
            content_overrides=dict(type='list',
                                   elements='dict',
                                   options=dict(
                                       label=dict(required=True),
                                       override=dict(
                                           required=True,
                                           choices=['enabled', 'disabled']),
                                   )),
            state=dict(default='present',
                       choices=[
                           'present', 'present_with_defaults', 'absent',
                           'copied'
                       ]),
        ),
        required_if=[
            ['state', 'copied', ['new_name']],
        ],
    )

    entity_dict = module.clean_params()

    module.connect()

    entity_dict['organization'] = module.find_resource_by_name(
        'organizations', entity_dict['organization'], thin=True)
    scope = {'organization_id': entity_dict['organization']['id']}
    if not module.desired_absent:
        if 'lifecycle_environment' in entity_dict:
            entity_dict[
                'lifecycle_environment'] = module.find_resource_by_name(
                    'lifecycle_environments',
                    entity_dict['lifecycle_environment'],
                    params=scope,
                    thin=True)

        if 'content_view' in entity_dict:
            entity_dict['content_view'] = module.find_resource_by_name(
                'content_views',
                entity_dict['content_view'],
                params=scope,
                thin=True)

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

    if module.state == 'copied':
        new_entity = module.find_resource_by_name('activation_keys',
                                                  name=entity_dict['new_name'],
                                                  params=scope,
                                                  failsafe=True)
        if new_entity is not None:
            module.warn("Activation Key '{0}' already exists.".format(
                entity_dict['new_name']))
            module.exit_json(changed=False)

    subscriptions = entity_dict.pop('subscriptions', None)
    content_overrides = entity_dict.pop('content_overrides', None)
    host_collections = entity_dict.pop('host_collections', None)
    changed, activation_key = module.ensure_entity('activation_keys',
                                                   entity_dict,
                                                   entity,
                                                   params=scope)

    # only update subscriptions of newly created or updated AKs
    # copied keys inherit the subscriptions of the origin, so one would not have to specify them again
    # deleted keys don't need subscriptions anymore either
    if module.state == 'present' or (module.state == 'present_with_defaults'
                                     and changed):
        # the auto_attach, release_version and service_level parameters can only be set on an existing AK with an update,
        # not during create, so let's force an update. see https://projects.theforeman.org/issues/27632 for details
        if any(key in entity_dict
               for key in ['auto_attach', 'release_version', 'service_level'
                           ]) and changed:
            _activation_key_changed, activation_key = module.ensure_entity(
                'activation_keys', entity_dict, activation_key, params=scope)

        ak_scope = {'activation_key_id': activation_key['id']}
        if subscriptions is not None:
            desired_subscriptions = []
            for subscription in subscriptions:
                if subscription['name'] is not None and subscription[
                        'pool_id'] is None:
                    desired_subscriptions.append(
                        module.find_resource_by_name('subscriptions',
                                                     subscription['name'],
                                                     params=scope,
                                                     thin=True))
                if subscription['pool_id'] is not None:
                    desired_subscriptions.append(
                        module.find_resource_by_id('subscriptions',
                                                   subscription['pool_id'],
                                                   params=scope,
                                                   thin=True))
            desired_subscription_ids = set(item['id']
                                           for item in desired_subscriptions)
            current_subscriptions = module.list_resource('subscriptions',
                                                         params=ak_scope)
            current_subscription_ids = set(item['id']
                                           for item in current_subscriptions)

            if desired_subscription_ids != current_subscription_ids:
                ids_to_remove = current_subscription_ids - desired_subscription_ids
                if ids_to_remove:
                    payload = {
                        'id': activation_key['id'],
                        'subscriptions': [{
                            'id': item
                        } for item in ids_to_remove],
                    }
                    payload.update(scope)
                    module.resource_action('activation_keys',
                                           'remove_subscriptions', payload)
                ids_to_add = desired_subscription_ids - current_subscription_ids
                if ids_to_add:
                    payload = {
                        'id':
                        activation_key['id'],
                        'subscriptions': [{
                            'id': item,
                            'quantity': 1
                        } for item in ids_to_add],
                    }
                    payload.update(scope)
                    module.resource_action('activation_keys',
                                           'add_subscriptions', payload)
                changed = True

        if content_overrides is not None:
            _product_content_changed, product_content = module.resource_action(
                'activation_keys',
                'product_content',
                params={'id': activation_key['id']})
            current_content_overrides = {
                product['content']['label']:
                product['enabled_content_override']
                for product in product_content['results']
                if product['enabled_content_override'] is not None
            }
            desired_content_overrides = {
                product['label']: override_to_boolnone(product['override'])
                for product in content_overrides
            }
            changed_content_overrides = []

            for label, override in desired_content_overrides.items():
                if override != current_content_overrides.pop(label, None):
                    changed_content_overrides.append({
                        'content_label': label,
                        'value': override
                    })
            for label in current_content_overrides.keys():
                changed_content_overrides.append({
                    'content_label': label,
                    'reset': True
                })

            if changed_content_overrides:
                payload = {
                    'id': activation_key['id'],
                    'content_overrides': changed_content_overrides,
                }
                module.resource_action('activation_keys', 'content_override',
                                       payload)
                changed = True

        if host_collections is not None:
            if 'host_collection_ids' in activation_key:
                current_host_collection_ids = set(
                    activation_key['host_collection_ids'])
            else:
                current_host_collection_ids = set(
                    item['id'] for item in activation_key['host_collections'])
            desired_host_collections = module.find_resources_by_name(
                'host_collections', host_collections, params=scope, thin=True)
            desired_host_collection_ids = set(
                item['id'] for item in desired_host_collections)

            if desired_host_collection_ids != current_host_collection_ids:
                ids_to_remove = current_host_collection_ids - desired_host_collection_ids
                if ids_to_remove:
                    payload = {
                        'id': activation_key['id'],
                        'host_collection_ids': list(ids_to_remove),
                    }
                    module.resource_action('activation_keys',
                                           'remove_host_collections', payload)
                ids_to_add = desired_host_collection_ids - current_host_collection_ids
                if ids_to_add:
                    payload = {
                        'id': activation_key['id'],
                        'host_collection_ids': list(ids_to_add),
                    }
                    module.resource_action('activation_keys',
                                           'add_host_collections', payload)
                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

    if module.desired_absent:
        module.ensure_entity('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]

            response = module.resource_action('content_views', 'publish', params=payload, synchronous=entity_dict['synchronous'])
            # 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 entity_dict:
            lifecycle_environments = module.find_resources_by_name('lifecycle_environments', names=entity_dict['lifecycle_environments'], params=scope)
            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()
Example #16
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,
        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(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)
Example #17
0
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(product=dict(required=True), ),
        entity_spec=dict(
            label=dict(),
            name=dict(required=True),
            content_type=dict(
                required=True,
                choices=['docker', 'ostree', 'yum', 'puppet', 'file', 'deb']),
            url=dict(),
            gpg_key=dict(type='entity', flat_name='gpg_key_id'),
            download_policy=dict(
                choices=['background', 'immediate', 'on_demand']),
            mirror_on_sync=dict(type='bool', default=True),
            upstream_username=dict(),
            upstream_password=dict(nolog=True),
            docker_upstream_name=dict(),
            docker_tags_whitelist=dict(type='list'),
            deb_releases=dict(),
            deb_components=dict(),
            deb_architectures=dict(),
            state=dict(default='present',
                       choices=['present_with_defaults', 'present', 'absent']),
        ),
    )

    entity_dict = module.clean_params()

    if entity_dict['content_type'] != 'docker':
        invalid_list = [
            key for key in ['docker_upstream_name', 'docker_tags_whitelist']
            if key in entity_dict
        ]
        if invalid_list:
            module.fail_json(
                msg="({0}) can only be used with content_type 'docker'".format(
                    ",".join(invalid_list)))

    if entity_dict['content_type'] != 'deb':
        invalid_list = [
            key
            for key in ['deb_releases', 'deb_components', 'deb_architectures']
            if key in entity_dict
        ]
        if invalid_list:
            module.fail_json(
                msg="({0}) can only be used with content_type 'deb'".format(
                    ",".join(invalid_list)))

    module.connect()

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

    if not module.desired_absent:
        if 'gpg_key' in entity_dict:
            entity_dict['gpg_key'] = module.find_resource_by_name(
                'content_credentials',
                name=entity_dict['gpg_key'],
                params=scope,
                thin=True)

    scope['product_id'] = entity_dict['product']['id']
    entity = module.find_resource_by_name('repositories',
                                          name=entity_dict['name'],
                                          params=scope,
                                          failsafe=True)

    changed = module.ensure_entity_state('repositories',
                                         entity_dict,
                                         entity,
                                         params=scope)

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            manifest_path=dict(type='path'),
            state=dict(default='present',
                       choices=['absent', 'present', 'refreshed']),
            repository_url=dict(aliases=['redhat_repository_url']),
        ),
        required_if=[
            ['state', 'present', ['manifest_path']],
        ],
    )

    module.task_timeout = 5 * 60

    entity_dict = module.clean_params()

    module.connect()

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

    try:
        existing_manifest = organization['owner_details']['upstreamConsumer']
    except KeyError:
        existing_manifest = None

    changed = False
    if module.state == 'present':
        if 'repository_url' in entity_dict:
            payload = {'redhat_repository_url': entity_dict['repository_url']}
            org_spec = dict(redhat_repository_url=dict())
            changed_url, organization = module.ensure_entity(
                'organizations',
                payload,
                organization,
                state='present',
                entity_spec=org_spec)
        else:
            changed_url = False

        try:
            with open(entity_dict['manifest_path'], 'rb') as manifest_file:
                files = {
                    'content': (entity_dict['manifest_path'], manifest_file,
                                'application/zip')
                }
                params = {}
                if 'repository_url' in entity_dict:
                    params['repository_url'] = entity_dict['repository_url']
                params.update(scope)
                changed, result = module.resource_action('subscriptions',
                                                         'upload',
                                                         params,
                                                         files=files)
                for error in result['humanized']['errors']:
                    if "same as existing data" in error:
                        changed = False
                    elif "older than existing data" in error:
                        module.fail_json(
                            msg="Manifest is older than existing data.")
                    else:
                        module.fail_json(
                            msg="Upload of the manifest failed: %s" % error)
                changed |= changed_url
        except IOError as e:
            module.fail_json(msg="Unable to read the manifest file: %s" % e)
    elif module.desired_absent and existing_manifest:
        changed, result = module.resource_action('subscriptions',
                                                 'delete_manifest', scope)
    elif module.state == 'refreshed':
        if existing_manifest:
            changed, result = module.resource_action('subscriptions',
                                                     'refresh_manifest', scope)
        else:
            module.fail_json(msg="No manifest found to refresh.")

    module.exit_json(changed=changed)
def main():
    module = KatelloEntityAnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            new_name=dict(),
            lifecycle_environment=dict(),
            content_view=dict(),
            subscriptions=dict(type='list'),
            host_collections=dict(type='list'),
            content_overrides=dict(type='list'),
            auto_attach=dict(type='bool', default=True),
            state=dict(default='present',
                       choices=[
                           'present', 'present_with_defaults', 'absent',
                           'copied'
                       ]),
        ),
        supports_check_mode=True,
        required_if=[
            ['state', 'copied', ['new_name']],
        ],
    )

    (entity_dict, state) = module.parse_params()

    module.connect()

    entity_dict['organization'] = find_organization(
        module, name=entity_dict['organization'])
    if 'lifecycle_environment' in entity_dict:
        entity_dict['lifecycle_environment'] = find_lifecycle_environment(
            module, entity_dict['lifecycle_environment'],
            entity_dict['organization'])

    if 'content_view' in entity_dict:
        entity_dict['content_view'] = find_content_view(
            module, entity_dict['content_view'], entity_dict['organization'])

    if 'host_collections' in entity_dict:
        entity_dict['host_collections'] = find_host_collections(
            module, entity_dict['host_collections'],
            entity_dict['organization'])

    activation_key_entity = find_activation_key(
        module,
        name=entity_dict['name'],
        organization=entity_dict['organization'],
        failsafe=True)

    activation_key_dict = sanitize_entity_dict(entity_dict, name_map)

    try:
        changed, activation_key_entity = naildown_entity(
            ActivationKey, activation_key_dict, activation_key_entity, state,
            module)

        # only update subscriptions of newly created or updated AKs
        # copied keys inherit the subscriptions of the origin, so one would not have to specify them again
        # deleted keys don't need subscriptions anymore either
        if state == 'present' or (state == 'present_with_defaults'
                                  and changed):
            if 'subscriptions' in entity_dict:
                subscriptions = entity_dict['subscriptions']
                desired_subscription_ids = set(
                    s.id for s in find_subscriptions(
                        module, subscriptions, entity_dict['organization']))
                current_subscriptions = [
                    Subscription(**result)
                    for result in Subscription().search_normalize(
                        activation_key_entity.subscriptions()['results'])
                ]
                current_subscription_ids = set(s.id
                                               for s in current_subscriptions)

                if desired_subscription_ids != current_subscription_ids:
                    if not module.check_mode:
                        for subscription_id in (desired_subscription_ids -
                                                current_subscription_ids):
                            activation_key_entity.add_subscriptions(
                                data={
                                    'quantity': 1,
                                    'subscription_id': subscription_id
                                })
                        for subscription_id in (current_subscription_ids -
                                                desired_subscription_ids):
                            activation_key_entity.remove_subscriptions(
                                data={'subscription_id': subscription_id})
                    changed = True

            if 'content_overrides' in entity_dict:
                content_overrides = entity_dict['content_overrides']
                product_content = activation_key_entity.product_content()
                current_content_overrides = set(
                    (product['content']['label'],
                     product['enabled_content_override'])
                    for product in product_content['results']
                    if product['enabled_content_override'] is not None)
                desired_content_overrides = set(
                    (product['label'],
                     override_to_boolnone(product['override']))
                    for product in content_overrides)

                if desired_content_overrides != current_content_overrides:
                    if not module.check_mode:
                        for (
                                label, override
                        ) in current_content_overrides - desired_content_overrides:
                            activation_key_entity.content_override(
                                data={
                                    'content_override': {
                                        'content_label': label,
                                        'value': 'default'
                                    }
                                })
                        for (
                                label, override
                        ) in desired_content_overrides - current_content_overrides:
                            activation_key_entity.content_override(
                                data={
                                    'content_override': {
                                        'content_label': label,
                                        'value': str(override).lower()
                                    }
                                })
                    changed = True

        module.exit_json(changed=changed)
    except Exception as e:
        module.fail_json(msg=e)
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['organization'] = module.find_resource_by_name(
        'organizations', entity_dict['organization'], thin=True)
    scope = {'organization_id': entity_dict['organization']['id']}
    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)

    changed, 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 changed))
    if update_dependent_entities and content_view_entity[
            'composite'] and components is not None:
        if not changed:
            content_view_entity['content_view_components'] = entity[
                'content_view_components']
        current_cvcs = content_view_entity.get('content_view_components', [])

        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={},version={}".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:
                changed |= module.ensure_entity_state(
                    '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)
            changed = True

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

    module.exit_json(changed=changed)
Example #21
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()