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)
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()
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()
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'], )