def test_positive_get_routes(): """Issue an HTTP GET response to both available routes. :id: 9e40ea7f-71ea-4ced-94ba-cde03620c654 :expectedresults: The same response is returned. :BZ: 1132817 :CaseImportance: Critical """ org = entities.Organization().create() entities.SyncPlan(organization=org).create() response1 = client.get( f'{get_url()}/katello/api/v2/sync_plans', auth=get_credentials(), data={'organization_id': org.id}, verify=False, ) response2 = client.get( f'{get_url()}/katello/api/v2/organizations/{org.id}/sync_plans', auth=get_credentials(), verify=False, ) for response in (response1, response2): response.raise_for_status() assert response1.json()['results'] == response2.json()['results']
def test_positive_build_pxe_default(self, tftpboot, target_sat): """Call the "build_pxe_default" path. :id: ca19d9da-1049-4b39-823b-933fc1a0cebd :expectedresults: The response is a JSON payload, all templates are deployed to TFTP/HTTP and are rendered correctly :CaseLevel: Integration :CaseImportance: Critical :BZ: 1202564 """ response = client.post( entities.ProvisioningTemplate().path('build_pxe_default'), auth=get_credentials(), verify=False, ) response.raise_for_status() assert type(response.json()) == dict for template in tftpboot.values(): if template['path'].startswith('http'): r = client.get(template['path'], verify=False) r.raise_for_status() rendered = r.text else: rendered = target_sat.execute( f'cat {template["path"]}').stdout.splitlines()[0] if template['kind'] == 'iPXE': assert f'{target_sat.hostname}/unattended/iPXE' in r.text else: assert (rendered == f"{settings.server.scheme}://" f"{target_sat.hostname} {template['kind']}")
def test_positive_put_status_code(self, entity_cls): """Issue a PUT request and check the returned status code. :id: 1a2186b1-0709-4a73-8199-71114e10afce :parametrized: yes :expectedresults: HTTP 200 is returned with an ``application/json`` content-type :CaseImportance: Critical :BZ: 1378009 """ # 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(), entity.update_payload(), auth=get_credentials(), verify=False, ) assert http.client.OK == response.status_code assert 'application/json' in response.headers['content-type']
def test_positive_get_status_code(self, api_url): """GET ``api/v2`` and examine the response. :id: 9d9c1afd-9158-419e-9a6e-91e9888f0c04 :expectedresults: HTTP 200 is returned with an ``application/json`` content-type """ response = client.get(api_url, auth=get_credentials(), verify=False) assert response.status_code == http.client.OK assert 'application/json' in response.headers['content-type']
def get_nailgun_config(user=None): """Return a NailGun configuration file constructed from default values. :param user: The ```nailgun.entities.User``` object of an user with additional passwd property/attribute :return: ``nailgun.config.ServerConfig`` object, populated from user parameter object else with values from ``robottelo.config.settings`` """ creds = (user.login, user.passwd) if user else get_credentials() return ServerConfig(get_url(), creds, verify=False)
def test_negative_run_capsule_upgrade_playbook_on_satellite(default_org): """Run Capsule Upgrade playbook against the Satellite itself :id: 99462a11-5133-415d-ba64-4354da539a34 :steps: 1. Add REX key to the Satellite server. 2. Run the Capsule Upgrade Playbook. 3. Check the job output for proper failure reason. :expectedresults: Should fail :CaseImportance: Medium """ sat = entities.Host().search( query={'search': f'name={settings.server.hostname}'})[0].read() template_id = (entities.JobTemplate().search( query={'search': 'name="Capsule Upgrade Playbook"'})[0].id) add_remote_execution_ssh_key(sat.name) with pytest.raises(TaskFailedError) as error: entities.JobInvocation().run( data={ 'job_template_id': template_id, 'inputs': { 'target_version': CAPSULE_TARGET_VERSION, 'whitelist_options': "repositories-validqqate,repositories-setup", }, 'targeting_type': "static_query", 'search_query': f"name = {sat.name}", }) assert 'A sub task failed' in error.value.args[0] job = entities.JobInvocation().search( query={ 'search': f'host={sat.name},status=failed,description="Capsule Upgrade Playbook"' })[0] response = client.get( f'https://{sat.name}/api/job_invocations/{job.id}/hosts/{sat.id}', auth=get_credentials(), verify=False, ) assert 'This playbook cannot be executed on a Satellite server.' in response.text
def test_positive_path(): """Check whether the path exists. :id: a8706cb7-549b-4426-9bd9-4beecc33c797 :expectedresults: Issuing an HTTP GET produces an HTTP 200 response with an ``application/json`` content-type, and the response is a list. :BZ: 1112802 :CaseImportance: Critical """ path = f'{get_url()}/rhsm' response = client.get(path, auth=get_credentials(), verify=False) assert response.status_code == http.client.OK assert 'application/json' in response.headers['content-type'] assert type(response.json()) is list
def test_negative_get_with_no_args(self): """Issue an HTTP GET to the base content view filters path. :id: da29fd90-cd96-49f9-b94e-71d4e3a35a57 :expectedresults: An HTTP 200 response is received if a GET request is issued with no arguments specified. :CaseLevel: Integration :CaseImportance: Low """ response = client.get( entities.AbstractContentViewFilter().path(), auth=get_credentials(), verify=False, ) assert response.status_code == http.client.OK
def test_positive_get_search(): """GET ``api/v2/hosts`` and specify the ``search`` parameter. :id: d63f87e5-66e6-4886-8b44-4129259493a6 :expectedresults: HTTP 200 is returned, along with ``search`` term. :CaseImportance: Critical """ query = gen_string('utf8', gen_integer(1, 100)) response = client.get( entities.Host().path(), auth=get_credentials(), data={'search': query}, verify=False, ) assert response.status_code == http.client.OK assert response.json()['search'] == query
def test_positive_get_status_code(self, entity_cls): """GET an entity-dependent path. :id: 89e4fafe-7780-4be4-acc1-90f7c02a8530 :parametrized: yes :expectedresults: HTTP 200 is returned with an ``application/json`` content-type :CaseImportance: Critical """ logger.info('test_get_status_code arg: %s', entity_cls) response = client.get(entity_cls().path(), auth=get_credentials(), verify=False) response.raise_for_status() assert http.client.OK == response.status_code assert 'application/json' in response.headers['content-type']
def test_positive_get_per_page(): """GET ``api/v2/hosts`` and specify the ``per_page`` parameter. :id: 9086f41c-b3b9-4af2-b6c4-46b80b4d1cfd :expectedresults: HTTP 200 is returned, along with per ``per_page`` value. :CaseImportance: Critical """ per_page = gen_integer(1, 1000) response = client.get( entities.Host().path(), auth=get_credentials(), data={'per_page': str(per_page)}, verify=False, ) assert response.status_code == http.client.OK assert response.json()['per_page'] == per_page
def test_positive_create(self): """Create an organization using a 'text/plain' content-type. :id: 6f67a3f0-0c1d-498c-9a35-28207b0faec2 :expectedresults: HTTP 415 is returned. :CaseImportance: Critical """ organization = entities.Organization() organization.create_missing() response = client.post( organization.path(), organization.create_payload(), auth=get_credentials(), headers={'content-type': 'text/plain'}, verify=False, ) assert http.client.UNSUPPORTED_MEDIA_TYPE == response.status_code
def test_negative_get_with_bad_args(self): """Issue an HTTP GET to the base content view filters path. :id: e6fea726-930b-4b74-b784-41528811994f :expectedresults: An HTTP 200 response is received if a GET request is issued with bad arguments specified. :CaseLevel: Integration :CaseImportance: Low """ response = client.get( entities.AbstractContentViewFilter().path(), auth=get_credentials(), verify=False, data={'foo': 'bar'}, ) assert response.status_code == http.client.OK
def test_positive_get_links(self, api_url, filtered_api_paths): """GET ``api/v2`` and check the links returned. :id: 7b2dd77a-a821-485b-94db-b583f93c9a89 :expectedresults: The paths returned are equal to ``API_PATHS``. """ # Did the server give us any paths at all? response = client.get(api_url, auth=get_credentials(), verify=False) response.raise_for_status() # response.json()['links'] is a dict like this: # # {'content_views': { # '…': '/katello/api/content_views/:id', # '…': '/katello/api/content_views/:id/available_puppet_modules', # '…': '/katello/api/organizations/:organization_id/content_views', # '…': '/katello/api/organizations/:organization_id/content_views', # }, …} # # We don't care about prose descriptions. It doesn't matter if those # change. Transform it before running any assertions: # # {'content_views': [ # '/katello/api/content_views/:id', # '/katello/api/content_views/:id/available_puppet_modules', # '/katello/api/organizations/:organization_id/content_views', # '/katello/api/organizations/:organization_id/content_views', # ], …} sat_api_paths = response.json()['links'] transformed_paths = { ep: tuple(paths.values()) for ep, paths in sat_api_paths.items() } api_diff = DeepDiff( filtered_api_paths, transformed_paths, ignore_order=True, report_repetition=True, verbose_level=0, ) assert api_diff == {}, f'API path mismatch (expected first): \n{pformat(api_diff)}'
def test_positive_put_and_get_requests(self, entity_cls): """Update an entity, then read it back. :id: f5d3039f-5468-4dd2-8ac9-6e948ef39866 :parametrized: yes :expectedresults: The entity is updated with the given attributes. :CaseImportance: Medium :BZ: 1378009 """ # Create an entity. entity = entity_cls().create_json() # Update that entity. FIXME: This whole procedure is a hack. kwargs = { 'organization': entity['organization_id'] } if 'organization_id' in entity else {} new_entity = entity_cls(**kwargs) # Generate randomized instance attributes new_entity.create_missing() response = client.put( entity_cls(id=entity['id']).path(), new_entity.create_payload(), auth=get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(new_entity) entity_attrs = entity_cls(id=entity['id']).read_json() for key, value in payload.items(): assert key in entity_attrs.keys() assert value == entity_attrs[key]
def test_inherit_puppetclass(self, session_puppet_enabled_sat): """Host that created from HostGroup entity with PuppetClass assigned to it should inherit such puppet class information under 'all_puppetclasses' field :id: 7b840f3d-413c-40bb-9a7d-cd9dad3c0737 :expectedresults: Host inherited 'all_puppetclasses' details from HostGroup that was used for such Host create procedure :BZ: 1107708, 1222118, 1487586 :CaseLevel: System """ # Creating entities like organization, content view and lifecycle_env # with not utf-8 names for easier interaction with puppet environment # further in test org = session_puppet_enabled_sat.api.Organization( name=gen_string('alpha')).create() location = session_puppet_enabled_sat.api.Location( organization=[org]).create() # Working with 'api_test_classparameters' module as we know for sure that it contains # at least few puppet classes, the name of the repo is the same as the name of puppet_class repo = puppet_class = 'api_test_classparameters' env_name = session_puppet_enabled_sat.create_custom_environment( repo=repo) content_view = session_puppet_enabled_sat.api.ContentView( name=gen_string('alpha'), organization=org).create() content_view.publish() content_view = content_view.read() lc_env = session_puppet_enabled_sat.api.LifecycleEnvironment( name=gen_string('alpha'), organization=org).create() promote(content_view.version[0], lc_env.id) content_view = content_view.read() assert len(content_view.version) == 1 # Get environments that contains chosen puppet module environment = session_puppet_enabled_sat.api.Environment().search( query={'search': f'name={env_name}'}) assert len(environment) == 1 environment = environment[0] environment.location = [location] environment.organization = [org] environment.update() # Create a host group and it dependencies. mac = entity_fields.MACAddressField().gen_value() root_pass = entity_fields.StringField(length=(8, 30)).gen_value() domain = session_puppet_enabled_sat.api.Domain().create() architecture = session_puppet_enabled_sat.api.Architecture().create() ptable = session_puppet_enabled_sat.api.PartitionTable().create() operatingsystem = session_puppet_enabled_sat.api.OperatingSystem( architecture=[architecture], ptable=[ptable]).create() medium = session_puppet_enabled_sat.api.Media( operatingsystem=[operatingsystem]).create() hostgroup = session_puppet_enabled_sat.api.HostGroup( architecture=architecture, domain=domain, environment=environment, location=[location.id], medium=medium, name=gen_string('alpha'), operatingsystem=operatingsystem, organization=[org.id], ptable=ptable, ).create() assert len(hostgroup.read_json()['all_puppetclasses']) == 0 # Get puppet class id for ntp module response = client.get( environment.path('self') + '/puppetclasses', auth=get_credentials(), verify=False, ) response.raise_for_status() results = response.json()['results'] puppet_class_id = results[puppet_class][0]['id'] # Assign puppet class client.post( hostgroup.path('self') + '/puppetclass_ids', data={ 'puppetclass_id': puppet_class_id }, auth=get_credentials(), verify=False, ).raise_for_status() hostgroup_attrs = hostgroup.read_json() assert len(hostgroup_attrs['all_puppetclasses']) == 1 assert hostgroup_attrs['all_puppetclasses'][0]['name'] == puppet_class # Create Host entity using HostGroup host = session_puppet_enabled_sat.api.Host( hostgroup=hostgroup, mac=mac, root_pass=root_pass, environment=environment, location=location, organization=org, content_facet_attributes={ 'content_view_id': content_view.id, 'lifecycle_environment_id': lc_env.id, }, name=gen_string('alpha'), ).create(False) host_attrs = host.read_json() assert len(host_attrs['all_puppetclasses']) == 1 assert host_attrs['all_puppetclasses'][0]['name'] == puppet_class
def test_inherit_puppetclass(self): """Host that created from HostGroup entity with PuppetClass assigned to it should inherit such puppet class information under 'all_puppetclasses' field :id: 7b840f3d-413c-40bb-9a7d-cd9dad3c0737 :expectedresults: Host inherited 'all_puppetclasses' details from HostGroup that was used for such Host create procedure :BZ: 1107708, 1222118, 1487586 :CaseLevel: System """ # Creating entities like organization, content view and lifecycle_env # with not utf-8 names for easier interaction with puppet environment # further in test org = entities.Organization(name=gen_string('alpha')).create() location = entities.Location(organization=[org]).create() # Creating puppet repository with puppet module assigned to it product = entities.Product(organization=org).create() puppet_repo = entities.Repository(content_type='puppet', product=product).create() # Working with 'ntp' module as we know for sure that it contains at # least few puppet classes with open(get_data_file(PUPPET_MODULE_NTP_PUPPETLABS), 'rb') as handle: puppet_repo.upload_content(files={'content': handle}) content_view = entities.ContentView(name=gen_string('alpha'), organization=org).create() result = content_view.available_puppet_modules()['results'] assert len(result) == 1 entities.ContentViewPuppetModule(author=result[0]['author'], name=result[0]['name'], content_view=content_view).create() content_view.publish() content_view = content_view.read() lc_env = entities.LifecycleEnvironment(name=gen_string('alpha'), organization=org).create() promote(content_view.version[0], lc_env.id) content_view = content_view.read() assert len(content_view.version) == 1 assert len(content_view.puppet_module) == 1 # Form environment name variable for our test env_name = f'KT_{org.name}_{lc_env.name}_{content_view.name}_{content_view.id}' # Get all environments for current organization. # We have two environments (one created after publishing and one more # was created after promotion), so we need to select promoted one environments = entities.Environment().search( query={'organization_id': org.id}) assert len(environments) == 2 environments = [ environment for environment in environments if environment.name == env_name ] assert len(environments) == 1 environment = environments[0].read() environment.location = [location] environment.update() # Create a host group and it dependencies. mac = entity_fields.MACAddressField().gen_value() root_pass = entity_fields.StringField(length=(8, 30)).gen_value() domain = entities.Domain().create() architecture = entities.Architecture().create() ptable = entities.PartitionTable().create() operatingsystem = entities.OperatingSystem(architecture=[architecture], ptable=[ptable]).create() medium = entities.Media(operatingsystem=[operatingsystem]).create() hostgroup = entities.HostGroup( architecture=architecture, domain=domain, environment=environment, location=[location.id], medium=medium, name=gen_string('alpha'), operatingsystem=operatingsystem, organization=[org.id], ptable=ptable, ).create() assert len(hostgroup.read_json()['all_puppetclasses']) == 0 # Get puppet class id for ntp module response = client.get( environment.path('self') + '/puppetclasses', auth=get_credentials(), verify=False, ) response.raise_for_status() results = response.json()['results'] puppet_class_id = results['ntp'][0]['id'] # Assign puppet class client.post( hostgroup.path('self') + '/puppetclass_ids', data={ 'puppetclass_id': puppet_class_id }, auth=get_credentials(), verify=False, ).raise_for_status() hostgroup_attrs = hostgroup.read_json() assert len(hostgroup_attrs['all_puppetclasses']) == 1 assert hostgroup_attrs['all_puppetclasses'][0]['name'] == 'ntp' # Create Host entity using HostGroup host = entities.Host( hostgroup=hostgroup, mac=mac, root_pass=root_pass, environment=environment, location=location, organization=org, content_facet_attributes={ 'content_view_id': content_view.id, 'lifecycle_environment_id': lc_env.id, }, name=gen_string('alpha'), ).create(False) host_attrs = host.read_json() assert len(host_attrs['all_puppetclasses']) == 1 assert host_attrs['all_puppetclasses'][0]['name'] == 'ntp'