def find_subscription(module, name, organization, failsafe=False): subscription = Subscription(organization=organization) return handle_find_response( module, subscription.search(query={'search': 'name="{}"'.format(name)}), message="No subscription found for %s" % name, failsafe=failsafe)
def manifest(module, organization, state, manifest_path=None, redhat_repository_url="https://cdn.redhat.com"): changed = False organization = find_organization(module, organization).read() current_manifest = current_subscription_manifest(module, organization) manifest_present = current_manifest is not None if organization.redhat_repository_url != redhat_repository_url: if not module.check_mode: organization.redhat_repository_url = redhat_repository_url organization.update({'redhat_repository_url'}) changed = True if state == 'present': try: with open(manifest_path, 'rb') as manifest_file: files = { 'content': (manifest_path, manifest_file, 'application/zip') } data = { 'organization_id': organization.id, 'repository_url': redhat_repository_url } headers = { 'content_type': 'multipart/form-data', 'multipart': 'true' } if not module.check_mode: Subscription().upload(data=data, files=files, headers=headers) changed = True except IOError as e: module.fail_json(msg="Unable to open the manifest file: %s" % e) except TaskFailedError as e: if "same as existing data" in e.message: pass elif "older than existing data" in e.message: module.fail_json( msg="Manifest is older than existing data: %s" % e) else: module.fail_json(msg="Upload of the mainfest failed: %s" % e) elif state == 'absent' and manifest_present: if not module.check_mode: Subscription().delete_manifest( data={'organization_id': organization.id}) changed = True elif state == 'refreshed': if not manifest_present: module.fail_json(msg="No manifest found to refresh.") else: if not module.check_mode: Subscription().refresh_manifest( data={'organization_id': organization.id}) changed = True return 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 setUpClass(cls): """Creates all the pre-requisites for the Incremental updates test""" super(IncrementalUpdateTestCase, cls).setUpClass() # Step 1 - Create a new Organization cls.org = Organization(name=gen_alpha()).create() # Step 2 - Create two life cycle environments - DEV, QE cls.dev_lce = LifecycleEnvironment(name='DEV', organization=cls.org).create() cls.qe_lce = LifecycleEnvironment(name='QE', prior=cls.dev_lce, organization=cls.org).create() # Step 3: Upload manifest with manifests.clone() as manifest: upload_manifest(cls.org.id, manifest.content) # Step 4: Enable repositories - 6Server and rhel6 sat6tools rhel_66_repo_id = enable_rhrepo_and_fetchid( basearch=PRD_SETS['rhel_66']['arch'], org_id=cls.org.id, product=PRD_SETS['rhel_66']['product'], repo=PRD_SETS['rhel_66']['reponame'], reposet=PRD_SETS['rhel_66']['reposet'], releasever=PRD_SETS['rhel_66']['releasever']) rhel6_sat6tools_repo_id = enable_rhrepo_and_fetchid( basearch=PRD_SETS['rhel6_sat6tools']['arch'], org_id=cls.org.id, product=PRD_SETS['rhel6_sat6tools']['product'], repo=PRD_SETS['rhel6_sat6tools']['reponame'], reposet=PRD_SETS['rhel6_sat6tools']['reposet'], releasever=PRD_SETS['rhel6_sat6tools']['releasever']) # Step 5: Read the repositories cls.rhel_66_repo = Repository(id=rhel_66_repo_id).read() cls.rhel6_sat6tools_repo = Repository( id=rhel6_sat6tools_repo_id).read() # Step 6: Sync the enabled repositories try: cls.old_task_timeout = entity_mixins.TASK_TIMEOUT # Update timeout to 2 hours to finish sync entity_mixins.TASK_TIMEOUT = 7200 for repo in [cls.rhel_66_repo, cls.rhel6_sat6tools_repo]: assert Repository(id=repo.id).sync()['result'] == u'success' finally: entity_mixins.TASK_TIMEOUT = cls.old_task_timeout # Step 7: Create two content views - one will be used with all erratas # and another with erratas filtered for cv_name in ('rhel_6_cv', 'rhel_6_partial_cv'): setattr( cls, cv_name, ContentView( organization=cls.org, name=cv_name, repository=[cls.rhel_66_repo, cls.rhel6_sat6tools_repo]).create()) # Step 8: Create a content view filter to filter out errata rhel_6_partial_cvf = ErratumContentViewFilter( content_view=cls.rhel_6_partial_cv, type='erratum', name='rhel_6_partial_cv_filter', repository=[cls.rhel_66_repo]).create() # Step 9: Create a content view filter rule - filtering out errata in # the last 365 days start_date = (date.today() - timedelta(days=365)).strftime('%Y-%m-%d') ContentViewFilterRule( content_view_filter=rhel_6_partial_cvf, types=['security', 'enhancement', 'bugfix'], start_date=start_date, end_date=date.today().strftime('%Y-%m-%d')).create() # Step 10: Publish both the content views and re-read the content views # Changing the nailgun timeout time for the rest of the steps as # publish/promote of larger repos take more than 5 minutes entity_mixins.TASK_TIMEOUT = 3600 for content_view in (cls.rhel_6_cv, cls.rhel_6_partial_cv): content_view.publish() cls.rhel_6_cv = cls.rhel_6_cv.read() cls.rhel_6_partial_cv = cls.rhel_6_partial_cv.read() # Step 11: Promote both content views to 'DEV' and 'QE' for content_view in (cls.rhel_6_cv, cls.rhel_6_partial_cv): assert len(content_view.version) == 1 for env in (cls.dev_lce, cls.qe_lce): promote(content_view.version[0], env.id) # Step 12: Create host collections for hc_name in ('rhel_6_hc', 'rhel_6_partial_hc'): setattr( cls, hc_name, HostCollection(organization=cls.org, name=hc_name, max_content_hosts=5).create()) # Step 13: Create activation keys for both content views kwargs = {'organization': cls.org, 'environment': cls.qe_lce.id} rhel_6_ak = ActivationKey(name=u'rhel_6_ak', content_view=cls.rhel_6_cv, host_collection=[cls.rhel_6_hc], **kwargs).create() rhel_6_partial_ak = ActivationKey( name=u'rhel_6_partial_ak', content_view=cls.rhel_6_partial_cv, host_collection=[cls.rhel_6_partial_hc], **kwargs).create() # Step 14: Assign subscriptions to activation keys # Fetch available subscriptions subs = Subscription(organization=cls.org).search() assert len(subs) > 0 # Add subscriptions to activation key sub_found = False for sub in subs: if sub.read_json()['product_name'] == u'Employee SKU': for act_key in [rhel_6_ak, rhel_6_partial_ak]: act_key.add_subscriptions( data={u'subscription_id': sub.id}) sub_found = True assert sub_found # Step 15: Enable product content in activation keys for act_key in [rhel_6_ak, rhel_6_partial_ak]: act_key.content_override( data={ 'content_override': { u'content_label': PRD_SETS['rhel6_sat6tools']['label'], u'value': u'1' } }) # Step 16: Create three client machines and register them to satellite # Register the first vm with rhel_6_ak and the other two vms with # rhel_6_partial_ak cls.vm = [ VirtualMachine(distro='rhel67', tag='incupdate') for _ in range(3) ] cls.setup_vm(cls.vm[0], rhel_6_ak.name, cls.org.label) for i in range(1, 3): cls.setup_vm(cls.vm[i], rhel_6_partial_ak.name, cls.org.label) # Find the content hosts (systems) and save them systems = System(organization=cls.org).search() cls.systems = [] cls.partial_systems = [] for system in systems: if system.content_view.read().name == cls.rhel_6_cv.name: cls.systems.append(system) else: cls.partial_systems.append(system)
def setUp(self): """Creates the pre-requisites for the Incremental updates that used per each test""" super(IncrementalUpdateTestCase, self).setUp() # Create content view that will be used filtered erratas self.rhel_6_partial_cv = ContentView( organization=self.org, name=gen_alpha(), repository=[self.rhva_6_repo, self.rhel6_sat6tools_repo] ).create() # Create a content view filter to filter out errata rhel_6_partial_cvf = ErratumContentViewFilter( content_view=self.rhel_6_partial_cv, type='erratum', name='rhel_6_partial_cv_filter', repository=[self.rhva_6_repo] ).create() # Create a content view filter rule - filtering out errata in the last # 365 days start_date = (date.today() - timedelta(days=365)).strftime('%Y-%m-%d') ContentViewFilterRule( content_view_filter=rhel_6_partial_cvf, types=['security', 'enhancement', 'bugfix'], start_date=start_date, end_date=date.today().strftime('%Y-%m-%d') ).create() # Publish content view and re-read it self.rhel_6_partial_cv.publish() self.rhel_6_partial_cv = self.rhel_6_partial_cv.read() # Promote content view to 'DEV' and 'QE' assert len(self.rhel_6_partial_cv.version) == 1 for env in (self.dev_lce, self.qe_lce): promote(self.rhel_6_partial_cv.version[0], env.id) # Create host collection self.rhel_6_partial_hc = HostCollection( organization=self.org, name=gen_alpha(), max_hosts=5).create() # Create activation key for content view kwargs = {'organization': self.org, 'environment': self.qe_lce.id} rhel_6_partial_ak = ActivationKey( name=gen_alpha(), content_view=self.rhel_6_partial_cv, host_collection=[self.rhel_6_partial_hc], **kwargs ).create() # Assign subscription to activation key. Fetch available subscriptions subs = Subscription(organization=self.org).search() assert len(subs) > 0 # Add subscription to activation key sub_found = False for sub in subs: if sub.read_json()['product_name'] == DEFAULT_SUBSCRIPTION_NAME: rhel_6_partial_ak.add_subscriptions(data={ u'subscription_id': sub.id }) sub_found = True assert sub_found # Enable product content in activation key rhel_6_partial_ak.content_override(data={'content_override': { u'content_label': REPOS['rhst6']['id'], u'value': u'1' }}) # Create client machine and register it to satellite with # rhel_6_partial_ak self.vm = VirtualMachine(distro=DISTRO_RHEL6, tag='incupdate') self.addCleanup(vm_cleanup, self.vm) self.setup_vm(self.vm, rhel_6_partial_ak.name, self.org.label) self.vm.enable_repo(REPOS['rhva6']['id']) self.vm.run('yum install -y {0}'.format(REAL_0_RH_PACKAGE)) # Find the content hosts and save them hosts = Host(organization=str(self.org.id)).search() self.partial_hosts = [] for host in hosts: self.partial_hosts.append(host)
def main(): module = AnsibleModule( argument_spec=dict( server_url=dict(required=True), username=dict(required=True, no_log=True), password=dict(required=True, no_log=True), verify_ssl=dict(type='bool', default=True), name=dict(required=True), new_name=dict(), organization=dict(required=True), lifecycle_environment=dict(), content_view=dict(), subscriptions=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']], ], ) if has_import_error: module.fail_json(msg=import_error_msg) entity_dict = dict([(k, v) for (k, v) in module.params.items() if v is not None]) server_url = entity_dict.pop('server_url') username = entity_dict.pop('username') password = entity_dict.pop('password') verify_ssl = entity_dict.pop('verify_ssl') state = entity_dict.pop('state') try: create_server(server_url, (username, password), verify_ssl) except Exception as e: module.fail_json(msg="Failed to connect to Foreman server: %s " % e) ping_server(module) 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']) activation_key_dict = sanitize_entity_dict(entity_dict, name_map) activation_key_entity = find_activation_key( module, name=entity_dict['name'], organization=entity_dict['organization'], failsafe=True) 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 = map( lambda s: s.id, 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 = map(lambda s: s.id, current_subscriptions) if set(desired_subscription_ids) != set( current_subscription_ids): if not module.check_mode: for subscription_id in set( desired_subscription_ids) - set( current_subscription_ids): activation_key_entity.add_subscriptions( data={ 'quantity': 1, 'subscription_id': subscription_id }) for subscription_id in set( current_subscription_ids) - set( 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() for product in product_content['results']: if product['enabled_content_override'] is not None: current_content_overrides.add( (product['content']['label'], product['enabled_content_override'])) desired_content_overrides = set() for product in content_overrides: desired_content_overrides.add( (product['label'], override_to_boolnone(product['override']))) 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_to_boolnone( override)).lower() } }) changed = True module.exit_json(changed=changed) except Exception as e: module.fail_json(msg=e)