def load_json_file(self, json_file): """Open file as read, load json, returns dict.""" self.called_tools.append('load_json_file') try: with open(json_file, 'r') as file: dict_result = json.load(file) except FileNotFoundError as error: self.safe_create_folder(CONSTANTS.CONF_FOLDER) raise RbkcliException.ToolsError(error) except json.decoder.JSONDecodeError as error: raise RbkcliException.ToolsError(error) return dict_result
def load_conf_file(self, file='', conf_dict=None): """Load configuration data from json file.""" self.called_tools.append('load_conf_file') if conf_dict is None: conf_dict = {} try: if file == '': file = CONSTANTS.CONF_FOLDER + '/rbkcli.conf' msg = '%s [%s]' % ('IOTools # Successfully loaded configuration' ' file: ', file) if conf_dict == {} and self.conf_dict == {}: self.conf_dict = self.load_json_file(file) self.logger.debug(msg) elif isinstance(conf_dict, dict) and self.conf_dict == {}: self.conf_dict = conf_dict self.logger.debug(msg) else: msg = 'IOTools # Configuration file already loaded.' self.logger.debug(msg) CONSTANTS.CONF_DICT = self.conf_dict except RbkcliException.ToolsError: try: self.create_vanila_conf() self.load_conf_file() except RbkcliException.ToolsError: msg = 'Unable to load configuration file' self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg) return self.conf_dict
def _create_auth_header(self): """Create the auth header based on auth type (user/token).""" user_agent = "RubrikRbkcli--{}--{}".format(self.rbkcli_version, self.python_version) try: auth = 'Bearer ' + self.auth.token self.auth_prpt.type_ = 'token' if self.auth_prpt.primary_exception != '': raise RbkcliException.ToolsError( self.auth_prpt.primary_exception) except KeyError as bad_key: msg = ('Authorization key not found ' + str(bad_key)) auth = self._create_username_header(msg) # Fix or cleanup needed. except AttributeError as bad_key: msg = ('Authorization key not found ' + str(bad_key)) auth = self._create_username_header(msg) # Until here except RbkcliException.ToolsError as error: auth = self._create_username_header(error) self.auth_prpt.header = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'User-Agent': user_agent, 'Authorization': auth, }
def _dict_list_table(self, dict_): """Convert dict to listed table.""" header = ['key', 'value'] key_row = [] value_row = [] for key, value in dict_.items(): key_row.append(key) value_row.append(str(value)) body = [key_row, value_row] summary = 'Total amount of objects' table = DynaTable(header, body, summary=summary) table_str = '' try: table_lst = table.assemble_table() except IndexError as error: msg = 'No results returned, canno\'t create table...' self.rbkcli_logger.error('DynamicTableError # ' + msg) raise RbkcliException.DynaTableError(msg + '\n') for line in table_lst: table_str = table_str + line + '\n' return table_str
def load_env_auth(self): """Load authentication data from environment variables.""" self.called_tools.append('load_env_auth') try: self.auth.server = os.environ['rubrik_cdm_node_ip'] self.auth.username = os.environ['rubrik_cdm_username'] self.auth.password = os.environ['rubrik_cdm_password'] self.auth.token = os.environ['rubrik_cdm_token'] except KeyError as bad_key: if str(bad_key) != "\'rubrik_cdm_token\'" and str( bad_key) != "\'RUBRIK_CDM_TOKEN\'": msg = '%s%s%s' % ('Unable to load environmental variable for' ' authentication: ', bad_key, '. Are they defined?') self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg) else: # Log successful actions keys = '' for line in self.auth.keys(): keys = keys + ',' + line msg = '%s [%s]' % ('IOTools # Successfully loaded' ' environmental vars', keys.strip(',')) self.logger.debug(msg) return self.auth
def convert_to_html(self): """Convert json to table.""" self.filled_worked = self.selected_data body = [] for head in self.final_fields_order: row = [] if isinstance(self.filled_worked, dict): if 'data' in self.filled_worked.keys(): self.filled_worked = self.filled_worked[data] for objt in self.filled_worked: try: line = objt[head] except Exception: line = 'N/E' line = str(line) row.append(line) else: try: line = self.filled_worked[head] line = str(line) except KeyError: line = 'N/E' row.append(line) elif isinstance(self.filled_worked, list): for objt in self.filled_worked: try: line = objt[head] except Exception: line = 'N/E' line = str(line) row.append(line) body.append(row) headers = self.final_fields_order summary = '' if body: summary = '**Total amount of objects [%s]' % str(len(body[0])) cmd = '%s %s %s' % (self.req['version'], self.req['endpoint_matched'], self.req['method']) table = html_table.Tabelfier(command=cmd, title='rbkcli command report', header=headers, columns=body, summary=summary) try: table_str = table.assemble() except IndexError as error: msg = 'No results returned, canno\'t create table...' self.rbkcli_logger.error('DynamicTableError # ' + msg) raise RbkcliException.DynaTableError(msg + '\n') return table_str
def _verify_api_version(self, version): """Verify the provided API version.""" if version not in CONSTANTS.SUPPORTED_API_VERSIONS: msg = str('API version [' + version + '] does not match any ' 'accepted version.') error = 'ApiHandlerError # ' + msg self.local_tools.logger.error(msg) raise RbkcliException.ApiHandlerError(error)
def load_yaml_file(self, yaml_file): """Open file as read, load yaml, returns dict.""" self.called_tools.append('load_yaml_file') try: with open(yaml_file, 'r') as file: dict_result = yaml.safe_load(file.read()) except FileNotFoundError as error: raise RbkcliException.ToolsError(error) return dict_result
def convert_to_table(self): """Convert json to table.""" self.filled_worked = self.selected_data body = [] for head in self.final_fields_order: row = [] if isinstance(self.filled_worked, dict): if 'data' in self.filled_worked.keys(): self.filled_worked = self.filled_worked[data] for objt in self.filled_worked: try: line = objt[head] except Exception: line = 'N/E' line = str(line) row.append(line) else: try: line = self.filled_worked[head] line = str(line) except KeyError: line = 'N/E' row.append(line) elif isinstance(self.filled_worked, list): for objt in self.filled_worked: try: line = objt[head] except Exception: line = 'N/E' line = str(line) row.append(line) body.append(row) headers = self.final_fields_order summary = 'Total amount of objects' table = DynaTable(headers, body, summary=summary) table_str = '' try: table_lst = table.assemble_table() except IndexError as error: msg = 'No results returned, canno\'t create table...' self.rbkcli_logger.error('DynamicTableError # ' + msg) raise RbkcliException.DynaTableError(msg + '\n') for line in table_lst: table_str = table_str + line + '\n' return table_str
def demand_json(self, method, endpoint, data=None): """Call demand method and only return json data.""" try: self.demand(method, endpoint, data) json_data = json.loads(self.api_result.text) except json.decoder.JSONDecodeError as error: msg = '%s %s "%s"' % ('Invalid json data received.', str(error), self.api_result.text) self.logger.error('ApiRequesterError # ' + msg) raise RbkcliException.ApiRequesterError(msg) return json.dumps(json_data, indent=2, sort_keys=True)
def load_auth_key(self, key): """Load key by key confirming if consistency is kept.""" try: self.auth[key] = self.auth_dict[key] except KeyError as bad_key: if str(bad_key) == "\'token\'": if ('username' not in self.auth_dict.keys() and 'password' not in self.auth_dict.keys()): msg = '%s%s%s' % ('Unable to load authentication data from' ' configuration file: ', bad_key, '. Are all keys defined correctly?') self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg) elif (str(bad_key) != "\'password\'" or str(bad_key) != "\'username\'"): msg = '%s%s%s' % ('Unable to load authentication data from ' 'configuration file: ', bad_key, '. Are all keys defined correctly?') self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg)
def download_file(self, url): """Download file from provided url.""" self.called_tools.append('download_file') pool = urllib3.PoolManager(cert_reqs='CERT_NONE') try: with pool.request('GET', url, preload_content=False) as file: content = file.read() if content == b'Route not defined.': error = str('Wrong or nonexistent URL [' + url + '], route is ' 'not defined') msg = 'IOToolsError # ' + error self.logger.error(msg) raise RbkcliException.ToolsError(error) else: msg = str('IOTools # Successfully downloaded file [%s]' % url) self.logger.debug(msg) except urllib3.exceptions.MaxRetryError as error: msg = 'IOToolsError # ' + str(error) self.logger.error(msg) raise RbkcliException.ToolsError(str(error)) return content
def load_auth_file(self): """Load authentication data from json file.""" self.called_tools.append('load_auth_file') file = 'rbkcli.conf' try: if self.conf_dict == {}: self.load_conf_file() file = self.conf_dict['config']['credentialsFile']['value'] file = CONSTANTS.CONF_FOLDER + '/' + file self.auth_dict = self.load_json_file(file) except RbkcliException.ToolsError: msg = 'Unable to load auth file, [' + file + ']' self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg)
def demand(self, method, endpoint, data=None, params=None): """Perform API request with provided data.""" self._create_url(endpoint) self._create_auth_header() try: self.api_result = requests.request(method, self.url, params=params, data=data, headers=self.auth_prpt.header, verify=self.VERIFICATION) self._validate_token_auth(method, endpoint, data={}, params={}) except requests.exceptions.ConnectionError as error: self.logger.error('ApiRequesterError # ' + str(error)) raise RbkcliException.ApiRequesterError(str(error)) except requests.exceptions.InvalidURL as error: self.logger.print_error('ApiRequesterError # ' + str(error)) raise RbkcliException.ApiRequesterError(str(error)) return self.api_result
def _get_rows_size(headers_calc, rows_calc): """ Get the size row should be. Joins all values in one list and gets the maximum size, of all values per row. """ rows_size = [] for i in enumerate(headers_calc): try: rows_calc[i[0]].append(headers_calc[i[0]]) rows_size.append(len(max(rows_calc[i[0]], key=len))) rows_calc[i[0]].remove(headers_calc[i[0]]) except IndexError: raise RbkcliException.DynaTableError('Incorrect number of ' 'rows provided') return rows_size
def _resolve_target(self, target_name): """Resolve target fqdn to IP.""" # Split port and fqdn if ':' in target_name: target_name = target_name.split(':') target_ip = target_name[0] port = ':' + target_name[1] else: port = '' target_ip = target_name try: target_ip = str(socket.gethostbyname(target_ip)) except socket.gaierror: msg = 'Unable to resolve FQDN [%s].' % target_ip self.logger.error('ToolsError # ' + msg) raise RbkcliException.ToolsError(msg) return target_ip + port
def _execute(self, args_dict, arg_list, operation): try: return RBK.cli_execute(args_dict, arg_list, operation) except RbkcliException.ApiRequesterError as error: raise RbkcliException('ApiRequester # ' + str(error)) except RbkcliException.DynaTableError as error: raise RbkcliException('DynamicTable # ' + str(error)) except RbkcliException.ToolsError as error: raise RbkcliException('IOTools # ' + str(error)) except RbkcliException.LoggerError as error: raise RbkcliException('Logger # ' + str(error)) except RbkcliException.ClusterError as error: raise RbkcliException('ApiTarget # ' + str(error)) except RbkcliException.ApiHandlerError as error: raise RbkcliException('ApiHandler # ' + str(error)) except RbkcliException.ScriptError as error: raise RbkcliException('Scripts # ' + str(error)) except RbkcliException.RbkcliError as error: operation.error(str(error)) except KeyboardInterrupt: raise RbkcliException('\nUserError # Operation Aborted!\n')
def api_requester(self, *args, **kwargs): """Instantiate requester and request API.""" method, endpoint = args endpoint_key = kwargs['endpoint_key'] data = kwargs['data'] params = kwargs['params'] if self.focus_list != [] and endpoint_key not in self.focus_list: msg = str('Requested endpoint [' + endpoint_key + '] not found on' ' authorized endpoints list.') raise RbkcliException.ApiHandlerError(str(msg)) endpoint = '/%s/%s' % (self.version, endpoint) api_rs = ApiRequester(self.local_tools.logger, self.local_tools.user_profile, auth=self.local_tools.auth).demand(method, endpoint, data=data, params=params) return api_rs
def create_yaml_file(self, yml_dict, yml_file): """Open file as write, dump yaml dict to file.""" self.called_tools.append('create_yaml_file') try: with open(yml_file, 'w') as file: yaml.dump(yml_dict, file, default_flow_style=False) self.logger.debug('File created successfully: ' + yml_file) return True except FileNotFoundError as error: error = str(error) + '\n' msg = 'Exception is ' + error self.logger.error('IOToolsError # ' + msg) return False except Exception as error: error = str(error) + '\n' msg = 'Exception is ' + error self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(error)
def create_json_file(self, json_dict, json_file): """Open file as write, dump json dict to file.""" self.called_tools.append('create_json_file') try: with open(json_file, 'w') as file: file.write(json.dumps(json_dict, indent=2, sort_keys=True)) self.logger.debug('IOTools # File created successfully: ' + json_file) return True except FileNotFoundError as error: error = str(error) + '\n' msg = 'Exception is ' + error self.logger.error('IOToolsError # ' + msg) return False except Exception as error: error = str(error) + '\n' msg = 'Exception is ' + str(error) self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(error)
def _create_username_header(self, msg): """Create the username authentication header for API request.""" self.logger.warning('ApiRequester # ' + msg) try: credentials = ('%s:%s' % (self.auth.username, self.auth.password)) # Python 2 compatibility try: base64bytes = base64.encodebytes(credentials.encode('utf-8')) except AttributeError: base64bytes = base64.b64encode(credentials.encode('utf-8')) auth = 'Basic ' + base64bytes.decode('utf-8').replace('\n', '') self.auth_prpt.type_ = 'username' except KeyError as bad_key: msg = ('%s%s%s.' % (self.auth_prpt.primary_exception, ' Expected authorization key not found ', str(bad_key))) msg = msg.strip(' ') self.logger.error('%s%s' % ('ApiRequesterError # ', msg)) raise RbkcliException.ApiRequesterError(msg) return auth
def natural_simple_dictstr(natural_str): """Convert natural values into simple dictionary.""" simple_dictstr = [] if isinstance(natural_str, list): natural_str = natural_str[0] natural_str = natural_str.split(',') for item in natural_str: try: key, value = item.split('=') if value[0] == '[' and value[-1] == ']': value = value[1:-1] simple_dictstr.append('"%s": ["%s"]' % (key, value)) else: simple_dictstr.append('"%s": "%s"' % (key, value)) except ValueError as e: raise RbkcliException.ToolsError('jsops error: ' + str(e) + '\n') return str('{%s}' % ', '.join(simple_dictstr))
def load_file_auth(self): """Load authentication data from json file.""" self.called_tools.append('load_file_auth') if self.conf_dict['config']['useCredentialsFile']['value'] == 'False': msg = 'CredentialsFile is disable, unable to read from file.' raise RbkcliException.ToolsError(msg) self.load_auth_file() auth_keys = ['server', 'token', 'username', 'password'] for key in auth_keys: self.load_auth_key(key) # Log successful actions keys = '' for line in self.auth.keys(): keys = keys + ',' + line msg = '%s [%s]' % ('IOTools # Successfully loaded file auth data', keys.strip(',')) self.logger.debug(msg) return self.auth
def _validate_token_auth(self, method, endpoint, data, params): """Validate last token authentication.""" error_msg = 'The supplied authentication is invalid' error_msg2 = '"message":"Incorrect username/password"' if (self.api_result.text == error_msg and self.auth_prpt.type_ == 'token'): error_msg = 'The supplied TOKEN authentication is invalid.' self.auth_prpt.primary_exception = error_msg error_msg = '%s %s' % (error_msg, 'Attempting to use secondary' ' auth type (username/password).') self.logger.warning('ApiRequester # ' + error_msg) self.demand(method, endpoint, data, params) elif (error_msg2 in self.api_result.text and self.auth_prpt.type_ == 'username'): error_msg = 'The supplied authentication is invalid' self.logger.error('ApiRequester # ' + error_msg) error_msg = error_msg + '.\n' raise RbkcliException.ApiRequesterError(error_msg) else: # Log successful actions msg = '%s [%s:%s]' % ('ApiRequester # Successfully requested API', method, self.url) self.logger.debug(msg)
def create_vanila_conf(self): """Create a default configuration file.""" self.called_tools.append('create_vanila_conf') conf_dict = { "config": { "storeToken": { "value": "False", "description": str("Caches the last successful token " "with environment data.") }, "logLevel": { "value": "debug", "description": str("Verbosity of the logs written to the" " file logs/rbkcli.log.") }, "useCredentialsFile": { "value": "False", "description": str("Tries to load credentials from auth" " file before looking for env vars.") }, "credentialsFile": { "value": "target.conf", "description": str("File where to load credentials from, " "before looking for env vars.") }, "whiteList": { "description": "", "value": [ 'v1:/session:post:NA', 'internal:/report/{id}/table:post:NA', 'internal:/managed_volume/{id}/begin_snapshot:post:NA', 'internal:/managed_volume/{id}/end_snapshot:post:NA', 'internal:/support/support_bundle:post:NA', 'rbkcli:/cmdlet/profile:get:NA', 'rbkcli:/cmdlet/profile:post:NA', 'rbkcli:/cmdlet/sync:post:NA', 'rbkcli:/cmdlet:delete:NA', 'rbkcli:/cmdlet:get:NA', 'rbkcli:/cmdlet:post:NA', 'rbkcli:/commands:get:NA', 'rbkcli:/jsonfy:get:NA', 'rbkcli:/script/sync:post:NA', 'rbkcli:/script:get:NA', 'scripts:/log/bundle:post:NA' ] }, "blackList": { "description": "", "value": [] }, "userProfile": { "description": str("String value which can be admin or " "support. A profile is a set of API" " endpoints that is available in the" " command line."), "value": "admin" } } } file = CONSTANTS.CONF_FOLDER + '/rbkcli.conf' try: self.safe_create_folder(CONSTANTS.CONF_FOLDER) self.create_json_file(conf_dict, file) msg = 'Successfully created new configuration file' self.logger.debug('IOTools # ' + msg) except Exception: msg = 'Unable to create new configuration file' self.logger.error('IOToolsError # ' + msg) raise RbkcliException.ToolsError(msg)