def find_children(playbook, playbook_dir): if not os.path.exists(playbook[0]): return [] if playbook[1] == 'role': playbook_ds = {'roles': [{'role': playbook[0]}]} else: try: playbook_ds = parse_yaml_from_file(playbook[0]) except AnsibleError as e: raise SystemExit(str(e)) results = [] basedir = os.path.dirname(playbook[0]) items = _playbook_items(playbook_ds) for item in items: for child in play_children(basedir, item, playbook[1], playbook_dir): if "$" in child['path'] or "{{" in child['path']: continue valid_tokens = list() for token in split_args(child['path']): if '=' in token: break valid_tokens.append(token) path = ' '.join(valid_tokens) results.append({ 'path': path_dwim(basedir, path), 'type': child['type'] }) return results
def _munge_include(self, ds, new_ds, k, v): ''' Splits the include line up into filename and parameters ''' # The include line must include at least one item, which is the filename # to include. Anything after that should be regarded as a parameter to the include items = split_args(v) if len(items) == 0: raise AnsibleParserError( "include statements must specify the file name to include", obj=ds) else: # FIXME/TODO: validate that items[0] is a file, which also # exists and is readable new_ds['include'] = items[0] if len(items) > 1: # rejoin the parameter portion of the arguments and # then use parse_kv() to get a dict of params back params = parse_kv(" ".join(items[1:])) if 'vars' in new_ds: # FIXME: see fixme above regarding merging vars raise AnsibleParserError( "include parameters cannot be mixed with 'vars' entries for include statements", obj=ds) new_ds['vars'] = params
def get_vars(self, args): """Updates variables based on given arguments from CLI.""" variables = {} args_split = split_args(args) for arg in args_split: variables.update(parse_kv(arg)) return variables
def find_children(playbook: Tuple[str, str], playbook_dir: str) -> List: if not os.path.exists(playbook[0]): return [] _set_collections_basedir(playbook_dir or '.') add_all_plugin_dirs(playbook_dir or '.') if playbook[1] == 'role': playbook_ds = {'roles': [{'role': playbook[0]}]} else: try: playbook_ds = parse_yaml_from_file(playbook[0]) except AnsibleError as e: raise SystemExit(str(e)) results = [] basedir = os.path.dirname(playbook[0]) items = _playbook_items(playbook_ds) for item in items: for child in _rebind_match_filename(playbook[0], play_children)(basedir, item, playbook[1], playbook_dir): if "$" in child['path'] or "{{" in child['path']: continue valid_tokens = list() for token in split_args(child['path']): if '=' in token: break valid_tokens.append(token) path = ' '.join(valid_tokens) results.append({ 'path': path_dwim(basedir, path), 'type': child['type'] }) return results
def _preprocess_import(self, ds, new_ds, k, v): ''' Splits the playbook import line up into filename and parameters ''' if v is None: raise AnsibleParserError("playbook import parameter is missing", obj=ds) elif not isinstance(v, string_types): raise AnsibleParserError("playbook import parameter must be a string indicating a file path, got %s instead" % type(v), obj=ds) # The import_playbook line must include at least one item, which is the filename # to import. Anything after that should be regarded as a parameter to the import items = split_args(v) if len(items) == 0: raise AnsibleParserError("import_playbook statements must specify the file name to import", obj=ds) else: new_ds['import_playbook'] = items[0].strip() if len(items) > 1: display.deprecated("Additional parameters in import_playbook statements are deprecated. " "Use 'vars' instead. See 'import_playbook' documentation for examples.", version='2.14') # rejoin the parameter portion of the arguments and # then use parse_kv() to get a dict of params back params = parse_kv(" ".join(items[1:])) if 'tags' in params: new_ds['tags'] = params.pop('tags') if 'vars' in new_ds: raise AnsibleParserError("import_playbook parameters cannot be mixed with 'vars' entries for import statements", obj=ds) new_ds['vars'] = params
def _preprocess_include(self, ds, new_ds, k, v): ''' Splits the include line up into filename and parameters ''' # The include line must include at least one item, which is the filename # to include. Anything after that should be regarded as a parameter to the include items = split_args(v) if len(items) == 0: raise AnsibleParserError( "include statements must specify the file name to include", obj=ds) else: new_ds['include'] = items[0] if len(items) > 1: # rejoin the parameter portion of the arguments and # then use parse_kv() to get a dict of params back params = parse_kv(" ".join(items[1:])) if 'tags' in params: new_ds['tags'] = params.pop('tags') if 'vars' in new_ds: raise AnsibleParserError( "include parameters cannot be mixed with 'vars' entries for include statements", obj=ds) new_ds['vars'] = params
def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) try: # Test splitter module args = splitter.split_args(fdp.ConsumeString(50)) splitter.join_args(args) # Test quoting module quoting.is_quoted(fdp.ConsumeString(10)) quoting.unquote(fdp.ConsumeString(10)) except (AnsibleError, AnsibleParserError) as e: pass
def _split_module_string(self, module_string): ''' when module names are expressed like: action: copy src=a dest=b the first part of the string is the name of the module and the rest are strings pertaining to the arguments. ''' tokens = split_args(module_string) if len(tokens) > 1: return (tokens[0], " ".join(tokens[1:])) else: return (tokens[0], "")
def find_children(lintable: Lintable) -> List[Lintable]: # noqa: C901 if not lintable.path.exists(): return [] playbook_dir = str(lintable.path.parent) _set_collections_basedir(playbook_dir or os.path.abspath('.')) add_all_plugin_dirs(playbook_dir or '.') if lintable.kind == 'role': playbook_ds = AnsibleMapping({'roles': [{'role': str(lintable.path)}]}) elif lintable.kind not in ("playbook", "tasks"): return [] else: try: playbook_ds = parse_yaml_from_file(str(lintable.path)) except AnsibleError as e: raise SystemExit(str(e)) results = [] basedir = os.path.dirname(str(lintable.path)) # playbook_ds can be an AnsibleUnicode string, which we consider invalid if isinstance(playbook_ds, str): raise MatchError(filename=str(lintable.path), rule=LoadingFailureRule()) for item in _playbook_items(playbook_ds): # if lintable.kind not in ["playbook"]: # continue for child in play_children(basedir, item, lintable.kind, playbook_dir): # We avoid processing parametrized children path_str = str(child.path) if "$" in path_str or "{{" in path_str: continue # Repair incorrect paths obtained when old syntax was used, like: # - include: simpletask.yml tags=nginx valid_tokens = list() for token in split_args(path_str): if '=' in token: break valid_tokens.append(token) path = ' '.join(valid_tokens) if path != path_str: child.path = Path(path) child.name = child.path.name results.append(child) return results
def _preprocess_include(self, ds, new_ds, k, v): ''' Splits the include line up into filename and parameters ''' # The include line must include at least one item, which is the filename # to include. Anything after that should be regarded as a parameter to the include items = split_args(v) if len(items) == 0: raise AnsibleParserError("include statements must specify the file name to include", obj=ds) else: new_ds['include'] = items[0] if len(items) > 1: # rejoin the parameter portion of the arguments and # then use parse_kv() to get a dict of params back params = parse_kv(" ".join(items[1:])) if 'tags' in params: new_ds['tags'] = params.pop('tags') if 'vars' in new_ds: raise AnsibleParserError("include parameters cannot be mixed with 'vars' entries for include statements", obj=ds) new_ds['vars'] = params
def find_children(playbook: Tuple[str, str], playbook_dir: str) -> List[Lintable]: if not os.path.exists(playbook[0]): return [] _set_collections_basedir(playbook_dir or os.path.abspath('.')) add_all_plugin_dirs(playbook_dir or '.') if playbook[1] == 'role': playbook_ds = {'roles': [{'role': playbook[0]}]} else: try: playbook_ds = parse_yaml_from_file(playbook[0]) except AnsibleError as e: raise SystemExit(str(e)) results = [] basedir = os.path.dirname(playbook[0]) # playbook_ds can be an AnsibleUnicode string, which we consider invalid if isinstance(playbook_ds, str): raise MatchError(filename=playbook[0], rule=LoadingFailureRule) items = _playbook_items(playbook_ds) for item in items: for child in play_children(basedir, item, playbook[1], playbook_dir): # We avoid processing parametrized children path_str = str(child.path) if "$" in path_str or "{{" in path_str: continue # Repair incorrect paths obtained when old syntax was used, like: # - include: simpletask.yml tags=nginx valid_tokens = list() for token in split_args(path_str): if '=' in token: break valid_tokens.append(token) path = ' '.join(valid_tokens) if path != path_str: child.path = Path(path) child.name = child.path.name results.append(child) return results
def _munge_include(self, ds, new_ds, k, v): ''' Splits the include line up into filename and parameters ''' # The include line must include at least one item, which is the filename # to include. Anything after that should be regarded as a parameter to the include items = split_args(v) if len(items) == 0: raise AnsibleParserError("include statements must specify the file name to include", obj=ds) else: # FIXME/TODO: validate that items[0] is a file, which also # exists and is readable new_ds['include'] = items[0] if len(items) > 1: # rejoin the parameter portion of the arguments and # then use parse_kv() to get a dict of params back params = parse_kv(" ".join(items[1:])) if 'vars' in new_ds: # FIXME: see fixme above regarding merging vars raise AnsibleParserError("include parameters cannot be mixed with 'vars' entries for include statements", obj=ds) new_ds['vars'] = params
def _preprocess_import(self, ds, new_ds, k, v): ''' Splits the playbook import line up into filename and parameters ''' if v is None: raise AnsibleParserError("playbook import parameter is missing", obj=ds) elif not isinstance(v, string_types): raise AnsibleParserError( "playbook import parameter must be a string indicating a file path, got %s instead" % type(v), obj=ds) # The import_playbook line must include at least one item, which is the filename # to import. Anything after that should be regarded as a parameter to the import items = split_args(v) if len(items) == 0: raise AnsibleParserError( "import_playbook statements must specify the file name to import", obj=ds) new_ds['import_playbook'] = items[0].strip()
def build_filters(filters): """ This will build the filters to be handed to NetBox endpoint call if they exist. Args: filters (str): String of filters to parse. Returns: result (list): List of dictionaries to filter by. """ filter = {} args_split = split_args(filters) args = [parse_kv(x) for x in args_split] for arg in args: for k, v in arg.items(): if k not in filter: filter[k] = list() filter[k].append(v) else: filter[k].append(v) return filter
def test_split_args(args, expected): assert split_args(args) == expected
def run(self, terms, variables=None, **kwargs): netbox_api_token = kwargs.get("token") netbox_api_endpoint = kwargs.get("api_endpoint") netbox_ssl_verify = kwargs.get("validate_certs", True) netbox_private_key_file = kwargs.get("key_file") netbox_api_filter = kwargs.get("api_filter") netbox_raw_return = kwargs.get("raw_data") if not isinstance(terms, list): terms = [terms] try: session = requests.Session() session.verify = netbox_ssl_verify netbox = pynetbox.api( netbox_api_endpoint, token=netbox_api_token if netbox_api_token else None, private_key_file=netbox_private_key_file, ) netbox.http_session = session except FileNotFoundError: raise AnsibleError( "%s cannot be found. Please make sure file exists." % netbox_private_key_file) results = [] for term in terms: try: endpoint = get_endpoint(netbox, term) except KeyError: raise AnsibleError( "Unrecognised term %s. Check documentation" % term) Display().vvvv( u"Netbox lookup for %s to %s using token %s filter %s" % (term, netbox_api_endpoint, netbox_api_token, netbox_api_filter)) if netbox_api_filter: args_split = split_args(netbox_api_filter) args = [parse_kv(x) for x in args_split] filter = {} for arg in args: for k, v in arg.items(): if k not in filter: filter[k] = list() filter[k].append(v) else: filter[k].append(v) Display().vvvv("filter is %s" % filter) for res in endpoint.filter(**filter): Display().vvvvv(pformat(dict(res))) if netbox_raw_return: results.append(dict(res)) else: key = dict(res)["id"] result = {key: dict(res)} results.extend(self._flatten_hash_to_list(result)) else: for res in endpoint.all(): Display().vvvvv(pformat(dict(res))) if netbox_raw_return: results.append(dict(res)) else: key = dict(res)["id"] result = {key: dict(res)} results.extend(self._flatten_hash_to_list(result)) return results
def check_split_args(self, args, expected): tools.eq_(split_args(args), expected)