diff --git a/zenApiLib.py b/zenApiLib.py index f536a6c..abf3a6d 100755 --- a/zenApiLib.py +++ b/zenApiLib.py @@ -5,6 +5,7 @@ from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry from requests.packages.urllib3.exceptions import InsecureRequestWarning +import time # Try to import from python 2 locations, fallback to python3. try: @@ -24,6 +25,9 @@ ) logging.getLogger().setLevel(logging.ERROR) +class SetRouterFailure(Exception): + pass + class zenConnector(): ''' @@ -44,7 +48,6 @@ def __init__(self, section = 'default', cfgFilePath = "", routerName = None, log self.setRouter('IntrospectionRouter') else: self.setRouter(routerName) - def _getConfigDetails(self, section, cfgFilePath): ''' @@ -73,7 +76,6 @@ def _getConfigDetails(self, section, cfgFilePath): configuration = self._sanitizeConfig(configuration) return configuration - def _sanitizeConfig(self, configuration): ''' Ensure 'creds.cfg' configuration file has required fields. @@ -114,7 +116,6 @@ def _sanitizeConfig(self, configuration): configuration['disable_saml'] = disableSaml return configuration - def getRequestSession(self): ''' Setup defaults for using the requests library @@ -134,7 +135,6 @@ def getRequestSession(self): ) return s - def callMethod(self, *method, **payload): ''' Call API directly and returns results directly. For paging API calls @@ -198,7 +198,6 @@ def callMethod(self, *method, **payload): else: return self._validateRawResponse(r) - def pagingMethodCall(self, *method, **payload): ''' Returns an iterative, generator type object of API call results. @@ -241,7 +240,6 @@ def pagingMethodCall(self, *method, **payload): payload['start'] = limitApiCallResults yield rJson - def _validateRawResponse(self, r): ''' todo @@ -279,13 +277,31 @@ def _validateRawResponse(self, r): apiResultsTotal = -1 return rJson - def setRouter(self, routerName): + self.log.info('setRouter: routerName:%s' % (routerName)) + setRouterTryCount = 0 + while setRouterTryCount <= self.config['retries']: + setRouterTryCount += 1 + try: + self._setRouter(routerName) + except SetRouterFailure as ex: + self.log.warn('SetRouter failed: %r', ex) + if setRouterTryCount >= self.config['retries']: + raise Exception( + 'SetRouter: failed and maximum number of retries[{}] ' + 'met.'.format(setRouterTryCount) + ) + else: + time.sleep(setRouterTryCount * 1.5) + else: + # no retry needed + break + + def _setRouter(self, routerName): ''' Set object to specific API router. Basic error checking that specified router actually exisits. ''' - self.log.info('setRouter: routerName:%s' % (routerName)) routers = {} # To query if specified router exists, first need to query all available routers. # Temporarily setting to 'IntrospectionRouter' in order to do so. @@ -297,10 +313,16 @@ def setRouter(self, routerName): if self._routersInfo == {}: apiResp = self.callMethod('getAllRouters') if not apiResp['result']['success']: - raise Exception('getAllRouters call was not sucessful') + raise SetRouterFailure( + 'getAllRouters call was not successful. API response was: ' + '{!r}'.format(apiResp) + ) if not len(apiResp['result']['data']) > 0: - raise Exception('getAllRouters call did not return any results') + raise SetRouterFailure( + 'getAllRouters call did not return any results. API ' + 'response was: {!r}'.format(apiResp) + ) for resp in apiResp['result']['data']: routerKey = resp.get('action', 'unknown') @@ -309,25 +331,32 @@ def setRouter(self, routerName): self._routersInfo = dict(routers) # Check router is valid if not (routerName in self._routersInfo.keys()): - raise Exception("Specified router '%s' is not an option. Available routers are: %s" % ( - routerName, - sorted(self._routersInfo.keys()) + raise Exception( + "Specified router '{}' is not an option. Available routers are: " + "{!r}".fomrat( + routerName, + sorted(self._routersInfo.keys()) )) # Query specified router's available methods if self._routersInfo[routerName]['methods'] == {}: apiResp = self.callMethod('getRouterMethods', router = routerName) if not apiResp['result']['success']: - raise Exception('getRouterMethods call was not sucessful') + raise SetRouterFailure( + 'getRouterMethods call was not successful. API response ' + 'was: {!r}'.format(apiResp) + ) else: if not len(apiResp['result']['data']) > 0: - raise Exception('getRouterMethods call did not return any resilts') + raise SetRouterFailure( + 'getRouterMethods call did not return any results. API ' + 'response was: {!r}'.format(apiResp) + ) self._routersInfo[routerName]['methods'] = dict(apiResp['result']['data']) # Set router self._routerName = routerName self._url = self.config['url'] + self._getEndpoint(routerName) if self.config['disable_saml'] == True: self._url +='?saml=0' - def _getEndpoint(self, routerName): '''