def test_smcoperationfailure_missing_msgparts(self, m): m.get('/foo', [{ 'json': { 'message': 'Impossible to store the element test.', 'status': '0' }, 'status_code': 400, 'headers': { 'content-type': 'application/json' } }, { 'json': { 'details': ['Element name test is already used.'], 'status': '0' }, 'status_code': 400, 'headers': { 'content-type': 'application/json' } }]) # Missing detqils key result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('Impossible to store')) # Missing message key result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('Element name test'))
def modify_attribute(self, **kwargs): """ Modify the attribute by key / value pair. Add append_lists=True kwarg if dict leaf is a list and you want to append, default: replace :param dict kwargs: key=value pair to change :param bool append_lists: if change is a list, append or overwrite :raises ElementNotFound: cannot find element specified :raises ModificationFailed, UpdateElementFailed: failure applying change with reason :return: href of the element modified :rtype: str """ if self.data.get('system', False): raise ModificationFailed('Cannot modify system element: %s' % self.name) params = {'href': self.href, 'etag': self.etag} append_lists = kwargs.pop('append_lists', False) merge_dicts(self.data, kwargs, append_lists) params.update(json=self.data) del self.data request = SMCRequest(**params) request.exception = UpdateElementFailed return request.update().href
def test_delete_already_deleted_host(self): # Verify a stale href that was deleted gives expected error Host.create('tyler', '1.1.1.1') host = Host('tyler').href Host('tyler').delete() result = SMCRequest(href=host).delete() self.assertIsNotNone(result.msg)
def testSMCResult_asjson_nodata(self, m): m.get('/foo', headers={'content-type': 'application/json'}, status_code=200) result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 200) self.assertFalse(result.json)
def test401_timeout(self, m): # session.login(url=url, api_key=api_key) m.get('/timeout', headers={'content-type': 'text/plain'}, status_code=401) with self.assertRaises(SMCConnectionError): SMCRequest(href='{}/timeout'.format(url)).read()
def ElementCreator(cls, json, **kwargs): """ Helper method for creating elements. If the created element type is a SubElement class type, provide href value as kwargs since that class type does not have a direct entry point. This is a lazy load that will provide only the meta for the element. Additional attribute access will load the full data. :param Element,SubElement cls: class for creating :param dict json: json payload :param SMCException exception: exception class to override :return: instance of type Element with meta :rtype: Element """ if 'exception' not in kwargs: kwargs.update(exception=CreateElementFailed) href = kwargs.pop('href') if 'href' in kwargs else cls.href result = SMCRequest(href=href, json=json, **kwargs).create() element = cls(name=json.get('name'), type=cls.typeof, href=result.href) if result.user_session.in_atomic_block: result.user_session.transactions.append(element) return element
def test_engine_upload_and_go_online_offline_lock_success(self): # Verify policy upload task = engine.upload(policy=None) #ProgressTask href = task.follower self.assertRegexpMatches(href, r'^http') # Call Wait and get a couple ierations for x in task.wait(timeout=2, max_intervals=1): self.assertIsNotNone(x) d = SMCRequest(href=href).delete() self.assertEqual(204, d.code) # Wait for task to be aborted wait_times = 0 while True: status = element_by_href_as_json(href) if not status.get('in_progress') and \ status.get('last_message').startswith('Operation abort'): # Abort break elif wait_times == 10: print("Aborted after waiting 20 seconds for upload to stop") break else: time.sleep(2) # Should return task 100% as it was cancelled for x in task.wait(timeout=3, max_intervals=1): self.assertEqual(x, 100)
def prepared_request(*exception, **kwargs): # @UnusedVariable """ Prepared request is a wrapper to allow an exception to be thrown to wrap the SMCResult. Exception is optional. If not provided, the SMCResult object is returned, otherwise it is only thrown if SMC reports an error. """ return SMCRequest(**kwargs)
def test_smcoperationfailure_json(self, m): m.get('/foo', headers={'content-type': 'application/json'}, json={'details': 'some error'}, status_code=400) result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('some error'))
def test_smcoperationfailure_nojson(self, m): # Invalid message (headers are json but no json body m.get('/foo', headers={'content-type': 'application/json'}, status_code=400) result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('No valid message'))
def test_update_no_etag(self): # Failed PUT request Host.create('tyler', '1.1.1.1') a = Host('tyler') element = a.data element.update(name='newtyler') result = SMCRequest(href=a.href, json=element).update() self.assertIsNotNone(result.msg) Host('tyler').delete()
def test_smcoperationfailure_notjson(self, m): # With message m.get('/foo', [{ 'text': 'blah blah error', 'status_code': 400 }, { 'status_code': 400 }]) # With text output result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('blah blah')) # Only status code result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue(result.msg.startswith('No message returned'))
def delete(self): """ Delete the element :raises DeleteElementFailed: possible dependencies, record locked, etc :return: None """ request = SMCRequest(href=self.href, headers={'if-match': self.etag}) request.exception = DeleteElementFailed request.delete()
def ElementCreator(cls): """ Helper method for create classmethods. Returns the href if creation is successful """ result = SMCRequest(href=search.element_entry_point(cls.typeof), json=cls.json).create() if result.msg: raise CreateElementFailed(result.msg) return result.href
def testSMCResult_asoctetstream(self, m): m.get('/foo', [{ 'headers': { 'content-type': 'application/octet-stream' }, 'status_code': 200, 'text': 'some text content' }, { 'headers': { 'content-type': 'application/octet-stream' }, 'status_code': 200 }]) result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 200) self.assertTrue(result.content.startswith('some text')) result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 200) self.assertIsNone(result.content)
def ElementFactory(href): """ Factory returns an object of type Element when only the href is provided. """ element = SMCRequest(href=href).read() if element.json: istype = find_type_from_self(element.json.get('link')) typeof = lookup_class(istype) e = typeof(name=element.json.get('name'), href=href, type=istype) e.data = ElementCache(element.json, etag=element.etag) return e
def LoadElement(href, only_etag=False): """ Return an instance of a element as a ElementCache dict used as a cache. :rtype ElementCache """ request = SMCRequest(href=href) request.exception = FetchElementFailed result = request.read() if only_etag: return result.etag return ElementCache(result.json, etag=result.etag)
def fetch_json_by_href(href, params=None): """ Fetch json for element by using href. Params should be key/value pairs. For example {'filter': 'myfilter'} :method: GET :param str href: href of the element :params dict params: optional search query parameters :return: :py:class:`smc.api.web.SMCResult` """ result = SMCRequest(href=href, params=params).read() if result: result.href = href return result
def ElementCreator(cls, json): """ Helper method for create classmethods. Returns the href if creation is successful. This is a lazy load that will provide only the meta for the element. Additional attribute access will load the full data. :return: instance of type Element with meta :rtype: Element """ result = SMCRequest(href=cls.href, json=json).create() if result.msg: raise CreateElementFailed(result.msg) return cls(json.get('name'), type=cls.typeof, href=result.href)
def make_request(self, *exception, **kwargs): raw_result = kwargs.pop("raw_result", False) method = kwargs.pop("method", "read") ex = exception[0] if exception else ActionCommandFailed if "resource" in kwargs: try: kwargs.update(href=self.data.get_link(kwargs.pop("resource"))) except ResourceNotFound as e: raise ex(e) request = SMCRequest(**kwargs) request.exception = ex result = getattr(request, method)() if raw_result: return result return result.json
def test_validwith_messageanddetails(self, m): m.get('/foo', json={ 'message': 'Impossible to store the element test.', 'details': ['Element name test is already used.'], 'status': '0' }, status_code=400, headers={'content-type': 'application/json'}) # Missing detqils key result = SMCRequest(href='{}/foo'.format(url)).read() self.assertEqual(result.code, 400) self.assertTrue( result.msg.startswith( 'Impossible to store the element test. Element name ' 'test is already used'))
def ElementFactory(href, raise_exc=None): """ Factory returns an object of type Element when only the href is provided. :param str href: string href to fetch :param Exception raise_exc: exception to raise if fetch failed """ element = SMCRequest(href=href).read() if element.json: istype = find_type_from_self(element.json.get('link')) typeof = lookup_class(istype) e = typeof(name=element.json.get('name'), href=href, type=istype) e.data = ElementCache(element.json, etag=element.etag) return e if raise_exc and element.msg: raise raise_exc(element.msg)
def test_engine_refresh_policy_success(self): # Verify we get a task returned href = engine.refresh().follower self.assertRegexpMatches(href, r'^http') d = SMCRequest(href=href).delete() self.assertEqual(204, d.code) wait_times = 0 while True: status = element_by_href_as_json(href) if not status.get('in_progress') and \ status.get('last_message').startswith('Operation abort'): # Abort break elif wait_times == 10: print("Aborted after waiting 20 seconds for policy to stop") break else: wait_times += 1 time.sleep(2)
def ElementFactory(href, smcresult=None, raise_exc=None): """ Factory returns an object of type Element when only the href is provided. :param str href: string href to fetch :param SMCResult smcresult: optional SMCResult. If provided, the request fetch will be skipped :param Exception raise_exc: exception to raise if fetch failed """ if smcresult is None: smcresult = SMCRequest(href=href).read() if smcresult.json: cache = ElementCache(smcresult.json, etag=smcresult.etag) typeof = lookup_class(cache.type) instance = typeof(name=cache.get('name'), href=href, type=cache.type) instance.data = cache return instance if raise_exc and smcresult.msg: raise raise_exc(smcresult.msg)
def SubElementCreator(cls, *exception, **kwargs): """ Helper method for creating sub elements. SubElements do not have direct entry points in the SMC API and require a direct href reference. This is a lazy load that will provide only the meta for the element. Additional attribute access will load the full data. :return: instance of type SubElement with meta :rtype: SubElement """ exc = exception[0] if exception else CreateElementFailed if 'href' not in kwargs: raise exc('Cannot create SubElement: %s. Missing the href value' % cls.__name__) result = SMCRequest(**kwargs).create() if result.msg: raise exc(result.msg) name = kwargs.get('json') return cls(name=name.get('name'), type=cls.typeof, href=result.href)
def add_policy(self): """ If a client AMI was specified when building a new VPC, this will add rules to allow inbound access to the AMI. This could be extended to more generically support VPN rules. """ if self.aws_ami_ip: policy = FirewallPolicy(self.firewall_policy) for rule in policy.fw_ipv4_nat_rules.all(): if rule.name == 'aws_client': orig = rule.describe() nat = orig['options']['static_dst_nat'] nat['translated_value']['ip_descriptor'] = self.aws_ami_ip result = SMCRequest(json=orig, href=rule.href, etag=rule.etag).update() if result.msg: logger.error('Error modifying NAT rule: {}'.format(result.msg)) else: logger.info('Success creating NAT rule for AMI client using address: {}' .format(self.aws_ami_ip)) '''
def testTimeoutDuringSession(self, m): m.post('/foo', text=raise_connection_error) req = SMCRequest(href='{}/foo'.format(url), filename=None) self.assertRaises(SMCConnectionError, lambda: req.create())
def update(self, *exception, **kwargs): """ Update the existing element and clear the instance cache. Removing the cache will ensure subsequent calls requiring element attributes will force a new fetch to obtain the latest copy. Calling update() with no args will assume the element has already been modified directly and the data cache will be used to update. You can also override the following attributes: href, etag and json. If json is sent, it is expected to the be a complete payload to satisfy the update. For kwargs, if attribute values are a list, you can pass 'append_lists=True' to add to an existing list, otherwise overwrite (default: overwrite) .. seealso:: To see different ways to utilize this method for updating, see: :ref:`update-elements-label`. :param exception: pass a custom exception to throw if failure :param kwargs: optional kwargs to update request data to server. :raises ModificationFailed: raised if element is tagged as System element :raises UpdateElementFailed: failed to update element with reason :return: href of the element modified :rtype: str """ if self.data.get('system', False): raise ModificationFailed('Cannot modify system element: %s' % self.name) if not exception: exception = UpdateElementFailed else: exception = exception[0] params = {'href': self.href, 'etag': self.etag} if 'href' in kwargs: params.update(href=kwargs.pop('href')) if 'etag' in kwargs: params.update(etag=kwargs.pop('etag')) name = kwargs.get('name', None) json = kwargs.pop('json') if 'json' in kwargs else self.data del self.data # Delete the cache before processing attributes # If kwarg settings are provided AND instance variables, kwargs # will overwrite collected instance attributes with the same name. if kwargs: append_lists = kwargs.pop('append_lists', False) merge_dicts(json, kwargs, append_lists) params.update(json=json) request = SMCRequest(**params) request.exception = exception result = request.update() if name: # Reset instance name self._meta = Meta(name=name, href=self.href, type=self._meta.type) self._name = name return result.href
def bad_json_POST(self): # If customized json is going through and it's invalid, TypeError is # thrown href = search.element_entry_point('host') self.assertRaises( TypeError, lambda: SMCRequest(href=href, json={'ertrte'}).create())
def test_type_error_in_common(self): # Catch TypeError in common. Caused by malformed JSON self.assertRaises( TypeError, lambda: SMCRequest(href=search.element_entry_point('host'), json={'test'}).create())