Skip to content

Commit

Permalink
Change cache_dir location to prefer venv and project_directory
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea committed Jan 7, 2025
1 parent 18696a6 commit 5465766
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 24 deletions.
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true
},
"editor.formatOnSave": true,
Expand Down Expand Up @@ -40,5 +40,6 @@
"yaml.completion": true,
"yaml.customTags": ["!encrypted/pkcs1-oaep scalar", "!vault scalar"],
"yaml.format.enable": false,
"yaml.validate": true
"yaml.validate": true,
"cSpell.words": ["delenv"]
}
33 changes: 18 additions & 15 deletions src/ansible_compat/prerun.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
"""Utilities for configuring ansible runtime environment."""

import hashlib
import os
from pathlib import Path


def get_cache_dir(project_dir: Path) -> Path:
"""Compute cache directory to be used based on project path."""
# we only use the basename instead of the full path in order to ensure that
# we would use the same key regardless the location of the user home
# directory or where the project is clones (as long the project folder uses
# the same name).
basename = project_dir.resolve().name.encode(encoding="utf-8")
# 6 chars of entropy should be enough
cache_key = hashlib.sha256(basename).hexdigest()[:6]
cache_dir = (
Path(os.getenv("XDG_CACHE_HOME", "~/.cache")).expanduser()
/ "ansible-compat"
/ cache_key
)
def get_cache_dir(project_dir: Path, *, isolated: bool = True) -> Path:
"""Compute cache directory to be used based on project path.
Returns:
Cache directory path.
"""
if "VIRTUAL_ENV" in os.environ:
cache_dir = Path(os.environ["VIRTUAL_ENV"]) / ".ansible"
elif isolated:
cache_dir = project_dir / ".ansible"
else:
cache_dir = Path(os.environ.get("ANSIBLE_HOME", "~/.ansible")).expanduser()

# Ensure basic folder structure exists so `ansible-galaxy list` does not
# fail with: None of the provided paths were usable. Please specify a valid path with
for name in ("roles", "collections"):
(cache_dir / name).mkdir(parents=True, exist_ok=True)

return cache_dir
4 changes: 2 additions & 2 deletions src/ansible_compat/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ def __init__(
if "PYTHONWARNINGS" not in self.environ: # pragma: no cover
self.environ["PYTHONWARNINGS"] = "ignore:Blowfish has been deprecated"

if isolated:
self.cache_dir = get_cache_dir(self.project_dir)
self.cache_dir = get_cache_dir(self.project_dir, isolated=self.isolated)

self.config = AnsibleConfig(cache_dir=self.cache_dir)

# Add the sys.path to the collection paths if not isolated
Expand Down
13 changes: 13 additions & 0 deletions test/test_prerun.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
"""Tests for ansible_compat.prerun module."""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from _pytest.monkeypatch import MonkeyPatch

from ansible_compat.prerun import get_cache_dir

Expand All @@ -10,3 +16,10 @@ def test_get_cache_dir_relative() -> None:
relative_path = Path()
abs_path = relative_path.resolve()
assert get_cache_dir(relative_path) == get_cache_dir(abs_path)


def test_get_cache_dir_no_isolation_no_venv(monkeypatch: MonkeyPatch) -> None:
"""Test behaviors of get_cache_dir."""
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
monkeypatch.delenv("ANSIBLE_HOME", raising=False)
assert get_cache_dir(Path(), isolated=False) == Path("~/.ansible").expanduser()
10 changes: 7 additions & 3 deletions test/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,10 +652,9 @@ def test_upgrade_collection(runtime_tmp: Runtime) -> None:
runtime_tmp.require_collection("community.molecule", "0.1.0")


def test_require_collection_no_cache_dir() -> None:
def test_require_collection_not_isolated() -> None:
"""Check require_collection without a cache directory."""
runtime = Runtime()
assert not runtime.cache_dir
runtime = Runtime(isolated=False)
runtime.require_collection("community.molecule", "0.1.0", install=True)


Expand Down Expand Up @@ -1022,6 +1021,11 @@ def test_runtime_has_playbook() -> None:
"""Tests has_playbook method."""
runtime = Runtime(require_module=True)

runtime.prepare_environment(
required_collections={"community.molecule": "0.1.0"},
install_local=True,
)

assert not runtime.has_playbook("this-does-not-exist.yml")
# call twice to ensure cache is used:
assert not runtime.has_playbook("this-does-not-exist.yml")
Expand Down
7 changes: 5 additions & 2 deletions test/test_runtime_scan_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def __str__(self) -> str:
@pytest.mark.parametrize(
("param"),
(
ScanSysPath(scan=False, raises_not_found=True),
ScanSysPath(scan=True, raises_not_found=False),
pytest.param(ScanSysPath(scan=False, raises_not_found=True), id="0"),
pytest.param(ScanSysPath(scan=True, raises_not_found=False), id="1"),
),
ids=str,
)
Expand All @@ -57,6 +57,9 @@ def test_scan_sys_path(
:param tmp_dir: Fixture for a temporary directory
:param param: The parameters for the test
"""
# Isolated the test from the others, so ansible will not find collections
# that might be installed by other tests.
monkeypatch.setenv("ANSIBLE_HOME", tmp_path.as_posix())
first_site_package_dir = venv_module.site_package_dirs()[0]

installed_to = (
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ passenv =
LANG
LC_*
setenv =
ANSIBLE_HOME = {envdir}/.ansible
ANSIBLE_DEVEL_WARNING='false'
COVERAGE_FILE = {env:COVERAGE_FILE:{envdir}/.coverage.{envname}}
COVERAGE_PROCESS_START={toxinidir}/pyproject.toml
Expand Down

0 comments on commit 5465766

Please sign in to comment.