def test_get_routes(self): """@Test: Issue an HTTP GET response to both available routes. @Assert: The same response is returned. @Feature: SyncPlan Targets BZ 1132817. """ org_id = entities.Organization().create_json()['id'] entities.SyncPlan(organization=org_id).create_json()['id'] response1 = client.get( '{0}/katello/api/v2/sync_plans'.format(get_server_url()), auth=get_server_credentials(), data={'organization_id': org_id}, verify=False, ) response2 = client.get( '{0}/katello/api/v2/organizations/{1}/sync_plans'.format( get_server_url(), org_id ), auth=get_server_credentials(), verify=False, ) for response in (response1, response2): response.raise_for_status() self.assertEqual( response1.json()['results'], response2.json()['results'], )
def get_packages(repository_id): """Return all packages belonging to repository ``repository_id``. :param int repository_id: A repository ID. :return: That repository's packages. :rtype: list :raises robottelo.api.utils.RepositoryPackagesException: If an error occurs while fetching the requested repository's packages. """ path = urljoin( helpers.get_server_url(), 'katello/api/v2/repositories/{0}/packages'.format(repository_id) ) response = client.get( path, auth=helpers.get_server_credentials(), verify=False, ).json() if 'errors' in response.keys(): raise RepositoryPackagesException( 'Error received after issuing GET to {0}. Error received: {1}' ''.format(path, response['errors']) ) return response['results']
def setUp(self): """ We do want a new browser instance for every test. """ if not self.remote: if self.driver_name.lower() == 'firefox': self.browser = webdriver.Firefox() elif self.driver_name.lower() == 'chrome': self.browser = webdriver.Chrome() elif self.driver_name.lower() == 'ie': self.browser = webdriver.Ie() elif self.driver_name.lower() == 'phantomjs': service_args = ['--ignore-ssl-errors=true'] self.browser = webdriver.PhantomJS( service_args=service_args ) else: self.browser = webdriver.Remote() else: self.browser = SeleniumFactory().createWebDriver( job_name=self.id(), show_session_id=True) self.browser.maximize_window() self.browser.get(get_server_url()) # Library methods self.activationkey = ActivationKey(self.browser) self.architecture = Architecture(self.browser) self.compute_resource = ComputeResource(self.browser) self.configgroups = ConfigGroups(self.browser) self.contentenv = ContentEnvironment(self.browser) self.content_views = ContentViews(self.browser) self.domain = Domain(self.browser) self.environment = Environment(self.browser) self.gpgkey = GPGKey(self.browser) self.hardwaremodel = HardwareModel(self.browser) self.hostgroup = Hostgroup(self.browser) self.hosts = Hosts(self.browser) self.location = Location(self.browser) self.login = Login(self.browser) self.medium = Medium(self.browser) self.navigator = Navigator(self.browser) self.user = User(self.browser) self.operatingsys = OperatingSys(self.browser) self.org = Org(self.browser) self.partitiontable = PartitionTable(self.browser) self.puppetclasses = PuppetClasses(self.browser) self.products = Products(self.browser) self.repository = Repos(self.browser) self.role = Role(self.browser) self.settings = Settings(self.browser) self.subnet = Subnet(self.browser) self.subscriptions = Subscriptions(self.browser) self.sync = Sync(self.browser) self.syncplan = Syncplan(self.browser) self.systemgroup = SystemGroup(self.browser) self.template = Template(self.browser) self.user = User(self.browser) self.usergroup = UserGroup(self.browser)
def setUp(self): # noqa pylint:disable=C0103 """ Back up and configure ``conf.properties``, and set ``self.base_path``. """ self.conf_properties = conf.properties.copy() conf.properties['main.server.hostname'] = 'example.com' self.base_path = '{0}/{1}'.format(helpers.get_server_url(), SampleEntity.Meta.api_path)
def setUp(self): # noqa """We do want a new browser instance for every test.""" if not self.remote: if self.driver_name.lower() == 'firefox': self.browser = webdriver.Firefox() elif self.driver_name.lower() == 'chrome': self.browser = webdriver.Chrome() elif self.driver_name.lower() == 'ie': self.browser = webdriver.Ie() elif self.driver_name.lower() == 'phantomjs': service_args = ['--ignore-ssl-errors=true'] self.browser = webdriver.PhantomJS( service_args=service_args ) else: self.browser = webdriver.Remote() else: self.browser = SeleniumFactory().createWebDriver( job_name=self.id(), show_session_id=True) self.browser.maximize_window() self.browser.get(get_server_url()) # Library methods self.activationkey = ActivationKey(self.browser) self.architecture = Architecture(self.browser) self.compute_resource = ComputeResource(self.browser) self.configgroups = ConfigGroups(self.browser) self.contentenv = ContentEnvironment(self.browser) self.content_views = ContentViews(self.browser) self.domain = Domain(self.browser) self.environment = Environment(self.browser) self.gpgkey = GPGKey(self.browser) self.hardwaremodel = HardwareModel(self.browser) self.hostgroup = Hostgroup(self.browser) self.hosts = Hosts(self.browser) self.location = Location(self.browser) self.login = Login(self.browser) self.medium = Medium(self.browser) self.navigator = Navigator(self.browser) self.user = User(self.browser) self.operatingsys = OperatingSys(self.browser) self.org = Org(self.browser) self.partitiontable = PartitionTable(self.browser) self.puppetclasses = PuppetClasses(self.browser) self.products = Products(self.browser) self.repository = Repos(self.browser) self.role = Role(self.browser) self.settings = Settings(self.browser) self.subnet = Subnet(self.browser) self.subscriptions = Subscriptions(self.browser) self.sync = Sync(self.browser) self.syncplan = Syncplan(self.browser) self.systemgroup = SystemGroup(self.browser) self.template = Template(self.browser) self.user = User(self.browser) self.usergroup = UserGroup(self.browser)
def get_api_doc(): """Go to Foreman server and grabs and returns its apidoc information :return: A dictionary with the apidoc information :rtype: dict """ response = requests.get(urljoin(get_server_url(), '/apidoc/v2.json'), verify=False) return response.json()['docs']
def get_api_doc(): """Go to Foreman server and grabs and returns its apidoc information :return: A dictionary with the apidoc information :rtype: dict """ response = requests.get( urljoin(get_server_url(), '/apidoc/v2.json'), verify=False) return response.json()['docs']
def setUp(self): # pylint:disable=C0103 """ Back up and configure ``conf.properties``, and set ``self.base_path``. """ self.conf_properties = conf.properties.copy() conf.properties['main.server.hostname'] = 'example.com' self.base_path = '{0}/{1}'.format( helpers.get_server_url(), SampleEntity.Meta.api_path )
def path(self, which=None): """Return the path to the current entity. Return the path to base entities of this entity's type if: * ``which`` is ``'base'``, or * ``which`` is ``None`` and instance attribute ``id`` is unset. Return the path to this exact entity if instance attribute ``id`` is set and: * ``which`` is ``'self'``, or * ``which`` is ``None``. Raise :class:`NoSuchPathError` otherwise. Child classes may choose to extend this method, especially if a child entity offers more than the two URLs supported by default. If extended, then the extending class should check for custom parameters before calling ``super``:: def path(self, which): if which == 'custom': return urlparse.urljoin(...) super(ChildEntity, self).__init__(which) This will allow the extending method to accept a custom parameter without accidentally raising a :class:`NoSuchPathError`. :param str which: Optional. Valid arguments are 'self' and 'base'. :return: A fully qualified URL. :rtype: str :raises robottelo.orm.NoSuchPathError: If no path can be built. """ # (no-member) pylint:disable=E1101 # It is OK that member ``self.Meta.api_path`` is not found. Subclasses # are required to set that attribute if they wish to use this method. # # Beware of leading and trailing slashes: # # urljoin('example.com', 'foo') => 'foo' # urljoin('example.com/', 'foo') => 'example.com/foo' # urljoin('example.com', '/foo') => '/foo' # urljoin('example.com/', '/foo') => '/foo' base = urlparse.urljoin( helpers.get_server_url() + '/', self.Meta.api_path ) if which == 'base' or (which is None and 'id' not in vars(self)): return base elif (which == 'self' or which is None) and 'id' in vars(self): return urlparse.urljoin(base + '/', str(self.id)) raise NoSuchPathError
def path(self, which=None): """Return the path to the current entity. Return the path to base entities of this entity's type if: * ``which`` is ``'base'``, or * ``which`` is ``None`` and instance attribute ``id`` is unset. Return the path to this exact entity if instance attribute ``id`` is set and: * ``which`` is ``'self'``, or * ``which`` is ``None``. Raise :class:`NoSuchPathError` otherwise. Child classes may choose to extend this method, especially if a child entity offers more than the two URLs supported by default. If extended, then the extending class should check for custom parameters before calling ``super``:: def path(self, which): if which == 'custom': return urlparse.urljoin(...) super(ChildEntity, self).__init__(which) This will allow the extending method to accept a custom parameter without accidentally raising a :class:`NoSuchPathError`. :param str which: Optional. Valid arguments are 'self' and 'base'. :return: A fully qualified URL. :rtype: str :raises robottelo.orm.NoSuchPathError: If no path can be built. """ # (no-member) pylint:disable=E1101 # It is OK that member ``self.Meta.api_path`` is not found. Subclasses # are required to set that attribute if they wish to use this method. # # Beware of leading and trailing slashes: # # urljoin('example.com', 'foo') => 'foo' # urljoin('example.com/', 'foo') => 'example.com/foo' # urljoin('example.com', '/foo') => '/foo' # urljoin('example.com/', '/foo') => '/foo' base = urlparse.urljoin(helpers.get_server_url() + '/', self.Meta.api_path) if which == 'base' or (which is None and 'id' not in vars(self)): return base elif (which == 'self' or which is None) and 'id' in vars(self): return urlparse.urljoin(base + '/', str(self.id)) raise NoSuchPathError
def _poll_task(task_id, poll_rate=None, timeout=None, auth=None): """Implement :meth:`robottelo.entities.ForemanTask.poll`. See :meth:`robottelo.entities.ForemanTask.poll` for a full description of how this method acts. Other methods may also call this method, such as :meth:`robottelo.orm.EntityDeleteMixin.delete`. This function has been placed in this module to keep the import tree sane. This function could also be placed in :mod:`robottelo.api.utils`. However, doing so precludes :mod:`robottelo.api.utils` from importing :mod:`robottelo.entities`, which may be desirable in the future. This function is private because only entity mixins should use this. :class:`robottelo.entities.ForemanTask` is, for obvious reasons, an exception. """ if poll_rate is None: poll_rate = TASK_POLL_RATE if timeout is None: timeout = TASK_TIMEOUT if auth is None: auth = helpers.get_server_credentials() # Implement the timeout. def raise_task_timeout(): """Raise a KeyboardInterrupt exception in the main thread.""" thread.interrupt_main() timer = threading.Timer(timeout, raise_task_timeout) # Poll until the task finishes. The timeout prevents an infinite loop. try: timer.start() path = '{0}/foreman_tasks/api/tasks/{1}'.format( helpers.get_server_url(), task_id ) while True: response = client.get(path, auth=auth, verify=False) response.raise_for_status() task_info = response.json() if task_info['state'] != 'running': return task_info time.sleep(poll_rate) except KeyboardInterrupt: # raise_task_timeout will raise a KeyboardInterrupt when the timeout # expires. Catch the exception and raise TaskTimeout raise TaskTimeout("Timed out polling task {0}".format(task_id)) finally: timer.cancel()
def _poll_task(task_id, poll_rate=None, timeout=None, auth=None): """Implement :meth:`robottelo.entities.ForemanTask.poll`. See :meth:`robottelo.entities.ForemanTask.poll` for a full description of how this method acts. Other methods may also call this method, such as :meth:`robottelo.orm.EntityDeleteMixin.delete`. This function has been placed in this module to keep the import tree sane. This function could also be placed in :mod:`robottelo.api.utils`. However, doing so precludes :mod:`robottelo.api.utils` from importing :mod:`robottelo.entities`, which may be desirable in the future. This function is private because only entity mixins should use this. :class:`robottelo.entities.ForemanTask` is, for obvious reasons, an exception. """ if poll_rate is None: poll_rate = TASK_POLL_RATE if timeout is None: timeout = TASK_TIMEOUT if auth is None: auth = helpers.get_server_credentials() # Implement the timeout. def raise_task_timeout(): """Raise a KeyboardInterrupt exception in the main thread.""" thread.interrupt_main() timer = threading.Timer(timeout, raise_task_timeout) # Poll until the task finishes. The timeout prevents an infinite loop. try: timer.start() path = '{0}/foreman_tasks/api/tasks/{1}'.format( helpers.get_server_url(), task_id) while True: response = client.get(path, auth=auth, verify=False) response.raise_for_status() task_info = response.json() if task_info['state'] != 'running': return task_info time.sleep(poll_rate) except KeyboardInterrupt: # raise_task_timeout will raise a KeyboardInterrupt when the timeout # expires. Catch the exception and raise TaskTimeout raise TaskTimeout("Timed out polling task {0}".format(task_id)) finally: timer.cancel()
def wait_for_server_connection(): success = False attempts = 0 while attempts < 5 and not success: try: r = requests.get(get_server_url(), verify=False, timeout=10) if r.status_code == 200: success = True except socket.error as e: if e.errno == errno.ECONNREFUSED: print "Attempt {} - connection refused! waiting 30s to retry...".format(attempts) sleep(30) # wait for 30 seconds before re-checking attempts += 1 else: raise
def single_delete(cls, uuid, thread_id): """Delete system from subscription""" start = time.time() response = requests.delete(urljoin( get_server_url(), '/katello/api/systems/{0}'.format(uuid)), auth=get_server_credentials(), verify=False) if response.status_code != 204: LOGGER.error('Fail to delete {0} on thread-{1}!'.format( uuid, thread_id)) LOGGER.error(response.content) return 0 LOGGER.info("Delete {0} on thread-{1} successful!".format( uuid, thread_id)) end = time.time() LOGGER.info('real {}s'.format(end - start)) return end - start
def wait_for_server_connection(): success = False attempts = 0 while attempts < 5 and not success: try: r = requests.get(get_server_url(), verify=False, timeout=10) if r.status_code == 200: success = True except socket.error as e: if e.errno == errno.ECONNREFUSED: print "Attempt {} - connection refused! waiting 30s to retry...".format( attempts) sleep(30) # wait for 30 seconds before re-checking attempts += 1 else: raise
def single_delete(cls, uuid, thread_id): """Delete system from subscription""" start = time.time() response = requests.delete( urljoin(get_server_url(), '/katello/api/systems/{0}'.format(uuid)), auth=get_server_credentials(), verify=False ) if response.status_code != 204: LOGGER.error( 'Fail to delete {0} on thread-{1}!'.format(uuid, thread_id)) LOGGER.error(response.content) return 0 LOGGER.info( "Delete {0} on thread-{1} successful!".format(uuid, thread_id)) end = time.time() LOGGER.info('real {}s'.format(end-start)) return end - start
def is_logged(self): """Checks whether user is logged by validating a session cookie""" cookies = dict( (cookie['name'], cookie['value']) for cookie in self.browser.get_cookies() ) # construct the link to the Dashboard web page url_root = get_server_url() + '/dashboard' response = requests.get( url_root, verify=False, allow_redirects=False, cookies=cookies ) response.raise_for_status() return ( response.status_code != 302 or not response.headers['location'].endswith('/login') )
def test_path_exists(self): """@Test: Check whether the path exists. @Feature: Red Hat Subscription Manager @Assert: Issuing an HTTP GET produces an HTTP 200 response with an ``application/json`` content-type, and the response is a list. This test targets bugzilla bug 1112802. """ path = '{0}/rhsm'.format(get_server_url()) response = client.get( path, auth=get_server_credentials(), verify=False, ) self.assertEqual(response.status_code, httplib.OK) self.assertIn('application/json', response.headers['content-type']) self.assertIsInstance(response.json(), list)
def _poll_task(task_id, poll_rate=5, timeout=120, auth=None): """Implement :meth:`robottelo.entities.ForemanTask.poll`. :meth:`robottelo.entities.ForemanTask.poll` calls this function, as does :class:`robottelo.orm.EntityDeleteMixin`. Other mixins which have yet to be implemented, such as ``EntityCreateMixin``, may also call this function. This function has been placed in this module to keep the import tree sane. This function could also be placed in ``robottelo.api.utils``. However, doing so precludes :mod:`robottelo.api.utils` from importing :mod:`robottelo.entities`, which may be desirable in the future. This function is private because only entity mixins should use this. ``ForemanTask`` is, for obvious reasons, an exception. """ if auth is None: auth = helpers.get_server_credentials() # Implement the timeout. def raise_task_timeout(): """Raise :class:`robottelo.orm.TaskTimeout`.""" raise TaskTimeout("Timed out polling task {0}".format(task_id)) timer = threading.Timer(timeout, raise_task_timeout) timer.start() # Poll until the task finishes. The timeout prevents an infinite loop. try: path = '{0}/foreman_tasks/api/tasks/{1}'.format( helpers.get_server_url(), task_id ) while True: response = client.get(path, auth=auth, verify=False) response.raise_for_status() task_info = response.json() if task_info['pending'] is False: return task_info time.sleep(poll_rate) finally: timer.cancel()
def create(self, auth=None): """Create a new entity, plus all of its dependent entities. Create an entity at the path returned by :meth:`Factory._factory_path`. If necessary, recursively create dependent entities. When done, return a dict of information about the newly created entity. :param tuple auth: A ``(username, password)`` pair to use when communicating with the API. If ``None``, the credentials returned by :func:`robottelo.common.helpers.get_server_credentials` are used. :return: Information about the newly created entity. :rtype: dict :raises robottelo.factory.FactoryError: If the server returns an error when attempting to create an entity. """ if auth is None: auth = get_server_credentials() # Create dependent entities and generate values for non-FK fields. values = self.build(auth) # Create the current entity. path = urljoin(get_server_url(), self._factory_path()) response = client.post(path, values, auth=auth, verify=False).json() if 'error' in response.keys() or 'errors' in response.keys(): if 'error' in response.keys(): message = response['error'] else: message = response['errors'] raise FactoryError( 'Error encountered while POSTing to {0}. Error received: {1}' ''.format(path, message) ) # Tell caller about created entity. return response
def get_packages(repository_id): """Return all packages belonging to repository ``repository_id``. :param int repository_id: A repository ID. :return: That repository's packages. :rtype: list :raises robottelo.api.utils.RepositoryPackagesException: If an error occurs while fetching the requested repository's packages. """ path = urljoin( helpers.get_server_url(), 'katello/api/v2/repositories/{0}/packages'.format(repository_id)) response = client.get( path, auth=helpers.get_server_credentials(), verify=False, ).json() if 'errors' in response.keys(): raise RepositoryPackagesException( 'Error received after issuing GET to {0}. Error received: {1}' ''.format(path, response['errors'])) return response['results']
def test_default_v4(self): """Hostname set, scheme and port blank.""" conf.properties['main.server.port'] = '' conf.properties['main.server.scheme'] = '' self.assertEqual(get_server_url(), 'https://example.com')
def test_port(self): """Hostname and port set.""" conf.properties['main.server.port'] = '1234' self.assertEqual(get_server_url(), 'https://example.com:1234')
def test_port_v2(self): """Hostname and port set, scheme blank.""" conf.properties['main.server.port'] = '1234' conf.properties['main.server.scheme'] = '' self.assertEqual(get_server_url(), 'https://example.com:1234')
def setUp(self): """Define commonly-used variables.""" self.path = '{0}/api/v2'.format(helpers.get_server_url())
def test_scheme_v2(self): """Hostname and scheme set, port blank.""" conf.properties['main.server.port'] = '' conf.properties['main.server.scheme'] = 'telnet' self.assertEqual(get_server_url(), 'telnet://example.com')
def test_all(self): """Hostname, scheme and port set.""" conf.properties['main.server.port'] = '1234' conf.properties['main.server.scheme'] = 'telnet' self.assertEqual(get_server_url(), 'telnet://example.com:1234')
def test_default_v1(self): """Hostname set.""" self.assertEqual(get_server_url(), 'https://example.com')