Skip to content

Commit

Permalink
Add ability to mock roles
Browse files Browse the repository at this point in the history
In addition to being able to mock modules, now we can also mock
roles.
  • Loading branch information
ssbarnea committed Feb 4, 2021
1 parent 4faa359 commit 9d9c63e
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 18 deletions.
2 changes: 2 additions & 0 deletions .ansible-lint
Expand Up @@ -2,3 +2,5 @@ exclude_paths:
- .github/
mock_modules:
- zuul_return
mock_roles:
- mocked_role
4 changes: 3 additions & 1 deletion docs/configuring.rst
Expand Up @@ -46,9 +46,11 @@ counterparts:
- and_this_one_too
- skip_this_id
- '401'
# Mock modules or roles in order to pass ansible-playbook --syntax-check
mock_modules:
# Mock modules in order to pass ansible-playbook --syntax-check
- some_module
mock_roles:
- some_role
Pre-commit Setup
Expand Down
@@ -1,4 +1,6 @@
- hosts: localhost
roles:
- mocked_role
tasks:
- name: some task
zuul_return: {}
32 changes: 24 additions & 8 deletions src/ansiblelint/_prerun.py
Expand Up @@ -34,12 +34,6 @@ def check_ansible_presence() -> None:

def prepare_environment() -> None:
"""Make custom modules available if needed."""
_prepare_library_paths()

if os.path.exists("roles") and "ANSIBLE_ROLES_PATH" not in os.environ:
os.environ['ANSIBLE_ROLES_PATH'] = "roles"
print("Added ANSIBLE_ROLES_PATH=roles", file=sys.stderr)

if os.path.exists("requirements.yml"):

cmd = [
Expand Down Expand Up @@ -83,14 +77,15 @@ def prepare_environment() -> None:
if run.returncode != 0:
sys.exit(run.returncode)

if 'ANSIBLE_ROLES_PATH' in os.environ:
os.environ['ANSIBLE_ROLES_PATH'] = f".cache/roles:{os.environ['ANSIBLE_ROLES_PATH']}"
if 'ANSIBLE_COLLECTIONS_PATHS' in os.environ:
os.environ['ANSIBLE_COLLECTIONS_PATHS'] = \
f".cache/collections:{os.environ['ANSIBLE_COLLECTIONS_PATHS']}"
else:
os.environ['ANSIBLE_COLLECTIONS_PATHS'] = ".cache/collections"

_prepare_library_paths()
_prepare_roles_path()


def _prepare_library_paths() -> None:
"""Configure ANSIBLE_LIBRARY."""
Expand All @@ -112,3 +107,24 @@ def _prepare_library_paths() -> None:
if library_path_str != os.environ.get('ANSIBLE_LIBRARY', ""):
os.environ['ANSIBLE_LIBRARY'] = library_path_str
print("Added ANSIBLE_LIBRARY=%s" % library_path_str, file=sys.stderr)


def _prepare_roles_path() -> None:
"""Configure ANSIBLE_ROLES_PATH."""
roles_path: List[str] = []
if 'ANSIBLE_ROLES_PATH' in os.environ:
roles_path = os.environ['ANSIBLE_ROLES_PATH'].split(':')

if os.path.exists("roles") and "roles" not in roles_path:
roles_path.append("roles")

if options.mock_roles or os.path.exists(".cache/roles"):
for role_name in options.mock_roles:
os.makedirs(f".cache/roles/{role_name}", exist_ok=True)
if ".cache/roles" not in roles_path:
roles_path.append(".cache/roles")

if roles_path:
roles_path_str = ":".join(roles_path)
os.environ['ANSIBLE_ROLES_PATH'] = roles_path_str
print("Added ANSIBLE_ROLES_PATH=%s" % roles_path_str, file=sys.stderr)
3 changes: 2 additions & 1 deletion src/ansiblelint/cli.py
Expand Up @@ -207,7 +207,8 @@ def merge_config(file_config, cli_config: Namespace) -> Namespace:
'skip_list': [],
'tags': [],
'warn_list': ['experimental'],
'mock_modules': []
'mock_modules': [],
'mock_roles': []
}

if not file_config:
Expand Down
3 changes: 2 additions & 1 deletion src/ansiblelint/config.py
Expand Up @@ -37,5 +37,6 @@
verbosity=False,
warn_list=[],
kinds=DEFAULT_KINDS,
mock_modules=[]
mock_modules=[],
mock_roles=[]
)
14 changes: 13 additions & 1 deletion src/ansiblelint/testing/__init__.py
Expand Up @@ -80,13 +80,25 @@ def run_ansible_lint(
else:
args = [executable, *argv]

# It is not safe to pass entire env for testing as other tests would
# polute the env, causing weird behaviors, so we pass only a safe list of
# vars.
if env is None:
_env = {}
for v in ['PYTHONPATH', 'PATH', 'TERM']:
if v in os.environ:
_env[v] = os.environ[v]

else:
_env = env

return subprocess.run(
args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False, # needed when command is a list
check=False,
cwd=cwd,
env=env,
env=_env,
universal_newlines=True
)
8 changes: 4 additions & 4 deletions test/TestCliRolePaths.py
Expand Up @@ -11,11 +11,11 @@

class TestCliRolePaths(unittest.TestCase):
def setUp(self):
self.local_test_dir = os.path.join(
self.local_test_dir = os.path.realpath(os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"..",
"examples"
)
))

def test_run_single_role_path_no_trailing_slash_module(self):
cwd = self.local_test_dir
Expand Down Expand Up @@ -99,7 +99,7 @@ def test_run_role_name_with_prefix(self):

result = run_ansible_lint(role_path, cwd=cwd)
assert len(result.stdout) == 0
assert "Added ANSIBLE_ROLES_PATH=roles" in result.stderr
assert "Added ANSIBLE_ROLES_PATH=roles:.cache/roles" in result.stderr
assert result.returncode == 0

def test_run_role_name_from_meta(self):
Expand All @@ -108,7 +108,7 @@ def test_run_role_name_from_meta(self):

result = run_ansible_lint(role_path, cwd=cwd)
assert len(result.stdout) == 0
assert "Added ANSIBLE_ROLES_PATH=roles" in result.stderr
assert "Added ANSIBLE_ROLES_PATH=roles:.cache/roles" in result.stderr
assert result.returncode == 0

def test_run_invalid_role_name_from_meta(self):
Expand Down
4 changes: 2 additions & 2 deletions test/TestUtils.py
Expand Up @@ -269,8 +269,8 @@ def test_cli_auto_detect(capfd):
# assures that we can parse playbooks as playbooks
assert "Identified: test/test/always-run-success.yml" not in err
# assure that zuul_return missing module is not reported
assert "examples/playbooks/mocked_module.yml" not in out
assert "Executing syntax check on examples/playbooks/mocked_module.yml" in err
assert "examples/playbooks/mocked_dependency.yml" not in out
assert "Executing syntax check on examples/playbooks/mocked_dependency.yml" in err


def test_is_playbook():
Expand Down

0 comments on commit 9d9c63e

Please sign in to comment.