def get_config_values(config_path, section, default='default'): """ Parse ini config file and return a dict of values. The provided section overrides any values in default section. """ values = {} if not os.path.isfile(config_path): raise IpaUtilsException( 'Config file not found: %s' % config_path ) config = configparser.ConfigParser() try: config.read(config_path) except Exception: raise IpaUtilsException( 'Config file format invalid.' ) try: values.update(config.items(default)) except Exception: pass try: values.update(config.items(section)) except Exception: pass return values
def update_history_log(history_log, clear=False, description=None, test_log=None): """ Update the history log file with item. If clear flag is provided the log file is deleted. """ if not test_log and not clear: raise IpaUtilsException('A test log or clear flag must be provided.') if clear: with ignored(OSError): os.remove(history_log) else: history_dir = os.path.dirname(history_log) if not os.path.isdir(history_dir): try: os.makedirs(history_dir) except OSError as error: raise IpaUtilsException('Unable to create directory: %s' % error) with open(history_log, 'a+') as f: # Using append mode creates file if it does not exist if description: description = '"%s"' % description out = '{} {}'.format(test_log, description or '') f.write(out.strip() + '\n')
def get_test_files(test_dirs): """ Walk all test dirs and find all tests and test descriptions. Returns: A tuple containing a dict mapping test names to full path and a dict mapping test descriptions to full path. Raises: IpaUtilsException: If there are multiple test files or test descriptions with the same name. Or, if there is a name overlap with a test file and test description. """ tests = {} descriptions = {} for test_dir in test_dirs: if not os.path.exists(test_dir): continue for root, dirs, files in os.walk(test_dir): test_files = fnmatch.filter(files, 'test_*.py') description_files = fnmatch.filter(files, 'test_*.yaml') for test_file in test_files: path = os.path.join(root, test_file) name, ext = test_file.split('.') if name not in tests: tests[name] = path else: raise IpaUtilsException( 'Duplicate test file name found: %s, %s' % (path, tests.get(name)) ) for description_file in description_files: path = os.path.join(root, description_file) name, ext = description_file.split('.') if name in tests: raise IpaUtilsException( 'Test description name matches test file: %s, %s' % (path, tests.get(name)) ) elif name not in descriptions: descriptions[name] = path else: raise IpaUtilsException( 'Duplicate test description file name found: %s, %s' % (path, descriptions.get(name)) ) return tests, descriptions
def expand_test_files(test_dirs, names): """ Expand the list of test files and test descriptions. The list is split on sync points and duplicates in each set are removed. Returns: List of test files split into sets by sync points. Raises: IpaUtilsException: If names is not a list. """ if not isinstance(names, list): raise IpaUtilsException( 'Names must be a list containing test names' ' and/or test descriptions.' ) tests, descriptions = get_test_files(test_dirs) expanded_names = [] for name in names: if name in descriptions: expanded_names += get_tests_from_description( name, descriptions ) else: expanded_names.append(name) return parse_sync_points(expanded_names, tests)
def generate_public_ssh_key(ssh_private_key_file): """Generate SSH public key from private key file.""" try: with open(ssh_private_key_file, "rb") as key_file: key = key_file.read() except FileNotFoundError: raise IpaUtilsException('SSH private key file: %s cannot be found.' % ssh_private_key_file) try: private_key = serialization.load_pem_private_key( key, password=None, backend=default_backend()) except ValueError: raise IpaUtilsException( 'SSH private key file: %s is not a valid key file.' % ssh_private_key_file) return private_key.public_key().public_bytes( serialization.Encoding.OpenSSH, serialization.PublicFormat.OpenSSH)
def put_file(client, source_file, destination_file): """ Copy file to instance using Paramiko client connection. """ try: sftp_client = client.open_sftp() sftp_client.put(source_file, destination_file) except Exception as error: raise IpaUtilsException( 'Error copying file to instance: {0}.'.format(error)) finally: with ignored(Exception): sftp_client.close()
def get_yaml_config(config_path): """ Load yaml config file and return dictionary. Todo: * This will need refactoring similar to the test search. """ config_path = os.path.expanduser(config_path) if not os.path.isfile(config_path): raise IpaUtilsException('Config file not found: %s' % config_path) with open(config_path, 'r') as f: config = yaml.safe_load(f) return config
def get_public_ssh_key(ssh_private_key_file): """Get SSH public key from private key file.""" pub_key = ssh_private_key_file + '.pub' try: with open(pub_key, "rb") as key_file: key = key_file.read() except FileNotFoundError: raise IpaUtilsException( 'SSH public key file: {key_path} cannot be found.'.format( key_path=pub_key ) ) return key
def get_tests_from_description(name, descriptions, parsed=None): """ Recursively collect all tests in test description. Args: name (str): Yaml test description file name. descriptions (dict): Dict of test description name (key) and absolute file paths (value). parsed (list): List of description paths which have already been parsed to prevent infinte recursion. Returns: A list of expanded test files. """ tests = [] if not parsed: parsed = [] description = descriptions.get(name, None) if not description: raise IpaUtilsException( 'Test description file with name: %s cannot be located.' % name ) if description in parsed: return tests parsed.append(description) test_data = get_yaml_config(description) if 'tests' in test_data: tests += test_data.get('tests') if 'include' in test_data: for description_name in test_data.get('include'): tests += get_tests_from_description( description_name, descriptions, parsed ) return tests
def find_test_file(name, tests): """ Find test file by name, given a list of tests. If a specific test case is appended to test name, split the case and append to path. Raises: IpaUtilsException: If test file not found. """ try: test_name, test_case = name.split('::', 1) except ValueError: test_name, test_case = name, None path = tests.get(test_name, None) if not path: raise IpaUtilsException('Test file with name: %s cannot be found.' % test_name) if test_case: path = ''.join([path, '::', test_case]) return path