def test_positive_rename_content_host(self): """Hosts renamed in katello via content-hosts appear in foreman :id: 34a2c507-b992-46fa-81d9-e4b31ffd9706 :steps: 1. Rename a host from 'Content-hosts' page 2. View host under content-hosts 3. View host under 'All Hosts' :expectedresults: Host appears in both places despite being renamed :BZ: 1495271 :CaseLevel: System """ with VirtualMachine(distro=DISTRO_RHEL7) as vm: vm.install_katello_ca() vm.register_contenthost(self.org_.label, lce='Library') self.assertTrue(vm.subscribed) with Session(self) as session: session.nav.go_to_select_org(self.org_.name) new_name = gen_string('alphanumeric').lower() self.contenthost.update( vm.hostname, new_name=new_name, ) self.assertIsNone(self.contenthost.search(vm.hostname)) if bz_bug_is_open(1495271): session.dashboard.navigate_to_entity() self.assertIsNotNone(self.contenthost.search(new_name)) self.assertIsNone(self.hosts.search(vm.hostname)) if bz_bug_is_open(1495271): session.dashboard.navigate_to_entity() self.assertIsNotNone(self.hosts.search(new_name))
def test_unauthenticated_bz_call(self, dec_settings, RHBugzilla): """Assert flags are not taken into account if bz credentials section is not present on robottelo.properties """ dec_settings.upstream = False # Missing password bz_credentials = {'user': '******', 'password': None} dec_settings.bugzilla.get_credentials.return_value = bz_credentials class MockBug(object): # pylint:disable=R0903 """A mock bug if empty flags""" status = 'VERIFIED' whiteboard = None flags = [] bz_conn_mock = mock.Mock() RHBugzilla.return_value = bz_conn_mock bz_conn_mock.getbug.return_value = MockBug self.assertFalse(decorators.bz_bug_is_open(self.bug_id)) RHBugzilla.assert_called_once_with(url=BUGZILLA_URL) bz_conn_mock.getbug.assert_called_once_with( self.bug_id, include_fields=['id', 'status', 'whiteboard', 'flags'] ) MockBug.status = 'NEW' # Missing user bz_credentials.update({'user': None, 'password': '******'}) # avoiding cache adding 1 to id self.assertTrue(decorators.bz_bug_is_open(self.bug_id + 1))
def test_positive_delete_and_get_requests(self): """Issue an HTTP DELETE request and GET the deleted entity. @id: 04a37ba7-c553-40e1-bc4c-ec2ebf567647 @Assert: An HTTP 404 is returned when fetching the missing entity. """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_delete_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) if (entity_cls is entities.ConfigTemplate and bz_bug_is_open(1096333)): self.skipTest('BZ 1096333: Cannot delete config templates') if (entity_cls in BZ_1187366_ENTITIES and bz_bug_is_open(1187366)): self.skipTest('BZ 1187366: Cannot delete orgs or envs.') # Create an entity, delete it and get it. try: entity = entity_cls(id=entity_cls().create_json()['id']) except HTTPError as err: self.fail(err) entity.delete() self.assertEqual( http_client.NOT_FOUND, entity.read_raw().status_code )
def test_positive_sort_by_last_checkin(self): """Register two content hosts and then sort them by last checkin date :id: c42c1347-8b3a-4ba7-95d1-609e2e9ec40e :expectedresults: Validate that content hosts are sorted properly :BZ: 1281251 :CaseLevel: System """ with VirtualMachine(distro=DISTRO_RHEL7) as vm: vm.install_katello_ca() vm.register_contenthost( self.session_org.label, self.activation_key.name) self.assertTrue(vm.subscribed) vm.enable_repo(REPOS['rhst7']['id']) vm.install_katello_agent() with Session(self): self.assertIsNotNone( self.contenthost.search(self.client.hostname)) if bz_bug_is_open(1495271): self.dashboard.navigate_to_entity() self.assertIsNotNone(self.contenthost.search(vm.hostname)) self.contenthost.click(common_locators['kt_clear_search']) if bz_bug_is_open(1495271): self.dashboard.navigate_to_entity() self.contenthost.navigate_to_entity() # prevent any issues in case some default sorting was set self.contenthost.sort_table_by_column('Name') dates = self.contenthost.sort_table_by_column('Last Checkin') self.assertGreater(dates[1], dates[0]) dates = self.contenthost.sort_table_by_column('Last Checkin') self.assertGreater(dates[0], dates[1])
def test_downstream_valid_whiteboard(self, dec_settings): """Assert ``True`` is returned if - bug is in any status - bug has a valid Whiteboard text - robottelo in downstream mode """ original_bug = { 'id': 1, 'status': 'CLOSED', 'whiteboard': '', 'target_milestone': 'Unspecified', 'flags': {'sat-6.2.z': '', 'sat-6.3.0': '+'} } dec_settings.upstream = False robozilla_decorators._get_bugzilla_bug = ( lambda bug_id, **_: original_bug ) all_statuses = chain(BZ_OPEN_STATUSES, BZ_CLOSED_STATUSES) for original_bug['status'], original_bug['whiteboard'] in \ product(all_statuses, self.valid_whiteboard_data): if original_bug['status'] == 'CLOSED': self.assertFalse(decorators.bz_bug_is_open( self.bug_id, sat_version_picker=None)) else: self.assertTrue(decorators.bz_bug_is_open( self.bug_id, sat_version_picker=None))
def test_upstream_with_whiteboard(self, dec_settings): """Assert that upstream bug is not affected by whiteboard texts""" original_bug = { 'id': 1, 'status': 'NEW', 'whiteboard': '', } dec_settings.upstream = True robozilla_decorators._get_bugzilla_bug = ( lambda bug_id, **_: original_bug ) # Assert bug is really closed with valid/invalid whiteboard texts white_board_data = ( self.valid_whiteboard_data + self.invalid_whiteboard_data) for original_bug['status'], original_bug['whiteboard'] in \ product(BZ_CLOSED_STATUSES, white_board_data): self.assertFalse(decorators.bz_bug_is_open( self.bug_id, sat_version_picker=None)) # Assert bug is really open with valid/invalid whiteboard texts for original_bug['status'], original_bug['whiteboard'] in \ product(BZ_OPEN_STATUSES, white_board_data): self.assertTrue(decorators.bz_bug_is_open( self.bug_id, sat_version_picker=None))
def _traverse_command_tree(self, command): """Recursively walk through the hammer commands tree and assert that the expected options are present. """ output = hammer.parse_help( ssh.command('{0} --help'.format(command)).stdout ) command_options = set([option['name'] for option in output['options']]) command_subcommands = set( [subcommand['name'] for subcommand in output['subcommands']] ) if 'discovery_rule' in command and bz_bug_is_open(1219610): # Adjust the discovery_rule subcommand name. The expected data is # already with the naming convetion name expected = _fetch_command_info( command.replace('discovery_rule', 'discovery-rule')) else: expected = _fetch_command_info(command) expected_options = set() expected_subcommands = set() if expected is not None: expected_options = set( [option['name'] for option in expected['options']] ) expected_subcommands = set( [subcommand['name'] for subcommand in expected['subcommands']] ) if command == 'hammer' and bz_bug_is_open(1219610): # Adjust the discovery_rule subcommand name command_subcommands.discard('discovery_rule') command_subcommands.add('discovery-rule') added_options = tuple(command_options - expected_options) removed_options = tuple(expected_options - command_options) added_subcommands = tuple(command_subcommands - expected_subcommands) removed_subcommands = tuple(expected_subcommands - command_subcommands) if (added_options or added_subcommands or removed_options or removed_subcommands): diff = { 'added_command': expected is None, } if added_options: diff['added_options'] = added_options if removed_options: diff['removed_options'] = removed_options if added_subcommands: diff['added_subcommands'] = added_subcommands if removed_subcommands: diff['removed_subcommands'] = removed_subcommands self.differences[command] = diff if len(output['subcommands']) > 0: for subcommand in output['subcommands']: self._traverse_command_tree( '{0} {1}'.format(command, subcommand['name']) )
def test_bug_is_open(self): """Assert ``True`` is returned if the bug is 'NEW' or 'ASSIGNED'.""" class MockBug(object): # pylint:disable=R0903 """A mock bug with an open status.""" status = 'NEW' whiteboard = None decorators._get_bugzilla_bug = lambda bug_id: MockBug() self.assertTrue(decorators.bz_bug_is_open(self.bug_id)) MockBug.status = 'ASSIGNED' self.assertTrue(decorators.bz_bug_is_open(self.bug_id))
def test_bug_is_closed(self): """Assert ``False`` is returned if the bug is not open.""" class MockBug(object): # pylint:disable=R0903 """A mock bug with a closed status.""" status = 'CLOSED' whiteboard = None decorators._get_bugzilla_bug = lambda bug_id: MockBug() self.assertFalse(decorators.bz_bug_is_open(self.bug_id)) MockBug.status = 'ON_QA' self.assertFalse(decorators.bz_bug_is_open(self.bug_id)) MockBug.status = 'SLOWLY DRIVING A DEV INSANE' self.assertFalse(decorators.bz_bug_is_open(self.bug_id))
def setUpClass(cls): """Create Org, Lifecycle Environment, Content View, Activation key """ super(RemoteExecutionTestCase, cls).setUpClass() cls.org = entities.Organization().create() ssh.command( '''echo 'getenforce' > {0}'''.format(TEMPLATE_FILE) ) # create subnet for current org, default loc and domain # using API due BZ#1370460 cls.sn = entities.Subnet( domain=[1], gateway=settings.vlan_networking.gateway, ipam='DHCP', location=[DEFAULT_LOC_ID], mask=settings.vlan_networking.netmask, network=settings.vlan_networking.subnet, organization=[cls.org.id] ).create() # add rex proxy to subnet, default is internal proxy (id 1) if bz_bug_is_open(1328322): cls.sn.remote_execution_proxy_ids = [1] cls.sn.update(["remote_execution_proxy_ids"]) else: cls.sn.remote_execution_proxy_id = 1 cls.sn.update(["remote_execution_proxy_id"])
def test_positive_search_by_hypervisor(self): """Able to find hypervisor or not hypervisor content host by searching hypervisor = true or hypervisor = false :id: 2165023f-7184-400c-a9d9-e0c0d065a7d2 :expectedresults: the hypervisor search work properly :BZ: 1246554, 1495271 :CaseLevel: System """ with Session(self) as session: set_context(session, org=self.session_org.name) is_hypervisor_hosts = { True: self.virt_who_hypervisor_host.name, False: self.virt_who_vm.hostname } for is_hypervisor in is_hypervisor_hosts: if bz_bug_is_open(1495271): session.dashboard.navigate_to_entity() self.assertIsNotNone( session.contenthost.search( is_hypervisor_hosts[is_hypervisor], _raw_query='hypervisor = {0}'.format( str(is_hypervisor).lower()) ) ) self.assertIsNone( session.subscriptions.wait_until_element( locators['contenthost.select_name'] % is_hypervisor_hosts[not is_hypervisor] ) )
def test_positive_run_recurring_job_with_max_iterations(self): """Run default job template multiple times with max iteration :id: 37fb7d77-dbb1-45ae-8bd7-c70be7f6d949 :expectedresults: Verify the job was run not more than the specified number of times. """ invocation_command = make_job_invocation({ 'job-template': 'Run Command - SSH Default', 'inputs': 'command="ls"', 'search-query': "name ~ {0}".format(self.client.hostname), 'cron-line': '* * * * *', # every minute 'max-iteration': 2, # just two runs }) if not bz_bug_is_open(1431190): JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname }) try: self.assertEqual(invocation_command['status'], u'queued') except AssertionError: result = 'host output: {0}'.format( ' '.join(JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname}) ) ) raise AssertionError(result) sleep(150) rec_logic = RecurringLogic.info({ 'id': invocation_command['recurring-logic-id']}) self.assertEqual(rec_logic['state'], u'finished') self.assertEqual(rec_logic['iteration'], u'2')
def test_positive_update_scap_content_with_newtitle(self): """Update scap content title :id: 2c32e94a-237d-40b9-8a3b-fca2ef26fe79 :setup: 1. Oscap should be enabled. 2. Oscap-cli hammer plugin installed. :steps: 1. Login to hammer shell. 2. Execute "scap-content" command with "update" as sub-command. 3. Pass valid parameters and newtitle parameter. :expectedresults: The scap-content is updated successfully. :CaseImportance: Critical """ title = gen_string('alpha') new_title = gen_string('alpha') scap_content = make_scapcontent({ 'title': title, 'scap-file': '/tmp/{0}'.format(self.file_name)}) self.assertEqual(scap_content['title'], title) result = Scapcontent.update({ 'title': title, 'new-title': new_title}) if bz_bug_is_open(1496810): result = Scapcontent.info({'title': new_title}) self.assertEqual(result['title'], new_title)
def test_positive_update(self): """Update partition table with its name, layout and OS family @Feature: Partition table - Positive Update @Assert: Partition table is updated """ name = gen_string('alphanumeric') with Session(self.browser) as session: make_partitiontable( session, name=name, template_path=PARTITION_SCRIPT_DATA_FILE, os_family='Debian', ) self.assertIsNotNone(self.partitiontable.search(name)) for test_data in valid_partition_table_update_names(): with self.subTest(test_data): bug_id = test_data.pop('bugzilla', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest( 'Bugzilla bug {0} is open for html ' 'data.'.format(bug_id) ) self.partitiontable.update( old_name=name, new_name=test_data['new_name'], new_template_path=PARTITION_SCRIPT_DATA_FILE, new_os_family='Red Hat', ) self.assertIsNotNone(self.partitiontable.search( test_data['new_name'])) name = test_data['new_name'] # for next iteration
def test_positive_rename_content_host_cli(self): """Content Hosts renamed in UI affects entity in the application entirely, so name looks different through CLI too :id: a64c7815-269b-45d0-9032-38df550d6cd9 :steps: 1. Rename a host from 'Content-hosts' page 2. View host under content-hosts 3. View host using command line interface :expectedresults: Host changed its name both in UI and CLI :BZ: 1417953, 1495271 :CaseLevel: System """ new_name = gen_string('alphanumeric').lower() with VirtualMachine(distro=DISTRO_RHEL7) as vm: vm.install_katello_ca() vm.register_contenthost(self.org_.label, lce='Library') self.assertTrue(vm.subscribed) host = Host.info({'name': vm.hostname}) with Session(self) as session: session.nav.go_to_select_org(self.org_.name) self.contenthost.update( vm.hostname, new_name=new_name, ) if bz_bug_is_open(1495271): session.dashboard.navigate_to_entity() self.assertIsNotNone(self.contenthost.search(new_name)) self.assertEqual(Host.info({'id': host['id']})['name'], new_name)
def test_positive_put_status_code(self): """Issue a PUT request and check the returned status code. @id: 1a2186b1-0709-4a73-8199-71114e10afce @Assert: HTTP 200 is returned with an ``application/json`` content-type """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) if bz_bug_is_open(1378009): exclude_list += (entities.HostGroup,) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), # FIXME: use entity.update_payload() entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) self.assertEqual(http_client.OK, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def test_post_and_get(self): """@Test: Create an entity, then read it back. @Feature: Test multiple API paths @Assert: The entity is created with the given attributes. """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_post_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) if (entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156)): self.skipTest('Bugzilla bug 1154156 is open.') entity = entity_cls() entity_id = entity.create_json()['id'] # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def generate_strings_list(length=None, exclude_types=None, bug_id=None, min_length=3, max_length=30): """Generates a list of different input strings. :param int length: Specifies the length of the strings to be be generated. If the len1 is None then the list is returned with string types of random length. :param exclude_types: Specify a list of data types to be removed from generated list. example: exclude_types=['html', 'cjk'] :param int bug_id: Specify any bug id that is associated to the datapoint specified in remove_str. This will be used only when remove_str is populated. :param int min_length: Minimum length to be used in integer generator :param int max_length: Maximum length to be used in integer generator :returns: A list of various string types. """ if length is None: length = gen_integer(min_length, max_length) strings = { str_type: gen_string(str_type, length) for str_type in STRING_TYPES } # Handle No bug_id, If some entity doesn't support a str_type. # Remove str_type from dictionary only if bug is open. if exclude_types and (bug_id is None or bz_bug_is_open(bug_id)): for item in exclude_types: strings.pop(item, None) return list(strings.values())
def generate_strings_list(length=None, remove_str=None, bug_id=None): """Generates a list of different input strings. :param int length: Specifies the length of the strings to be be generated. If the len1 is None then the list is returned with string types of random length. :param str remove_str: Specify any specific data point that needs to be removed. Example: remove_str='numeric'. :param int bug_id: Specify any bug id that is associated to the datapoint specified in remove_str. This will be used only when remove_str is populated. :returns: A list of various string types. """ if length is None: length = gen_integer(3, 30) strings = { str_type: gen_string(str_type, length) for str_type in (u'alpha', u'numeric', u'alphanumeric', u'latin1', u'utf8', u'cjk', u'html') } # Handle No bug_id, If some entity doesn't support a str_type. # Remove str_type from dictionary only if bug is open. if remove_str and (bug_id is None or bz_bug_is_open(bug_id)): del strings[remove_str] return list(strings.values())
def test_bug_lookup_fails(self): """Assert ``False`` is returned if the bug cannot be found.""" def bomb(_): """A function that mocks a failure to fetch a bug.""" raise decorators.BugFetchError decorators._get_bugzilla_bug = bomb self.assertFalse(decorators.bz_bug_is_open(self.bug_id))
def test_positive_post_status_code(self): """Issue a POST request and check the returned status code. :id: 40247cdd-ad72-4b7b-97c6-583addb1b25a :expectedresults: HTTP 201 is returned with an ``application/json`` content-type :CaseImportance: Critical """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_post_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Libvirt compute resources suffer from BZ 1118015. However, # partials cannot be compared for class identity and the class # hierarchy needs fixing (SatelliteQE/nailgun#42), so we just # comment it out above. if (entity_cls in BZ_1118015_ENTITIES and bz_bug_is_open(1118015)): self.skipTest('Bugzilla bug 1118015 is open.') response = entity_cls().create_raw() self.assertEqual(http_client.CREATED, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def test_post_status_code(self): """@Test: Issue a POST request and check the returned status code. @Feature: Test multiple API paths @Assert: HTTP 201 is returned with an ``application/json`` content-type """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_post_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Libvirt compute resources suffer from BZ 1118015. However, # partials cannot be compared for class identity and the class # hierarchy needs fixing (SatelliteQE/nailgun#42), so we just # comment it out above. if (entity_cls in BZ_1118015_ENTITIES and bz_bug_is_open(1118015)): self.skipTest('Bugzilla bug 1118015 is open.') response = entity_cls().create_raw() self.assertEqual(httplib.CREATED, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def delete(self, name=DEFAULT_SUBSCRIPTION_NAME, really=True): """Deletes Manifest/subscriptions via UI.""" self.navigate_to_entity() if not self.wait_until_element(locators.subs.upload, timeout=1): self.click(locators.subs.manage_manifest) self.click(locators['subs.delete_manifest']) if really: self.click(common_locators['confirm_remove']) timeout = 300 if bz_bug_is_open(1339696): timeout = 1500 self.wait_until_element(common_locators['alert.success'], timeout) else: self.click(common_locators['close']) # if no subscriptions are present, user is automatically redirected to # manifest upload page, meaning search will fail with # UINoSuchElementError as searchbox can't be found there searched = None try: searched = self.search(name) except UINoSuchElementError: pass if bool(searched) == really: raise UIError( 'An error occurred while attempting to delete {}'.format(name))
def test_positive_end_to_end(session, module_org, module_loc, module_libvirt_url): """Perform end to end testing for compute resource Libvirt component. :id: 4f4650c8-32f3-4dab-b3bf-9c54d0cda3b2 :expectedresults: All expected CRUD actions finished successfully. :CaseLevel: Integration :CaseImportance: High """ cr_name = gen_string('alpha') cr_description = gen_string('alpha') new_cr_name = gen_string('alpha') new_cr_description = gen_string('alpha') new_org = entities.Organization().create() new_loc = entities.Location().create() display_type = choice(('VNC', 'SPICE')) if bz_bug_is_open(1662164): display_type = 'VNC' console_passwords = choice((True, False)) with session: session.computeresource.create({ 'name': cr_name, 'description': cr_description, 'provider': FOREMAN_PROVIDERS['libvirt'], 'provider_content.url': module_libvirt_url, 'provider_content.display_type': display_type, 'provider_content.console_passwords': console_passwords, 'organizations.resources.assigned': [module_org.name], 'locations.resources.assigned': [module_loc.name], }) cr_values = session.computeresource.read(cr_name) assert cr_values['name'] == cr_name assert cr_values['description'] == cr_description assert cr_values['provider_content']['url'] == module_libvirt_url assert cr_values['provider_content']['display_type'] == display_type assert cr_values['provider_content']['console_passwords'] == console_passwords assert cr_values['organizations']['resources']['assigned'] == [module_org.name] assert cr_values['locations']['resources']['assigned'] == [module_loc.name] session.computeresource.edit(cr_name, { 'name': new_cr_name, 'description': new_cr_description, 'organizations.resources.assigned': [new_org.name], 'locations.resources.assigned': [new_loc.name], }) assert not session.computeresource.search(cr_name) cr_values = session.computeresource.read(new_cr_name) assert cr_values['name'] == new_cr_name assert cr_values['description'] == new_cr_description assert (set(cr_values['organizations']['resources']['assigned']) == {module_org.name, new_org.name}) assert (set(cr_values['locations']['resources']['assigned']) == {module_loc.name, new_loc.name}) # check that the compute resource is listed in one of the default compute profiles profile_cr_values = session.computeprofile.list_resources(COMPUTE_PROFILE_SMALL) profile_cr_names = [cr['Compute Resource'] for cr in profile_cr_values] assert '{0} ({1})'.format(new_cr_name, FOREMAN_PROVIDERS['libvirt']) in profile_cr_names session.computeresource.delete(new_cr_name) assert not session.computeresource.search(new_cr_name)
def enable_rhrepo_and_fetchid(basearch, org_id, product, repo, reposet, releasever): """Enable a RedHat Repository and fetches it's Id. :param str org_id: The organization Id. :param str product: The product name in which repository exists. :param str reposet: The reposet name in which repository exists. :param str repo: The repository name who's Id is to be fetched. :param str basearch: The architecture of the repository. :param str optional releasever: The releasever of the repository. :return: Returns the repository Id. :rtype: str """ product = entities.Product(name=product, organization=org_id).search()[0] r_set = entities.RepositorySet(name=reposet, product=product).search()[0] payload = {} if basearch is not None: payload['basearch'] = basearch if releasever is not None: payload['releasever'] = releasever r_set.enable(data=payload) result = entities.Repository(name=repo).search( query={'organization_id': org_id}) if bz_bug_is_open(1252101): for _ in range(5): if len(result) > 0: break time.sleep(5) result = entities.Repository(name=repo).search( query={'organization_id': org_id}) return result[0].id
def upload(self, manifest, repo_url=None): """Uploads Manifest/subscriptions via UI. :param Manifest manifest: The manifest to upload. :param str repo_url: The RedHat URL to sync content from. """ self.navigate_to_entity() if not self.wait_until_element(locators.subs.upload, timeout=1): self.click(locators.base.locators.subs.manage_manifest) if repo_url: self.click(locators['subs.repo_url_edit']) self.assign_value(locators['subs.repo_url_update'], repo_url) self.click(common_locators['save']) browse_element = self.wait_until_element(locators['subs.file_path']) # File fields requires a file path in order to upload it. Create an # actual file on filesystem and fill the path on the file field. with open(manifest.filename, 'wb') as handler: handler.write(manifest.content.read()) browse_element.send_keys(manifest.filename) self.click(locators['subs.upload']) timeout = 300 if bz_bug_is_open(1339696): timeout = 1500 self.wait_until_element(locators['subs.manifest_exists'], timeout) os.remove(manifest.filename)
def test_positive_ping(self): """Check if all services are running @Feature: End to End Test @Assert: Overall and individual services status should be 'ok'. """ response = entities.Ping().search_json() self.assertEqual(response['status'], u'ok') # overall status # Check that all services are OK. ['services'] is in this format: # # {u'services': { # u'candlepin': {u'duration_ms': u'40', u'status': u'ok'}, # u'candlepin_auth': {u'duration_ms': u'41', u'status': u'ok'}, # … # }, u'status': u'ok'} services = response['services'] if bz_bug_is_open('1325995'): services.pop('foreman_auth') self.assertTrue( all([service['status'] == u'ok' for service in services.values()]), u'Not all services seem to be up and running!' )
def test_positive_update_rh_product(session): """Update Content View in an Activation key :id: 9b0ac209-45de-4cc4-97e8-e191f3f37239 :Steps: 1. Create an activation key 2. Update the content view with another content view which has RH products :expectedresults: Activation key is updated :CaseLevel: Integration """ name = gen_string('alpha') env1_name = gen_string('alpha') env2_name = gen_string('alpha') cv1_name = gen_string('alpha') cv2_name = gen_string('alpha') rh_repo1 = { 'name': REPOS['rhva6']['name'], 'product': PRDS['rhel'], 'reposet': REPOSET['rhva6'], 'basearch': DEFAULT_ARCHITECTURE, 'releasever': DEFAULT_RELEASE_VERSION, } rh_repo2 = { 'name': ('Red Hat Enterprise Virtualization Agents for RHEL 6 ' 'Server RPMs i386 6Server'), 'product': PRDS['rhel'], 'reposet': REPOSET['rhva6'], 'basearch': 'i386', 'releasever': DEFAULT_RELEASE_VERSION, } org = entities.Organization().create() with manifests.clone() as manifest: upload_manifest(org.id, manifest.content) repo1_id = enable_sync_redhat_repo(rh_repo1, org.id) cv_publish_promote(cv1_name, env1_name, repo1_id, org.id) repo2_id = enable_sync_redhat_repo(rh_repo2, org.id) cv_publish_promote(cv2_name, env2_name, repo2_id, org.id) with session: session.organization.select(org.name) session.activationkey.create({ 'name': name, 'lce': {env1_name: True}, 'content_view': cv1_name, }) assert session.activationkey.search(name)[0]['Name'] == name ak = session.activationkey.read(name) assert ak['details']['content_view'] == cv1_name if bz_bug_is_open(1597639): assert session.activationkey.search(name)[0]['Name'] == name session.activationkey.update(name, {'details': { 'lce': {env2_name: True}, 'content_view': cv2_name, }}) ak = session.activationkey.read(name) assert ak['details']['content_view'] == cv2_name
def test_positive_add_foreman_role_with_org_loc( session, ldap_data, ldap_user_name, test_name, auth_source, ldap_usergroup_name, module_org, module_loc): """Associate foreman roles to User Group with org and loc set. [belonging to external AD User Group.] :id: b39d7b2a-6d78-4c35-969a-37c8317ce64f :setup: LDAP Auth Source should be created with Org and Location Associated. :Steps: 1. Create an UserGroup. 2. Assign some foreman roles to UserGroup. 3. Create and associate an External AD UserGroup. :expectedresults: Whether a User belonging to User Group is able to access foreman entities as per roles, with the associated org and loc in LDAP Auth source page as the context set. :CaseLevel: Integration """ auth_source_name = 'LDAP-' + auth_source.name name = gen_string('alpha') user_permissions = { 'Hostgroup': PERMISSIONS['Hostgroup'], 'Location': ['assign_locations'], 'Organization': ['assign_organizations'], } foreman_role = entities.Role().create() create_role_permissions(foreman_role, user_permissions) with session: session.usergroup.create({ 'usergroup.name': ldap_usergroup_name, 'roles.resources.assigned': [foreman_role.name], 'external_groups.name': EXTERNAL_GROUP_NAME, 'external_groups.auth_source': auth_source_name, }) assert session.usergroup.search(ldap_usergroup_name)[0]['Name'] == ldap_usergroup_name session.user.update(ldap_data['ldap_user_name'], {'user.auth': auth_source_name}) session.usergroup.refresh_external_group(ldap_usergroup_name, EXTERNAL_GROUP_NAME) with Session( test_name, ldap_data['ldap_user_name'], ldap_data['ldap_user_passwd'], ) as ldapsession: with raises(NavigationTriesExceeded): ldapsession.architecture.search('') if bz_bug_is_open(1652938): try: ldapsession.hostgroup.search('') except NoSuchElementException: ldapsession.browser.refresh() ldapsession.hostgroup.create({'host_group.name': name}) hostgroup = session.hostgroup.read(name, ['organizations', 'locations']) assert len(hostgroup['organizations']['resources']['assigned']) == 1 assert module_org.name in hostgroup['organizations']['resources']['assigned'] assert len(hostgroup['locations']['resources']['assigned']) == 1 assert module_loc.name in hostgroup['locations']['resources']['assigned']
def test_entity_read(self): """@Test: Create an entity and get it using ``nailgun.entity_mixins.EntityReadMixin.read``. @Feature: Test multiple API paths @Assert: The just-read entity is an instance of the correct class. """ exclude_list = ( entities.Architecture, # see test_architecture_read entities.OperatingSystemParameter, # see test_osparameter_read entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_entity_read arg: %s', entity_cls) skip_if_sam(self, entity_cls) if entity_cls == entities.System and bz_bug_is_open(1223494): self.skipTest('Cannot read all system attributes.') entity_id = entity_cls().create_json()['id'] self.assertIsInstance( entity_cls(id=entity_id).read(), entity_cls )
def test_positive_update(self): """Update a role with and give a name of ``name_generator()``. @id: 30cb4b42-24cd-48a0-a3c5-7ca44c060e2e @Assert: The role is updated with the given name. """ for name in generate_strings_list(exclude_types=['html']): with self.subTest(name): if bz_bug_is_open(1112657) and name in [ 'cjk', 'latin1', 'utf8' ]: self.skipTest('Bugzilla bug 1112657 is open.') role = entities.Role().create() role.name = name self.assertEqual(role.update(['name']).name, name)
def valid_domain_update_data(): """Returns a list of valid test data for domain update tests""" names = [{ 'name': gen_string('alpha') }, { 'name': gen_string('numeric') }, { 'name': gen_string('alphanumeric') }, { 'name': gen_string('utf8') }, { 'name': gen_string('latin1') }] if not bz_bug_is_open(1220104): names.append({'name': gen_string('html')}) return names
def test_negative_create_with_invalid_hostname(self): """Create Discovery Rule with invalid hostname :id: 0ae51085-30d0-44f9-9e49-abe928a8a4b7 :expectedresults: Error should be raised and rule should not be created :CaseImportance: Critical """ for name in self.invalid_hostnames_list(): with self.subTest(name): bug_id = name.pop('bugzilla', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest('Bugzilla bug {0} is open.'.format(bug_id)) with self.assertRaises(CLIFactoryError): self._make_discoveryrule({u'hostname': name})
def test_downstream_openbug_whiteboard(self, dec_settings): """Assert ``True`` is returned if - bug is in open status - bug has a valid/invalid Whiteboard text - robottelo in downstream mode """ class MockBug(object): # pylint:disable=R0903 """A mock bug""" status = None whiteboard = None dec_settings.upstream = False decorators._get_bugzilla_bug = lambda bug_id: MockBug() for MockBug.status in BZ_OPEN_STATUSES: for MockBug.whiteboard in (self.valid_whiteboard_data + self.invalid_whiteboard_data): self.assertTrue(decorators.bz_bug_is_open(self.bug_id))
def test_downstream_openbug_whiteboard(self, dec_settings): """Assert ``True`` is returned if - bug is in open status - bug has a valid/invalid Whiteboard text - robottelo in downstream mode """ original_bug = {'id': 1, 'status': '', 'whiteboard': ''} dec_settings.upstream = False decorators._get_bugzilla_bug = lambda bug_id: original_bug all_whiteboard_data = chain(self.valid_whiteboard_data, self.invalid_whiteboard_data) for original_bug['status'], original_bug['whiteboard'] in \ product(BZ_OPEN_STATUSES, all_whiteboard_data): self.assertTrue(decorators.bz_bug_is_open(self.bug_id))
def test_positive_sc_params_by_name(self): """Check if environment sc-param subcommand works passing an environment name @Feature: Environment @Assert: The command runs without raising an error @BZ: 1219934 """ environment = make_environment() Environment.sc_params({ 'environment': environment['name'], }) if not bz_bug_is_open(1219934): self.fail('BZ #1219934 is closed, should assert the content')
def test_positive_update_cv(session, module_org, cv2_name): """Update Content View in an Activation key :id: 68880ca6-acb9-4a16-aaa0-ced680126732 :Steps: 1. Create Activation key 2. Update the Content view with another Content view which has custom products :expectedresults: Activation key is updated :CaseLevel: Integration """ name = gen_string('alpha') env1_name = gen_string('alpha') env2_name = gen_string('alpha') cv1_name = gen_string('alpha') # Helper function to create and promote CV to next environment repo1_id = create_sync_custom_repo(module_org.id) cv_publish_promote(cv1_name, env1_name, repo1_id, module_org.id) repo2_id = create_sync_custom_repo(module_org.id) cv_publish_promote(cv2_name, env2_name, repo2_id, module_org.id) with session: session.activationkey.create({ 'name': name, 'lce': { env1_name: True }, 'content_view': cv1_name, }) assert session.activationkey.search(name)[0]['Name'] == name ak = session.activationkey.read(name) assert ak['details']['content_view'] == cv1_name if bz_bug_is_open(1597639): assert session.activationkey.search(name)[0]['Name'] == name session.activationkey.update(name, { 'details': { 'lce': { env2_name: True }, 'content_view': cv2_name, } }) ak = session.activationkey.read(name) assert ak['details']['content_view'] == cv2_name
def test_positive_update(self): """Update a role with and give a name of ``name_generator()``. @Feature: Role @Assert: The role is updated with the given name. """ for name_generator in data_generator(): with self.subTest(name_generator): if bz_bug_is_open(1112657) and (name_generator is gen_cjk or name_generator is gen_latin1 or name_generator is gen_utf8): self.skipTest('Bugzilla bug 1112657 is open.') role = entities.Role().create() name = name_generator() role.name = name self.assertEqual(role.update(['name']).name, name)
def test_positive_run_recurring_job_with_max_iterations_by_ip(self): """Run default job template multiple times with max iteration by ip :id: 0a3d1627-95d9-42ab-9478-a908f2a7c509 :expectedresults: Verify the job was run not more than the specified number of times. """ # set connecting to host by ip Host.set_parameter({ 'host': self.client.hostname, 'name': 'remote_execution_connect_by_ip', 'value': 'True', }) invocation_command = make_job_invocation({ 'job-template': 'Run Command - SSH Default', 'inputs': 'command="ls"', 'search-query': "name ~ {0}".format(self.client.hostname), 'cron-line': '* * * * *', # every minute 'max-iteration': 2, # just two runs }) if not bz_bug_is_open(1431190): JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname }) try: self.assertEqual(invocation_command['status'], u'queued') except AssertionError: result = 'host output: {0}'.format(' '.join( JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname }))) raise AssertionError(result) sleep(150) rec_logic = RecurringLogic.info( {'id': invocation_command['recurring-logic-id']}) self.assertEqual(rec_logic['state'], u'finished') self.assertEqual(rec_logic['iteration'], u'2')
def test_positive_create(self): """Create a role with name ``name_generator()``. :id: 488a0970-f844-4286-b1eb-dd93005b4580 :expectedresults: An entity can be created without receiving any errors, the entity can be fetched, and the fetched entity has the specified name. :CaseImportance: Critical """ for name in generate_strings_list(exclude_types=['html']): with self.subTest(name): if bz_bug_is_open(1112657) and name in [ 'cjk', 'latin1', 'utf8' ]: self.skipTest('Bugzilla bug 1112657 is open.') self.assertEqual(entities.Role(name=name).create().name, name)
def _install_package(self, clients, host_ids, package_name): """Workaround BZ1374669 and install package via CLI while the bug is open. """ if bz_bug_is_open(1374669): for client in clients: result = client.run('yum install -y {}'.format(package_name)) self.assertEqual(result.return_code, 0) result = client.run('rpm -q {}'.format(package_name)) self.assertEqual(result.return_code, 0) return entities.Host().install_content(data={ 'organization_id': self.org.id, 'included': {'ids': host_ids}, 'content_type': 'package', 'content': [package_name], }) self._validate_package_installed(clients, package_name)
def test_positive_delete(self): """Deletes the Hardware-Model @feature: Hardware-Model - Positive delete @assert: Hardware-Model is deleted """ with Session(self.browser) as session: for test_data in valid_hw_model_names(): with self.subTest(test_data): bug_id = test_data.pop('bugzilla', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest( 'Bugzilla bug {0} is open for html ' 'data.'.format(bug_id) ) make_hw_model(session, name=test_data['name']) self.hardwaremodel.delete(test_data['name'])
def test_positive_delete(self): """Delete a role with name ``name_generator()``. @id: 6e1d9f9c-3cbb-460b-8ef8-4a156e6552a0 @Assert: The role cannot be fetched after it is deleted. """ for name in generate_strings_list(exclude_types=['html']): with self.subTest(name): if bz_bug_is_open(1112657) and name in [ 'cjk', 'latin1', 'utf8' ]: self.skipTest('Bugzilla bug 1112657 is open.') role = entities.Role(name=name).create() self.assertEqual(role.name, name) role.delete() with self.assertRaises(HTTPError): role.read()
def test_positive_list_permission(test_name, module_org, module_repos_col, module_rhva_repos_col): """Show errata only if the User has permissions to view them :id: cdb28f6a-23df-47a2-88ab-cd3b492126b2 :Setup: 1. Create two products with one repo each. Sync them. 2. Make sure that they both have errata. 3. Create a user with view access on one product and not on the other. :Steps: Go to Content -> Errata. :expectedresults: Check that the new user is able to see errata for one product only. :CaseLevel: Integration """ role = entities.Role().create() entities.Filter( organization=[module_org], permission=entities.Permission( resource_type='Katello::Product').search(), role=role, search='name = "{0}"'.format(PRDS['rhel']), ).create() user_password = gen_string('alphanumeric') user = entities.User( default_organization=module_org, organization=[module_org], role=[role], password=user_password, ).create() with Session(test_name, user=user.login, password=user_password) as session: if bz_bug_is_open(1652938): # The bug has a persistent effect when user has no access to dashboard and foreman # access denied page is shown directly after login. try: session.errata.search('') except NoSuchElementException: session.errata.browser.refresh() assert (session.errata.search(RHVA_ERRATA_ID, applicable=False)[0]['Errata ID'] == RHVA_ERRATA_ID) assert not session.errata.search(CUSTOM_REPO_ERRATA_ID, applicable=False)
def setUpClass(cls): """Display all the bookmarks on the same page, create user and entities for testing. """ super(BookmarkTestCase, cls).setUpClass() cls.entities = [] # Custom user for bookmark visibility testing role = entities.Role().search(query={'search': 'name="Viewer"'})[0] cls.custom_password = gen_string('alphanumeric') cls.custom_user = entities.User( role=[role], password=cls.custom_password, ).create() for entity in BOOKMARK_ENTITIES: # Skip the entities, which can't be tested ATM (require framework # update) skip = entity.get('skip_for_ui') if isinstance(skip, tuple): if (skip[0] == 'bugzilla' and bz_bug_is_open(skip[1]) or skip[0] == 'redmine' and rm_bug_is_open(skip[1])): skip = True if skip is True: continue cls.entities.append(entity) # Some pages require at least 1 existing entity for search bar to # appear. Creating 1 entity for such pages if entity.get('setup'): # entities with 1 organization if entity['name'] in ('Hosts',): entity['setup'](organization=cls.session_org).create() # entities with no organizations elif entity['name'] in ( 'Compute_Profile', 'ConfigGroups', 'GlobalParameters', 'HardwareModel', 'PuppetClasses', 'UserGroup'): entity['setup']().create() # entities with multiple organizations else: entity['setup'](organization=[cls.session_org]).create()
def install_katello_agent(self): """Installs katello agent on the virtual machine. :return: None. :raises robottelo.vm.VirtualMachineError: If katello-ca wasn't installed. """ self.run('yum install -y katello-agent') result = self.run('rpm -q katello-agent') if result.return_code != 0: raise VirtualMachineError('Failed to install katello-agent') if bz_bug_is_open('1431747'): gofer_start = self.run('service goferd start') if gofer_start.return_code != 0: raise VirtualMachineError('Failed to start katello-agent') gofer_check = self.run('service goferd status') if gofer_check.return_code != 0: raise VirtualMachineError('katello-agent is not running')
def _capsule_cleanup(self): """make the necessary cleanup in case of a crash""" if self._subscribed: # use try except to unregister the host, in case of host not # reachable (or any other failure), the capsule is not deleted and # this failure will hide any prior failure. try: self.unregister() except Exception as exp: logger.error('Failed to unregister the host: {0}\n{1}'.format( self.hostname, exp)) if self._capsule_hostname: # do cleanup as using a static hostname that can be reused by # other tests and organizations try: # try to delete the hostname first Host.delete({'name': self._capsule_hostname}) # try delete the capsule except Exception as exp: # log the exception # as maybe that the host was not registered or setup does not # reach that stage # or maybe that the capsule was not registered or setup does # not reach that stage # Destroys the Capsule VM on the provisioning server if # exception has 'return_code=70(Error: host not found)' if exp.return_code == 70: super(CapsuleVirtualMachine, self).destroy() if bz_bug_is_open('1622064'): logger.warn('Failed to cleanup the host: {0}\n{1}'.format( self.hostname, exp)) else: logger.error('Failed to cleanup the host: {0}\n{1}'.format( self.hostname, exp)) raise try: # try to delete the capsule if it was added already Capsule.delete({'name': self._capsule_hostname}) except Exception as exp: logger.error('Failed to cleanup the capsule: {0}\n{1}'.format( self.hostname, exp)) raise
def test_positive_delete(self): """Delete a role with name ``name_generator()``. @Feature: Role @Assert: The role cannot be fetched after it is deleted. """ for name_generator in data_generator(): with self.subTest(name_generator): if bz_bug_is_open(1112657) and (name_generator is gen_cjk or name_generator is gen_latin1 or name_generator is gen_utf8): self.skipTest('Bugzilla bug 1112657 is open.') name = name_generator() role = entities.Role(name=name).create() self.assertEqual(role.name, name) role.delete() with self.assertRaises(HTTPError): role.read()
def test_positive_create_with_os_family(self): """Create operating system with every OS family possible :id: 6ad32d22-53cc-4bab-ac10-f466f75d7cc6 :expectedresults: Operating system entity is created and has proper OS family assigned :CaseAutomation: Automated :CaseImportance: Critical """ for os_family in OPERATING_SYSTEMS: with self.subTest(os_family): if bz_bug_is_open(1709683): if os_family == 'Debian': continue os = entities.OperatingSystem(family=os_family).create() self.assertEqual(os.family, os_family)
def invalid_emails_list(): """Returns a list of invalid emails.""" data = [ u'foreman@', u'@foreman', u'@', u'Abc.example.com', u'A@b@[email protected]', u'[email protected]', # total length 255: u'{0}@example.com'.format(gen_string('alpha', 243)), u'{0}@example.com'.format(gen_string('html')), u's p a c e [email protected]', u'*****@*****.**' ] # Skip successive dots (not valid by RFC 5322) if bug is open if bz_bug_is_open(1455501): data.remove(u'[email protected]') data.remove(u'*****@*****.**') return data
def test_positive_upload_facts(self): """Upload fake facts to create a discovered host :id: c1f40204-bbb0-46d0-9b60-e42f00ad1649 :Steps: POST /api/v2/discovered_hosts/facts :expectedresults: Host should be created successfully :CaseLevel: Integration """ for name in valid_data_list(): with self.subTest(name): mac_address = gen_mac() host = _create_discovered_host(name, macaddress=mac_address) if bz_bug_is_open(1392919): host_name = 'mac{0}'.format(mac_address.replace(':', '')) else: host_name = 'mac{0}'.format(host['mac'].replace(':', '')) self.assertEqual(host['name'], host_name)
def test_positive_put_and_get_requests(self): """Update an entity, then read it back. :id: f5d3039f-5468-4dd2-8ac9-6e948ef39866 :expectedresults: The entity is updated with the given attributes. :CaseImportance: Critical """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) if bz_bug_is_open(1378009): exclude_list += (entities.HostGroup, ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_put_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Create an entity. entity_id = entity_cls().create_json()['id'] # Update that entity. FIXME: This whole procedure is a hack. entity = entity_cls() # Generate randomized instance attributes entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def package_search(self, name, package_name, package_tab="installed"): """Search for package on specific content host :param name: Content Host name. :param package_name: Package name. :param package_tab: Search for either `installed` packages or `applicable` packages. :return: WebElement containing package information. """ if bz_bug_is_open(1495271): Navigator(self.browser).go_to_dashboard() self.click(self.search(name)) self.click(tab_locators['contenthost.tab_packages']) if package_tab == 'installed': self.click(tab_locators.contenthost.tab_packages.installed) elif package_tab == 'applicable': self.click(tab_locators.contenthost.tab_packages.applicable) self.assign_value(common_locators.kt_search, package_name) self.click(common_locators.kt_search_button) return self.wait_until_element( locators['contenthost.package_search_name'] % package_name)
def test_positive_create_with_long_name(self): """Create new subnet with 255 characters in name @id: b86772ad-a8ff-4c2b-93f4-4a715e4da59b @Assert: Subnet is created with 255 chars """ with Session(self.browser) as session: for test_data in valid_long_names(): with self.subTest(test_data): bug_id = test_data.pop('bz-bug', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest( 'Bugzilla bug {0} is open.'.format(bug_id)) make_subnet( session, subnet_name=test_data['name'], subnet_network=gen_ipaddr(ip3=True), subnet_mask=gen_netmask(), ) self.assertIsNotNone(self.subnet.search(test_data['name']))
def test_positive_update(self): """Update a domain with name and description @id: 25ff4a1d-3ca1-4153-be45-4fe1e63f3f16 @Assert: Domain is updated """ domain_name = description = DOMAIN % gen_string('alpha', 10) with Session(self.browser) as session: make_domain(session, name=domain_name, description=description) self.assertIsNotNone(self.domain.search(domain_name)) for testdata in valid_domain_update_data(): with self.subTest(testdata): bug_id = testdata.pop('bugzilla', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest( 'Bugzilla bug {0} is open.'.format(bug_id)) new_name = new_description = DOMAIN % testdata['name'] self.domain.update(domain_name, new_name, new_description) self.assertIsNotNone(self.domain.search(new_name)) domain_name = new_name # for next iteration
def test_positive_delete_by_id(self): """Check if product can be deleted @id: 21bb8373-96d1-402c-973c-cf70d4b8244e @Assert: Product is deleted """ new_product = make_product({u'organization-id': self.org['id']}) Product.delete({u'id': new_product['id']}) with self.assertRaises(CLIReturnCodeError): Product.info({ u'id': new_product['id'], u'organization-id': self.org['id'], }) if bz_bug_is_open(1219490): for _ in range(5): time.sleep(5) Product.info({ u'id': new_product['id'], u'organization-id': self.org['id'], })
def menu_click(self, top_menu_locator, sub_menu_locator, tertiary_menu_locator=None): self.perform_action_chain_move(top_menu_locator) if not tertiary_menu_locator: self.click(sub_menu_locator, scroll=False) else: self.perform_action_chain_move(sub_menu_locator) tertiary_element = self.wait_until_element(tertiary_menu_locator) self.browser.execute_script( "arguments[0].click();", tertiary_element, ) # 1328627 - as the number of subs increases, dashboard page gets slower wait_timeout = 12 if bz_bug_is_open(1328627): wait_timeout = 40 self.wait_until_element_is_not_visible(menu_locators['navbar.spinner'], timeout=wait_timeout) self.wait_for_ajax()
def test_positive_put_and_get_requests(self): """Update an entity, then read it back. @Feature: Test multiple API paths @Assert: The entity is updated with the given attributes. """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_put_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) if (entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156)): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity. entity_id = entity_cls().create_json()['id'] # Update that entity. FIXME: This whole procedure is a hack. entity = entity_cls() # Generate randomized instance attributes entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def _get_readable_attributes(entity): """Return a dict of attributes matching what can be read from the server. When one reads an entity from the server, some attributes such as passwords are not returned. In addition, it is extremely hard to predict the exact format or naming of certain types of foreign key attributes. The remaining attributes, however, definitely should be present. Collect attributes from the ``entity`` object, drop attributes that the server doesn't hand back like passwords, drop foreign keys. What remains should match what the server will return. """ attributes = entity.get_values() # Drop sensitive attributes. if isinstance(entity, entities.Host): del attributes['root_pass'] del attributes['name'] # FIXME: "Foo" in, "foo.example.com" out. if isinstance(entity, entities.User): del attributes['password'] if isinstance(entity, entities.System) and bz_bug_is_open(1202917): del attributes['facts'] del attributes['type'] # Drop foreign key attributes. for field_name in attributes.keys(): if isinstance( entity.get_fields()[field_name], (entity_fields.OneToOneField, entity_fields.OneToManyField) ): del attributes[field_name] # The server deals with a field named "path", but we name the same field # path_ due to a naming conflict with a method by that name. Same w/search. if isinstance(entity, entities.Media): attributes['path'] = attributes.pop('path_') if isinstance(entity, entities.DiscoveryRule): attributes['search'] = attributes.pop('search_') return attributes
def test_positive_run_recurring_job_with_max_iterations(self): """Run default job template multiple times with max iteration :id: 37fb7d77-dbb1-45ae-8bd7-c70be7f6d949 :expectedresults: Verify the job was run not more than the specified number of times. """ invocation_command = make_job_invocation({ 'job-template': 'Run Command - SSH Default', 'inputs': 'command="ls"', 'search-query': "name ~ {0}".format(self.client.hostname), 'cron-line': '* * * * *', # every minute 'max-iteration': 2, # just two runs }) if not bz_bug_is_open(1431190): JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname }) try: self.assertEqual(invocation_command['status'], u'queued') except AssertionError: result = 'host output: {0}'.format(' '.join( JobInvocation.get_output({ 'id': invocation_command[u'id'], 'host': self.client.hostname }))) raise AssertionError(result) sleep(150) rec_logic = RecurringLogic.info( {'id': invocation_command['recurring-logic-id']}) self.assertEqual(rec_logic['state'], u'finished') self.assertEqual(rec_logic['iteration'], u'2')