File: test_runtime_scan_path.py

package info (click to toggle)
python-ansible-compat 25.1.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 656 kB
  • sloc: python: 2,522; sh: 26; makefile: 24
file content (125 lines) | stat: -rw-r--r-- 4,343 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""Test the scan path functionality of the runtime."""

import json
import os
import subprocess
import textwrap
from pathlib import Path

import pytest
from _pytest.monkeypatch import MonkeyPatch

from ansible_compat.runtime import Runtime

from .conftest import VirtualEnvironment

V2_COLLECTION_TARBALL = Path("examples/reqs_v2/community-molecule-0.1.0.tar.gz")
V2_COLLECTION_NAMESPACE = "community"
V2_COLLECTION_NAME = "molecule"
V2_COLLECTION_VERSION = "0.1.0"
V2_COLLECTION_FULL_NAME = f"{V2_COLLECTION_NAMESPACE}.{V2_COLLECTION_NAME}"


@pytest.mark.parametrize(
    ("scan", "raises_not_found"),
    (
        pytest.param(False, True, id="disabled"),
        pytest.param(True, False, id="enabled"),
    ),
    ids=str,
)
def test_scan_sys_path(
    venv_module: VirtualEnvironment,
    monkeypatch: MonkeyPatch,
    tmp_path: Path,
    scan: bool,
    raises_not_found: bool,
) -> None:
    """Confirm sys path is scanned for collections.

    Args:
        venv_module: Fixture for a virtual environment
        monkeypatch: Fixture for monkeypatching
        tmp_path: Fixture for a temporary directory
        scan: Whether to scan the sys path
        raises_not_found: Whether the collection is expected to be found
    """
    # Isolated the test from the others, so ansible will not find collections
    # that might be installed by other tests.
    monkeypatch.setenv("VIRTUAL_ENV", venv_module.project.as_posix())
    monkeypatch.setenv("ANSIBLE_HOME", tmp_path.as_posix())
    # Set the sys scan path environment variable
    monkeypatch.setenv("ANSIBLE_COLLECTIONS_SCAN_SYS_PATH", str(scan))
    # Set the ansible collections paths to avoid bleed from other tests
    monkeypatch.setenv("ANSIBLE_COLLECTIONS_PATH", str(tmp_path))

    runtime_tmp = Runtime(project_dir=tmp_path, isolated=True)
    first_site_package_dir = venv_module.site_package_dirs()[0]

    installed_to = (
        first_site_package_dir
        / "ansible_collections"
        / V2_COLLECTION_NAMESPACE
        / V2_COLLECTION_NAME
    )
    if not installed_to.exists():
        # Install the collection into the venv site packages directory, force
        # as of yet this test is not isolated from the rest of the system
        runtime_tmp.install_collection(
            collection=V2_COLLECTION_TARBALL,
            destination=first_site_package_dir,
            force=True,
        )
    # Confirm the collection is installed
    assert installed_to.exists()

    script = textwrap.dedent(
        f"""
    import json;
    from ansible_compat.runtime import Runtime;
    r = Runtime();
    fv, cp = r.require_collection(name="{V2_COLLECTION_FULL_NAME}", version="{V2_COLLECTION_VERSION}", install=False);
    print(json.dumps({{"found_version": str(fv), "collection_path": str(cp)}}));
    """,
    )

    proc = venv_module.python_script_run(script)
    if raises_not_found:
        assert proc.returncode != 0, (proc.stdout, proc.stderr)
        assert "InvalidPrerequisiteError" in proc.stderr
        assert "'community.molecule' not found" in proc.stderr
    else:
        assert proc.returncode == 0, (proc.stdout, proc.stderr)
        result = json.loads(proc.stdout)
        assert result["found_version"] == V2_COLLECTION_VERSION
        assert result["collection_path"] == str(installed_to)

    runtime_tmp.clean()


def test_ro_venv() -> None:
    """Tests behavior when the virtual environment is read-only.

    See Related https://github.com/ansible/ansible-compat/pull/470
    """
    tox_work_dir = os.environ.get("TOX_WORK_DIR", ".tox")
    venv_path = f"{tox_work_dir}/ro"
    commands = [
        f"mkdir -p {venv_path}",
        f"chmod -R a+w {venv_path}",
        f"python -m venv --symlinks {venv_path}",
        f"{venv_path}/bin/python -m pip install -q -e .",
        f"chmod -R a-w {venv_path}",
        f"{venv_path}/bin/python -c \"from ansible_compat.runtime import Runtime; r = Runtime(); r.install_collection('ansible.posix:>=2.0.0')\"",
    ]
    for cmd in commands:
        result = subprocess.run(  # noqa: S602
            cmd,
            check=False,
            shell=True,
            text=True,
            capture_output=True,
        )
        assert (
            result.returncode == 0
        ), f"Got {result.returncode} running {cmd}\n\tstderr: {result.stderr}\n\tstdout: {result.stdout}"