def _perform_mockings() -> None: """Mock modules and roles.""" for role_name in options.mock_roles: if re.match(r"\w+\.\w+\.\w+", role_name): namespace, collection, role_dir = role_name.split(".") path = f".cache/collections/ansible_collections/{ namespace }/{ collection }/roles/{ role_dir }/" else: path = f".cache/roles/{role_name}" os.makedirs(path, exist_ok=True) if options.mock_modules: for module_name in options.mock_modules: _make_module_stub(module_name) # if inside a collection repo, symlink it to simulate its installed state if not os.path.exists("galaxy.yml"): return yaml = yaml_from_file("galaxy.yml") if not yaml: # ignore empty galaxy.yml file return namespace = yaml.get('namespace', None) collection = yaml.get('name', None) if not namespace or not collection: return p = pathlib.Path( f"{options.project_dir}/.cache/collections/ansible_collections/{ namespace }" ) p.mkdir(parents=True, exist_ok=True) link_path = p / collection if not link_path.exists(): link_path.symlink_to( pathlib.Path("../../../..", target_is_directory=True))
def _install_galaxy_role() -> None: """Detect standalone galaxy role and installs it.""" if not os.path.exists("meta/main.yml"): return yaml = yaml_from_file("meta/main.yml") if 'galaxy_info' not in yaml: return fqrn = _get_role_fqrn(yaml['galaxy_info']) if 'role-name' not in options.skip_list: if not re.match(r"[a-z0-9][a-z0-9_]+\.[a-z][a-z0-9_]+$", fqrn): msg = ( """\ Computed fully qualified role name of %s does not follow current galaxy requirements. Please edit meta/main.yml and assure we can correctly determine full role name: galaxy_info: role_name: my_name # if absent directory name hosting role is used instead namespace: my_galaxy_namespace # if absent, author is used instead Namespace: https://galaxy.ansible.com/docs/contributing/namespaces.html#galaxy-namespace-limitations Role: https://galaxy.ansible.com/docs/contributing/creating_role.html#role-names As an alternative, you can add 'role-name' to either skip_list or warn_list. """ % fqrn ) if 'role-name' in options.warn_list: _logger.warning(msg) else: _logger.error(msg) sys.exit(INVALID_PREREQUISITES_RC) else: # when 'role-name' is in skip_list, we stick to plain role names if 'role_name' in yaml['galaxy_info']: role_namespace = _get_galaxy_role_ns(yaml['galaxy_info']) role_name = _get_galaxy_role_name(yaml['galaxy_info']) fqrn = f"{role_namespace}{role_name}" else: fqrn = pathlib.Path(".").absolute().name p = pathlib.Path(f"{options.cache_dir}/roles") p.mkdir(parents=True, exist_ok=True) link_path = p / fqrn # despite documentation stating that is_file() reports true for symlinks, # it appears that is_dir() reports true instead, so we rely on exits(). target = pathlib.Path(options.project_dir).absolute() if not link_path.exists() or os.readlink(link_path) != str(target): if link_path.exists(): link_path.unlink() link_path.symlink_to(target, target_is_directory=True) _logger.info( "Using %s symlink to current repository in order to enable Ansible to find the role using its expected full name.", link_path, )
def prepare_environment() -> None: """Make dependencies available if needed.""" if not options.offline and os.path.exists("requirements.yml"): cmd = [ "ansible-galaxy", "role", "install", "--roles-path", f"{options.project_dir}/.cache/roles", "-vr", "requirements.yml", ] print("Running %s" % " ".join(cmd), file=sys.stderr) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: print(run.stdout, file=sys.stderr) sys.exit(run.returncode) # Run galaxy collection install works on v2 requirements.yml if "collections" in yaml_from_file("requirements.yml"): cmd = [ "ansible-galaxy", "collection", "install", "-p", f"{options.project_dir}/.cache/collections", "-vr", "requirements.yml", ] print("Running %s" % " ".join(cmd), file=sys.stderr) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: print(run.stdout, file=sys.stderr) sys.exit(run.returncode) _install_galaxy_role() _perform_mockings() _prepare_ansible_paths()
def install_requirements(requirement: str) -> None: """Install dependencies from a requirements.yml.""" if not os.path.exists(requirement): return cmd = [ "ansible-galaxy", "role", "install", "--roles-path", f"{options.cache_dir}/roles", "-vr", f"{requirement}", ] _logger.info("Running %s", " ".join(cmd)) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: _logger.error(run.stdout) raise RuntimeError(run.returncode) # Run galaxy collection install works on v2 requirements.yml if "collections" in yaml_from_file(requirement): cmd = [ "ansible-galaxy", "collection", "install", "-p", f"{options.cache_dir}/collections", "-vr", f"{requirement}", ] _logger.info("Running %s", " ".join(cmd)) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: _logger.error(run.stdout) raise RuntimeError(run.returncode)
def _install_galaxy_role() -> None: """Detect standalone galaxy role and installs it.""" if not os.path.exists("meta/main.yml"): return yaml = yaml_from_file("meta/main.yml") if 'galaxy_info' not in yaml: return role_name = yaml['galaxy_info'].get('role_name', None) role_author = yaml['galaxy_info'].get('author', None) if not role_name: role_name = pathlib.Path(".").absolute().name role_name = re.sub(r'^{0}'.format(re.escape('ansible-role-')), '', role_name) fqrn = f"{role_author}.{role_name}" if not re.match(r"[a-z0-9][a-z0-9_]+\.[a-z][a-z0-9_]+$", fqrn): print( f"""\ Computed fully qualified role name of {fqrn} is not valid. Please edit meta/main.yml and assure we can correctly determine full role name: galaxy_info: role_name: my_name # if absent directory name hosting role is used instead author: my_galaxy_namespace Namespace: https://galaxy.ansible.com/docs/contributing/namespaces.html#galaxy-namespace-limitations Role: https://galaxy.ansible.com/docs/contributing/creating_role.html#role-names """, file=sys.stderr, ) sys.exit(INVALID_PREREQUISITES_RC) p = pathlib.Path(f"{options.project_dir}/.cache/roles") p.mkdir(parents=True, exist_ok=True) link_path = p / f"{role_author}.{role_name}" # despite documentation stating that is_file() reports true for symlinks, # it appears that is_dir() reports true instead, so we rely on exits(). if not link_path.exists(): link_path.symlink_to(pathlib.Path("../..", target_is_directory=True)) print( f"Using {link_path} symlink to current repository in order to enable Ansible to find the role using its expected full name.", file=sys.stderr, )
def prepare_environment() -> None: """Make dependencies available if needed.""" if not options.configured: # Allow method to be used without calling the command line, so we can # reuse it in other tools, like molecule. # pylint: disable=import-outside-toplevel,cyclic-import from ansiblelint.__main__ import initialize_options initialize_options() if not options.offline and os.path.exists("requirements.yml"): cmd = [ "ansible-galaxy", "role", "install", "--roles-path", f"{options.project_dir}/.cache/roles", "-vr", "requirements.yml", ] _logger.info("Running %s", " ".join(cmd)) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: _logger.error(run.stdout) sys.exit(run.returncode) # Run galaxy collection install works on v2 requirements.yml if "collections" in yaml_from_file("requirements.yml"): cmd = [ "ansible-galaxy", "collection", "install", "-p", f"{options.project_dir}/.cache/collections", "-vr", "requirements.yml", ] _logger.info("Running %s", " ".join(cmd)) run = subprocess.run( cmd, universal_newlines=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if run.returncode != 0: _logger.error(run.stdout) sys.exit(run.returncode) _install_galaxy_role() _perform_mockings() _prepare_ansible_paths()