def test_delete(self, entity): """@Test Create an entity, fetch it, DELETE it, and fetch it again. @Assert DELETE succeeds. HTTP 200, 202 or 204 is returned before deleting entity, and 404 is returned after deleting entity. """ attrs = entity().create() path = entity(id=attrs['id']).path() response = client.delete( path, auth=get_server_credentials(), verify=False, ) status_code = (httplib.NO_CONTENT, httplib.OK, httplib.ACCEPTED) self.assertIn( response.status_code, status_code, status_code_error(path, status_code, response), ) response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.NOT_FOUND self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_positive_update_3(self): """@Test: Create a repository and update its GPGKey @Feature: Repositories @Assert: Repository is updated with new GPGkey """ key_1_content = read_data_file(VALID_GPG_KEY_FILE) key_2_content = read_data_file(VALID_GPG_KEY_BETA_FILE) # Create an organization and product org_attrs = entities.Organization().create() product_attrs = entities.Product( organization=org_attrs['id'] ).create() gpgkey_1_attrs = entities.GPGKey( content=key_1_content, organization=org_attrs['id'] ).create() gpgkey_2_attrs = entities.GPGKey( content=key_2_content, organization=org_attrs['id'] ).create() # Creates new repository repository_attrs = entities.Repository( url=FAKE_1_YUM_REPO, product=product_attrs['id'], gpg_key=gpgkey_1_attrs['id'], ).create() path = entities.Repository(id=repository_attrs['id']).path() repository_copy = copy.deepcopy(repository_attrs) repository_copy['gpg_key_id'] = gpgkey_2_attrs['id'] response = client.put( path, repository_copy, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( response.status_code, status_code, status_code_error(path, status_code, response), ) # Fetch the updated repository updated_attrs = entities.Repository( id=repository_attrs['id'] ).read_json() # Assert that key is updated self.assertEqual( updated_attrs['gpg_key_id'], gpgkey_2_attrs['id'], )
def test_post_status_code(self, entity): """@Test: Issue a POST request and check the returned status code. @Assert: HTTP 201 is returned with an ``application/json`` content-type """ # Some arguments are "normal" classes and others are objects produced # by functools.partial. Also, `partial(SomeClass).func == SomeClass`. if ((entity.func if isinstance(entity, partial) else entity) in BZ_1118015_ENTITIES and bz_bug_is_open(1118015)): self.skipTest('Bugzilla bug 1118015 is open.') path = entity().path() response = client.post( path, entity().build(), auth=get_server_credentials(), verify=False, ) status_code = httplib.CREATED self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_get_releases_status_code(self): """@Test: Get an activation key's releases. Check response format. @Assert: HTTP 200 is returned with an ``application/json`` content-type @Feature: ActivationKey """ try: attrs = entities.ActivationKey().create() except HTTPError as err: self.fail(err) path = entities.ActivationKey(id=attrs['id']).path(which='releases') response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_get_status_code(self, entity): """@Test: Create an entity and GET it. @Assert: HTTP 200 is returned with an ``application/json`` content-type """ if entity is entities.ActivationKey and bz_bug_is_open(1127335): self.skipTest("Bugzilla bug 1127335 is open.""") try: attrs = entity().create() except factory.FactoryError as err: self.fail(err) path = entity(id=attrs['id']).path() response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_positive_create_1(self, login): """ @Test Create a user providing the initial login name. @Assert: User is created and contains provided login name. @Feature: User """ path = entities.User().path() attrs = entities.User(login=login).build() response = client.post( path, attrs, auth=get_server_credentials(), verify=False, ) status_code = (httplib.OK, httplib.CREATED) self.assertIn( response.status_code, status_code, status_code_error(path, status_code, response), ) # Fetch the user real_attrs = client.get( entities.User(id=response.json()['id']).path(), auth=get_server_credentials(), verify=False, ).json() # Remove the ``password`` field from ``attrs`` since it isn't # returned by GET. attrs.pop('password') # Assert that keys and values match for key, value in attrs.items(): self.assertIn(key, real_attrs.keys()) self.assertEqual(value, real_attrs[key])
def test_update_max_content_hosts(self): """@Test: Create an activation key with ``max_content_hosts == 1``, then update that field with a string value. @Feature: ActivationKey @Assert: The update fails with an HTTP 422 return code. """ attrs = entities.ActivationKey(max_content_hosts=1).create() path = entities.ActivationKey(id=attrs['id']).path() new_attrs = attrs.copy() new_attrs['max_content_hosts'] = 'foo' response = client.put( path, new_attrs, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.UNPROCESSABLE_ENTITY, status_code_error(path, httplib.UNPROCESSABLE_ENTITY, response), ) # Status code is OK. Was `max_content_hosts` changed, or is it still 1? response = entities.ActivationKey(id=attrs['id']).read_json() self.assertEqual(response['max_content_hosts'], 1)
def test_delete_status_code(self, entity): """@Test Issue an HTTP DELETE request and check the returned status code. @Assert: HTTP 200, 202 or 204 is returned with an ``application/json`` content-type. """ if entity is entities.ConfigTemplate and bz_bug_is_open(1096333): self.skipTest('Cannot delete config templates.') try: attrs = entity().create() except factory.FactoryError as err: self.fail(err) path = entity(id=attrs['id']).path() response = client.delete( path, auth=get_server_credentials(), verify=False, ) status_code = (httplib.NO_CONTENT, httplib.OK, httplib.ACCEPTED) self.assertIn( response.status_code, status_code, status_code_error(path, status_code, response), ) # According to RFC 2616, HTTP 204 responses "MUST NOT include a # message-body". If a message does not have a body, there is no need to # set the content-type of the message. if response.status_code is not httplib.NO_CONTENT: self.assertIn('application/json', response.headers['content-type'])
def test_delete_and_get(self): """@Test: Issue an HTTP DELETE request and GET the deleted system. @Assert: An HTTP 404 is returned when fetching the missing system. """ try: attrs = System().create() except factory.FactoryError as err: self.fail(err) System(uuid=attrs['uuid']).delete() # Get the now non-existent system path = System(uuid=attrs['uuid']).path() response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.NOT_FOUND self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_delete_and_get(self, entity): """@Test: Issue an HTTP DELETE request and GET the deleted entity. @Assert: An HTTP 404 is returned when fetching the missing entity. """ if entity is entities.ConfigTemplate and bz_bug_is_open(1096333): self.skipTest('Cannot delete config templates.') # Create an entity, then delete it. try: entity_n = entity(id=entity().create()['id']) except factory.FactoryError as err: self.fail(err) logger.info('test_delete_and_get path: {0}'.format(entity_n.path())) entity_n.delete() # Get the now non-existent entity. response = client.get( entity_n.path(), auth=get_server_credentials(), verify=False, ) status_code = httplib.NOT_FOUND self.assertEqual( status_code, response.status_code, status_code_error(entity_n.path(), status_code, response), )
def test_json_error(self): """Make ``response.json()`` return a dict with an error message.""" self.response.json = lambda: {'error': 'error message'} msg = utils.status_code_error(self.path, self.desired, self.response) if version_info[0] == 2: self.assertIsInstance(msg, unicode) else: self.assertIsInstance(msg, str)
def test_positive_delete_filter_from_role(self): """@Test: Delete the filter to remove permissions from a role. @Feature: Role and Permissions @Assert: Filter should be deleted """ role_name = orm.StringField(str_type=('alphanumeric',)).get_value() try: role_attrs = entities.Role(name=role_name).create() except factory.FactoryError as err: self.fail(err) # fail instead of error path = entities.Role(id=role_attrs['id']).path() # GET the role and verify it's name. response = client.get( path, auth=get_server_credentials(), verify=False, ).json() self.assertEqual(response['name'], role_name) # Get permissions that have a resource_type of ConfigTemplate. permissions = client.get( entities.Permission().path(), auth=get_server_credentials(), verify=False, data={'resource_type': 'Ptable'}, ).json()['results'] # Create a filter under a selected role with all permissions # of a selected resource_type. filter_attrs = entities.Filter( role=role_attrs['id'], permission=[permission['id'] for permission in permissions] ).create() filter_path = entities.Filter(id=filter_attrs['id']).path() client.get( filter_path, auth=get_server_credentials(), verify=False, ).json() # Delete the Filter, GET it, and assert that an HTTP 404 is returned. entities.Filter(id=filter_attrs['id']).delete() response = client.get( filter_path, auth=get_server_credentials(), verify=False, ) status_code = httplib.NOT_FOUND self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_negative_update_1(self, max_content_hosts): """@Test: Create activation key then update its limit to invalid value. @Assert: 1. Activation key is created 2. Update fails 3. Record is not changed @Feature: ActivationKey """ try: attrs = entities.ActivationKey().create() except FactoryError as err: self.fail(err) path = entities.ActivationKey(id=attrs['id']).path() # Make a copy of the activation key and update a few fields. ak_copy = attrs.copy() ak_copy['unlimited_content_hosts'] = False ak_copy['max_content_hosts'] = max_content_hosts # Update the activation key with semantically incorrect values. response = client.put( path, ak_copy, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.UNPROCESSABLE_ENTITY, status_code_error(path, httplib.UNPROCESSABLE_ENTITY, response), ) # Fetch the activation key. Assert that values have not changed. real_attrs = entities.ActivationKey(id=attrs['id']).read_json() self.assertEqual( real_attrs['unlimited_content_hosts'], attrs['unlimited_content_hosts'], u"Unlimited content hosts values: {0} == {1}".format( real_attrs['unlimited_content_hosts'], attrs['unlimited_content_hosts']) ) self.assertTrue( real_attrs['unlimited_content_hosts'], u"Unlimited content hosts is {0}".format( real_attrs['unlimited_content_hosts'] ) ) self.assertEqual( real_attrs['max_content_hosts'], attrs['max_content_hosts'], u"Max content hosts values: {0} == {1}".format( real_attrs['max_content_hosts'], attrs['max_content_hosts']) )
def test_no_json(self): """Make ``response.json()`` raise a ``ValueError``.""" def json(): raise ValueError() self.response.json = json msg = utils.status_code_error(self.path, self.desired, self.response) if version_info[0] == 2: self.assertIsInstance(msg, unicode) else: self.assertIsInstance(msg, str)
def test_post_unauthorized(self, entity): """@Test: POST to an entity-dependent path without credentials. @Assert: HTTP 401 is returned """ path = entity().path() response = client.post(path, verify=False) status_code = httplib.UNAUTHORIZED self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_positive_update_2(self): """@Test: Create a repository and update its URL @Feature: Repositories @Assert: Repository URL is updated """ # Creates new repository repository_attrs = entities.Repository( url=FAKE_1_YUM_REPO, ).create() path = entities.Repository(id=repository_attrs['id']).path() repository_copy = copy.deepcopy(repository_attrs) repository_copy['url'] = FAKE_2_YUM_REPO response = client.put( path, repository_copy, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( response.status_code, status_code, status_code_error(path, status_code, response), ) # Fetch the updated repository updated_attrs = entities.Repository( id=repository_attrs['id'] ).read_json() # Assert that URL is updated self.assertNotEqual( updated_attrs['url'], repository_attrs['url'], ) self.assertEqual( updated_attrs['url'], FAKE_2_YUM_REPO, )
def test_get_status_code(self, entity): """@Test GET an entity-dependent path. @Assert: HTTP 200 is returned with an ``application/json`` content-type """ path = entity().path() response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_negative_update_1(self, max_content_hosts): """@Test: Create activation key then update its limit to invalid value. @Assert: 1. Activation key is created 2. Update fails 3. Record is not changed @Feature: ActivationKey """ try: attrs = entities.ActivationKey().create() except HTTPError as err: self.fail(err) activationkey = entities.ActivationKey(id=attrs['id']) # Update the activation key with semantically incorrect values. response = client.put( activationkey.path(), { u'unlimited_content_hosts': False, u'max_content_hosts': max_content_hosts }, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.UNPROCESSABLE_ENTITY, status_code_error( activationkey.path(), httplib.UNPROCESSABLE_ENTITY, response ), ) # Make sure no attributes have changed. new_attrs = activationkey.read_json() for attr in ('unlimited_content_hosts', 'max_content_hosts'): self.assertEqual(attrs[attr], new_attrs[attr]) self.assertTrue(new_attrs['unlimited_content_hosts'])
def test_get_status_code(self): """@Test: Create a system and GET it. @Assert: HTTP 200 is returned with an ``application/json`` content-type """ attrs = System().create() path = System(uuid=attrs['uuid']).path() response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_put_status_code(self, entity): """@Test Issue a PUT request and check the returned status code. @Assert: HTTP 200 is returned with an ``application/json`` content-type """ path = entity(id=entity().create()['id']).path() response = client.put( path, entity().attributes(), auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def test_positive_update_1(self, test_data): """@Test: Create a role and update its name @Feature: Role @Assert: Role name should be updated """ try: role_attrs = entities.Role(name=test_data['name']).create() except factory.FactoryError as err: self.fail(err) # fail instead of error path = entities.Role(id=role_attrs['id']).path() role_copy = role_attrs.copy() role_copy['name'] = test_data['new_name'] response = client.put( path, role_copy, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( response.status_code, status_code, status_code_error(path, status_code, response), ) # Fetch the updated role updated_attrs = client.get( path, auth=get_server_credentials(), verify=False, ).json() # Assert that values have changed self.assertNotEqual( updated_attrs['name'], role_attrs['name'], )
def test_positive_delete_1(self, name): """@Test: Create a role and delete it @Feature: Role @Assert: Role deletion should succeed """ try: role_attrs = entities.Role(name=name).create() except factory.FactoryError as err: self.fail(err) # fail instead of error path = entities.Role(id=role_attrs['id']).path() # GET the role and verify it's name. response = client.get( path, auth=get_server_credentials(), verify=False, ).json() self.assertEqual(response['name'], name) # Delete the role, GET it, and assert that an HTTP 404 is returned. response = client.delete( path, auth=get_server_credentials(), verify=False, ) # 404 should be returned for deleted role response = client.get( path, auth=get_server_credentials(), verify=False, ) status_code = httplib.NOT_FOUND self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_ping(self): """ @Test: Check if all services are running @Feature: Smoke Test @Assert: Overall and individual services status should be 'ok'. """ path = entities.Ping().path() response = client.get( path, auth=get_server_credentials(), verify=False) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response) ) # Check overal status self.assertEqual( response.json()['status'], u'ok', U"The server does not seem to be configured properly!" ) # Extract all services status information returned with the 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'elasticsearch': {u'duration_ms': u'22', u'status': u'ok'}, # u'katello_jobs': {u'duration_ms': u'43', u'status': u'ok'}, # u'pulp': {u'duration_ms': u'18', u'status': u'ok'}, # u'pulp_auth': {u'duration_ms': u'30', u'status': u'ok'}}, # u'status': u'ok'} services = response.json()['services'] # Check if all services are 'OK' ok_status = all( [service['status'] == u'ok' for service in services.values()] ) self.assertTrue( ok_status, u"Not all services seem to be up and running!" )
def test_positive_update_4(self): """@Test: Create a repository and update to publish it via HTTP @Feature: Repositories @Assert: Repository is updated with unprotected flag 'True' """ repository_attrs = entities.Repository( url=FAKE_1_YUM_REPO, ).create() path = entities.Repository(id=repository_attrs['id']).path() repository_copy = copy.deepcopy(repository_attrs) repository_copy['unprotected'] = True response = client.put( path, repository_copy, auth=get_server_credentials(), verify=False, ) status_code = httplib.OK self.assertEqual( response.status_code, status_code, status_code_error(path, status_code, response), ) # Fetch the updated repository updated_attrs = entities.Repository( id=repository_attrs['id'] ).read_json() # Assert that unprotected flag is updated self.assertEqual( updated_attrs['unprotected'], True, )
def test_post_status_code(self, entity): """@Test: Issue a POST request and check the returned status code. @Assert: HTTP 201 is returned with an ``application/json`` content-type """ if entity in BZ_1118015_ENTITIES and bz_bug_is_open(1118015): self.skipTest("Bugzilla bug 1118015 is open.""") path = entity().path() response = client.post( path, entity().build(), auth=get_server_credentials(), verify=False, ) status_code = httplib.CREATED self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), ) self.assertIn('application/json', response.headers['content-type'])
def _search(self, entity, query, auth=None): """ Performs a GET ``api/v2/<entity>`` and specify the ``search`` parameter. :param robottelo.orm.Entity entity: A logical representation of a Foreman entity. :param string query: A ``search`` parameter. :param tuple auth: A ``tuple`` containing the credentials to be used for authentication when accessing the API. If ``None``, credentials are automatically read from :func:`robottelo.common.helpers.get_server_credentials`. :return: A ``dict`` representing a Foreman entity. :rtype: dict """ # Use the server credentials if None are provided if auth is None: auth = get_server_credentials() path = entity().path() response = client.get( path, auth=auth, params={'search': query}, verify=False, ) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response) ) self.assertEqual( response.json()['search'], query, u"Could not find {0}.".format(query) ) return response.json()
def test_create_text_plain(self): """@Test Create an organization using a 'text/plain' content-type. @Assert: HTTP 415 is returned. @Feature: Organization """ path = entities.Organization().path() attrs = entities.Organization().build() response = client.post( path, attrs, auth=get_server_credentials(), headers={'content-type': 'text/plain'}, verify=False, ) status_code = httplib.UNSUPPORTED_MEDIA_TYPE self.assertEqual( status_code, response.status_code, status_code_error(path, status_code, response), )
def test_positive_update_1(self, max_content_hosts): """@Test: Create activation key then update it to limited content hosts. @Assert: Activation key is created, updated to limited content host @Feature: ActivationKey """ try: attrs = entities.ActivationKey().create() except FactoryError as err: self.fail(err) path = entities.ActivationKey(id=attrs['id']).path() # Make a copy of the activation key... ak_copy = attrs.copy() # ...and update a few fields ak_copy['unlimited_content_hosts'] = False ak_copy['max_content_hosts'] = max_content_hosts # Update the activation key response = client.put( path, ak_copy, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response), ) # Fetch the activation key real_attrs = client.get( entities.ActivationKey(id=attrs['id']).path(), auth=get_server_credentials(), verify=False, ).json() # Assert that values have changed self.assertNotEqual( real_attrs['unlimited_content_hosts'], attrs['unlimited_content_hosts'], u"Unlimited content hosts values: {0} == {1}".format( real_attrs['unlimited_content_hosts'], attrs['unlimited_content_hosts']) ) self.assertFalse( real_attrs['unlimited_content_hosts'], u"Unlimited content hosts is {0}".format( real_attrs['unlimited_content_hosts'] ) ) self.assertNotEqual( real_attrs['max_content_hosts'], attrs['max_content_hosts'], u"Max content hosts values: {0} == {1}".format( real_attrs['max_content_hosts'], attrs['max_content_hosts']) ) self.assertEqual( real_attrs['max_content_hosts'], max_content_hosts, u"Max content hosts values don't match: {0} != {1}".format( real_attrs['max_content_hosts'], attrs['max_content_hosts'] ) )
def test_smoke(self): """@Test: Check that basic content can be created 1. Create a new user with admin permissions 2. Using the new user from above: 1. Create a new organization 2. Create two new lifecycle environments 3. Create a custom product 4. Create a custom YUM repository 5. Create a custom PUPPET repository 6. Synchronize both custom repositories 7. Create a new content view 8. Associate both repositories to new content view 9. Publish content view 10. Promote content view to both lifecycles 11. Create a new libvirt compute resource 12. Create a new subnet 13. Create a new domain 14. Create a new hostgroup and associate previous entities to it @Feature: Smoke Test @Assert: All entities are created and associated. """ # prep work # # FIXME: Use a larger charset when authenticating users. # # It is possible to create a user with a wide range of characters. (see # the "User" entity). However, Foreman supports only HTTP Basic # authentication, and the requests lib enforces the latin1 charset in # this auth mode. We then further restrict ourselves to the # alphanumeric charset, because Foreman complains about incomplete # multi-byte chars when latin1 chars are used. # login = gen_string('alphanumeric') password = gen_string('alphanumeric') # step 1: Create a new user with admin permissions entities.User(admin=True, login=login, password=password).create() # step 2.1: Create a new organization org = entities.Organization().create(auth=(login, password)) # step 2.2: Create 2 new lifecycle environments le1 = entities.LifecycleEnvironment(organization=org['id']).create() le2 = entities.LifecycleEnvironment( organization=org['id'], prior=le1['id']).create() # step 2.3: Create a custom product prod = entities.Product(organization=org['id']).create() # step 2.4: Create custom YUM repository repo1 = entities.Repository( product=prod['id'], content_type=u'yum', url=GOOGLE_CHROME_REPO ).create() # step 2.5: Create custom PUPPET repository repo2 = entities.Repository( product=prod['id'], content_type=u'puppet', url=FAKE_0_PUPPET_REPO ).create() # step 2.6: Synchronize both repositories for repo in [repo1, repo2]: response = client.post( entities.Repository(id=repo['id']).path('sync'), { u'ids': [repo['id']], u'organization_id': org['id'] }, auth=get_server_credentials(), verify=False, ).json() self.assertGreater( len(response['id']), 1, u"Was not able to fetch a task ID.") task_status = entities.ForemanTask(id=response['id']).poll() self.assertEqual( task_status['result'], u'success', u"Sync for repository {0} failed.".format(repo['name'])) # step 2.7: Create content view content_view = entities.ContentView(organization=org['id']).create() # step 2.8: Associate YUM repository to new content view response = client.put( entities.ContentView(id=content_view['id']).path(), auth=get_server_credentials(), verify=False, data={u'repository_ids': [repo1['id']]}) # Fetch all available puppet modules puppet_mods = client.get( entities.ContentView(id=content_view['id']).path( 'available_puppet_module_names'), auth=get_server_credentials(), verify=False).json() self.assertGreater( puppet_mods['results'], 0, u"No puppet modules were found") # Select a random puppet module from the results puppet_mod = random.choice(puppet_mods['results']) # ... and associate it to the content view path = entities.ContentView(id=content_view['id']).path( 'content_view_puppet_modules') response = client.post( path, auth=get_server_credentials(), verify=False, data={u'name': puppet_mod['module_name']}) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response) ) self.assertEqual( response.json()['name'], puppet_mod['module_name'], ) # step 2.9: Publish content view task_status = entities.ContentView(id=content_view['id']).publish() self.assertEqual( task_status['result'], u'success', u"Publishing {0} failed.".format(content_view['name'])) # step 2.10: Promote content view to both lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 1, u"Content view should be present on 1 lifecycle only") task_status = entities.ContentViewVersion( id=content_view['versions'][0]['id'] ).promote(le1['id']) self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le1['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 2, u"Content view should be present on 2 lifecycles only") task_status = entities.ContentViewVersion( id=content_view['versions'][0]['id'] ).promote(le2['id']) self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le2['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 3, u"Content view should be present on 3 lifecycle only") # BONUS: Create a content host and associate it with promoted # content view and last lifecycle where it exists content_host = entities.System( content_view=content_view['id'], environment=le2['id'] ).create() # Check that content view matches what we passed self.assertEqual( content_host['content_view_id'], content_view['id'], u"Content views do not match." ) # Check that lifecycle environment matches self.assertEqual( content_host['environment']['id'], le2['id'], u"Environments do not match." )
def test_smoke(self): """ @Test: Check that basic content can be created 1. Create a new user with admin permissions 2. Using the new user from above: 1. Create a new organization 2. Create two new lifecycle environments 3. Create a custom product 4. Create a custom YUM repository 5. Create a custom PUPPET repository 6. Synchronize both custom repositories 7. Create a new content view 8. Associate both repositories to new content view 9. Publish content view 10. Promote content view to both lifecycles 11. Create a new libvirt compute resource 12. Create a new subnet 13. Create a new domain 14. Create a new hostgroup and associate previous entities to it @Feature: Smoke Test @Assert: All entities are created and associated. """ # prep work # # FIXME: Use a larger charset when authenticating users. # # It is possible to create a user with a wide range of characters. (see # the "User" entity). However, Foreman supports only HTTP Basic # authentication, and the requests lib enforces the latin1 charset in # this auth mode. We then further restrict ourselves to the # alphanumeric charset, because Foreman complains about incomplete # multi-byte chars when latin1 chars are used. # login = orm.StringField(str_type=('alphanumeric',)).get_value() password = orm.StringField(str_type=('alphanumeric',)).get_value() # step 1: Create a new user with admin permissions entities.User(admin=True, login=login, password=password).create() # step 2.1: Create a new organization org = entities.Organization().create(auth=(login, password)) # step 2.2: Create 2 new lifecycle environments le1 = entities.LifecycleEnvironment(organization=org['id']).create() le2 = entities.LifecycleEnvironment( organization=org['id'], prior=le1['id']).create() # step 2.3: Create a custom product prod = entities.Product(organization=org['id']).create() # step 2.4: Create custom YUM repository repo1 = entities.Repository( product=prod['id'], content_type=u'yum', url=GOOGLE_CHROME_REPO ).create() # step 2.5: Create custom PUPPET repository repo2 = entities.Repository( product=prod['id'], content_type=u'puppet', url=FAKE_PUPPET_REPO ).create() # step 2.6: Synchronize both repositories for repo in [repo1, repo2]: response = client.post( entities.Repository(id=repo['id']).path('sync'), { u'ids': [repo['id']], u'organization_id': org['id'] }, auth=get_server_credentials(), verify=False, ).json() self.assertGreater( len(response['id']), 1, u"Was not able to fetch a task ID.") task_status = entities.ForemanTask(id=response['id']).poll() self.assertEqual( task_status['result'], u'success', u"Sync for repository {0} failed.".format(repo['name'])) # step 2.7: Create content view content_view = entities.ContentView(organization=org['id']).create() # step 2.8: Associate YUM repository to new content view response = client.put( entities.ContentView(id=content_view['id']).path(), auth=get_server_credentials(), verify=False, data={u'repository_ids': [repo1['id']]}) # Fetch all available puppet modules puppet_mods = client.get( entities.ContentView(id=content_view['id']).path( 'available_puppet_module_names'), auth=get_server_credentials(), verify=False).json() self.assertGreater( puppet_mods['results'], 0, u"No puppet modules were found") # Select a random puppet module from the results puppet_mod = random.choice(puppet_mods['results']) # ... and associate it to the content view path = entities.ContentView(id=content_view['id']).path( 'content_view_puppet_modules') response = client.post( path, auth=get_server_credentials(), verify=False, data={u'name': puppet_mod['module_name']}) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response) ) self.assertEqual( response.json()['name'], puppet_mod['module_name'], ) # step 2.9: Publish content view task = entities.ContentView(id=content_view['id']).publish() task_status = entities.ForemanTask(id=task['id']).poll() self.assertEqual( task_status['result'], u'success', u"Publishing {0} failed.".format(content_view['name'])) # step 2.10: Promote content view to both lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 1, u"Content view should be present on 1 lifecycle only") task = entities.ContentViewVersion( id=content_view['versions'][0]['id']).promote(le1['id']) task_status = entities.ForemanTask(id=task['id']).poll() self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le1['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 2, u"Content view should be present on 2 lifecycles only") task = entities.ContentViewVersion( id=content_view['versions'][0]['id']).promote(le2['id']) task_status = entities.ForemanTask(id=task['id']).poll() self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le2['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 3, u"Content view should be present on 3 lifecycle only") # BONUS: Create a content host and associate it with promoted # content view and last lifecycle where it exists content_host = entities.System( content_view=content_view['id'], environment=le2['id'] ).create() # Check that content view matches what we passed self.assertEqual( content_host['content_view_id'], content_view['id'], u"Content views do not match." ) # Check that lifecycle environment matches self.assertEqual( content_host['environment']['id'], le2['id'], u"Environments do not match." )