def new_request(self, method, url, **kwargs): kwargs_copy = kwargs.copy() if 'data' in kwargs: kwargs_copy['data'] = json.loads(kwargs['data']) if 'params' in kwargs and method == 'GET': # query params for GET are handled a bit differently by # tower-cli and python requests as opposed to REST framework APIRequestFactory kwargs_copy.setdefault('data', {}) if isinstance(kwargs['params'], dict): kwargs_copy['data'].update(kwargs['params']) elif isinstance(kwargs['params'], list): for k, v in kwargs['params']: kwargs_copy['data'][k] = v # make request rf = _request(method.lower()) django_response = rf(url, user=request_user, expect=None, **kwargs_copy) # requests library response object is different from the Django response, but they are the same concept # this converts the Django response object into a requests response object for consumption resp = Response() py_data = django_response.data sanitize_dict(py_data) resp._content = bytes(json.dumps(django_response.data), encoding='utf8') resp.status_code = django_response.status_code if request.config.getoption('verbose') > 0: logger.info( '%s %s by %s, code:%s', method, '/api/' + url.split('/api/')[1], request_user.username, resp.status_code ) return resp
def new_request(self, method, url, **kwargs): kwargs_copy = kwargs.copy() if 'data' in kwargs: if isinstance(kwargs['data'], dict): kwargs_copy['data'] = kwargs['data'] elif kwargs['data'] is None: pass elif isinstance(kwargs['data'], str): kwargs_copy['data'] = json.loads(kwargs['data']) else: raise RuntimeError( 'Expected data to be dict or str, got {0}, data: {1}'. format(type(kwargs['data']), kwargs['data'])) if 'params' in kwargs and method == 'GET': # query params for GET are handled a bit differently by # tower-cli and python requests as opposed to REST framework APIRequestFactory if not kwargs_copy.get('data'): kwargs_copy['data'] = {} if isinstance(kwargs['params'], dict): kwargs_copy['data'].update(kwargs['params']) elif isinstance(kwargs['params'], list): for k, v in kwargs['params']: kwargs_copy['data'][k] = v # make request with transaction.atomic(): rf = _request(method.lower()) django_response = rf(url, user=request_user, expect=None, **kwargs_copy) # requests library response object is different from the Django response, but they are the same concept # this converts the Django response object into a requests response object for consumption resp = Response() py_data = django_response.data sanitize_dict(py_data) resp._content = bytes(json.dumps(django_response.data), encoding='utf8') resp.status_code = django_response.status_code resp.headers = { 'X-API-Product-Name': 'AWX', 'X-API-Product-Version': '0.0.1-devel' } if request.config.getoption('verbose') > 0: logger.info('%s %s by %s, code:%s', method, '/api/' + url.split('/api/')[1], request_user.username, resp.status_code) resp.request = PreparedRequest() resp.request.prepare(method=method, url=url) return resp
def new_request(self, method, url, **kwargs): kwargs_copy = kwargs.copy() if 'data' in kwargs: kwargs_copy['data'] = json.loads(kwargs['data']) # make request rf = _request(method.lower()) django_response = rf(url, user=request_user, expect=None, **kwargs_copy) # requests library response object is different from the Django response, but they are the same concept # this converts the Django response object into a requests response object for consumption resp = Response() py_data = django_response.data sanitize_dict(py_data) resp._content = bytes(json.dumps(django_response.data), encoding='utf8') resp.status_code = django_response.status_code return resp
def test_completeness(collection_import, request, admin_user, job_template): option_comparison = {} # Load a list of existing module files from disk base_folder = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) module_directory = os.path.join(base_folder, 'plugins', 'modules') for root, dirs, files in os.walk(module_directory): if root == module_directory: for filename in files: if re.match('^tower_.*.py$', filename): module_name = filename[:-3] option_comparison[module_name] = { 'endpoint': 'N/A', 'api_options': {}, 'module_options': {}, 'module_name': module_name, } resource_module = collection_import( 'plugins.modules.{0}'.format(module_name)) option_comparison[module_name][ 'module_options'] = yaml.load( resource_module.DOCUMENTATION, Loader=yaml.SafeLoader)['options'] endpoint_response = _request('get')( url='/api/v2/', user=admin_user, expect=None, ) for endpoint in endpoint_response.data.keys(): # Module names are singular and endpoints are plural so we need to convert to singular singular_endpoint = '{0}'.format(endpoint) if singular_endpoint.endswith('ies'): singular_endpoint = singular_endpoint[:-3] if singular_endpoint != 'settings' and singular_endpoint.endswith('s'): singular_endpoint = singular_endpoint[:-1] module_name = 'tower_{0}'.format(singular_endpoint) endpoint_url = endpoint_response.data.get(endpoint) # If we don't have a module for this endpoint then we can create an empty one if module_name not in option_comparison: option_comparison[module_name] = {} option_comparison[module_name]['module_name'] = 'N/A' option_comparison[module_name]['module_options'] = {} # Add in our endpoint and an empty api_options option_comparison[module_name]['endpoint'] = endpoint_url option_comparison[module_name]['api_options'] = {} # Get out the endpoint, load and parse its options page options_response = _request('options')( url=endpoint_url, user=admin_user, expect=None, ) if 'POST' in options_response.data.get('actions', {}): option_comparison[module_name][ 'api_options'] = options_response.data.get('actions').get( 'POST') else: read_only_endpoint.append(module_name) # Parse through our data to get string lengths to make a pretty report longest_module_name = 0 longest_option_name = 0 longest_endpoint = 0 for module in option_comparison: if len(option_comparison[module]['module_name']) > longest_module_name: longest_module_name = len(option_comparison[module]['module_name']) if len(option_comparison[module]['endpoint']) > longest_endpoint: longest_endpoint = len(option_comparison[module]['endpoint']) for option in option_comparison[module][ 'api_options'], option_comparison[module]['module_options']: if len(option) > longest_option_name: longest_option_name = len(option) # Print out some headers print("".join([ "End Point", " " * (longest_endpoint - len("End Point")), " | Module Name", " " * (longest_module_name - len("Module Name")), " | Option", " " * (longest_option_name - len("Option")), " | API | Module | State", ])) print("-|-".join([ "-" * longest_endpoint, "-" * longest_module_name, "-" * longest_option_name, "---", "------", "---------------------------------------------", ])) # Print out all of our data for module in sorted(option_comparison): module_data = option_comparison[module] all_param_names = list( set(module_data['api_options']) | set(module_data['module_options'])) for parameter in sorted(all_param_names): print("".join([ module_data['endpoint'], " " * (longest_endpoint - len(module_data['endpoint'])), " | ", module_data['module_name'], " " * (longest_module_name - len(module_data['module_name'])), " | ", parameter, " " * (longest_option_name - len(parameter)), " | ", " X " if (parameter in module_data['api_options']) else ' ', " | ", ' X ' if (parameter in module_data['module_options']) else ' ', " | ", determine_state( module, module_data['endpoint'], module_data['module_name'], parameter, module_data['api_options'][parameter] if (parameter in module_data['api_options']) else None, module_data['module_options'][parameter] if (parameter in module_data['module_options']) else None, ), ])) # This handles cases were we got no params from the options page nor from the modules if len(all_param_names) == 0: print("".join([ module_data['endpoint'], " " * (longest_endpoint - len(module_data['endpoint'])), " | ", module_data['module_name'], " " * (longest_module_name - len(module_data['module_name'])), " | ", "N/A", " " * (longest_option_name - len("N/A")), " | ", ' ', " | ", ' ', " | ", determine_state(module, module_data['endpoint'], module_data['module_name'], 'N/A', None, None), ])) if return_value != 0: raise Exception("One or more failures caused issues")