Fixed cyclic dependencie AND swapped pytest-parallel for pytest-xdist to fix deadlock in tests

This commit is contained in:
Qubasa
2023-10-16 15:03:53 +02:00
parent ecdd4949b7
commit 7bbadaa60f
25 changed files with 59 additions and 42 deletions

View File

@@ -11,7 +11,7 @@ from typing import Any, Optional, Tuple, get_origin
from clan_cli.dirs import machine_settings_file, specific_flake_dir
from clan_cli.errors import ClanError
from clan_cli.flakes.types import FlakeName
from clan_cli.types import FlakeName
from clan_cli.git import commit_file
from clan_cli.nix import nix_eval

View File

@@ -15,7 +15,7 @@ from clan_cli.dirs import (
from clan_cli.git import commit_file, find_git_repo_root
from clan_cli.nix import nix_eval
from ..flakes.types import FlakeName
from ..types import FlakeName
def verify_machine_config(

View File

@@ -4,7 +4,7 @@ from pathlib import Path
from typing import Optional
from .errors import ClanError
from .flakes.types import FlakeName
from .types import FlakeName
def _get_clan_flake_toplevel() -> Path:

View File

@@ -5,7 +5,7 @@ from typing import Dict
from ..async_cmd import CmdOut, run, runforcli
from ..dirs import specific_flake_dir, specific_machine_dir
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
from ..nix import nix_shell
log = logging.getLogger(__name__)

View File

@@ -1,5 +1,5 @@
from ..dirs import specific_machine_dir
from ..flakes.types import FlakeName
from ..types import FlakeName
def machine_has_fact(flake_name: FlakeName, machine: str, fact: str) -> bool:

View File

@@ -3,7 +3,7 @@ import logging
import os
from ..dirs import machines_dir
from ..flakes.types import FlakeName
from ..types import FlakeName
from .types import validate_hostname
log = logging.getLogger(__name__)

View File

@@ -5,7 +5,7 @@ from typing import Callable
from ..dirs import specific_flake_dir
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
def get_sops_folder(flake_name: FlakeName) -> Path:

View File

@@ -3,7 +3,7 @@ import os
from pathlib import Path
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
from ..machines.types import machine_name_type, validate_hostname
from . import secrets
from .folders import (

View File

@@ -1,6 +1,6 @@
import argparse
from ..flakes.types import FlakeName
from ..types import FlakeName
from ..machines.types import machine_name_type, validate_hostname
from . import secrets
from .folders import list_objects, remove_object, sops_machines_folder

View File

@@ -8,7 +8,7 @@ from typing import IO
from .. import tty
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
from .folders import (
list_objects,
sops_groups_folder,

View File

@@ -9,7 +9,7 @@ from typing import IO, Iterator
from ..dirs import user_config_dir
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
from ..nix import nix_shell
from .folders import sops_machines_folder, sops_users_folder

View File

@@ -11,7 +11,7 @@ from clan_cli.nix import nix_shell
from ..dirs import specific_flake_dir
from ..errors import ClanError
from ..flakes.types import FlakeName
from ..types import FlakeName
from .folders import sops_secrets_folder
from .machines import add_machine, has_machine
from .secrets import decrypt_secret, encrypt_secret, has_secret

View File

@@ -1,6 +1,6 @@
import argparse
from ..flakes.types import FlakeName
from ..types import FlakeName
from . import secrets
from .folders import list_objects, remove_object, sops_users_folder
from .sops import read_key, write_key

View File

@@ -10,7 +10,7 @@ from ...config.machine import (
set_config_for_machine,
verify_machine_config,
)
from ...flakes.types import FlakeName
from ...types import FlakeName
from ...machines.create import create_machine as _create_machine
from ...machines.list import list_machines as _list_machines
from ..api_outputs import (

View File

@@ -8,6 +8,7 @@
, openssh
, pytest
, pytest-cov
, pytest-xdist
, pytest-subprocess
, pytest-parallel
, pytest-timeout
@@ -45,7 +46,8 @@ let
pytest
pytest-cov
pytest-subprocess
pytest-parallel
# pytest-parallel
pytest-xdist
pytest-timeout
openssh
git

View File

@@ -14,9 +14,13 @@ exclude = ["clan_cli.nixpkgs*"]
[tool.setuptools.package-data]
clan_cli = [ "config/jsonschema/*", "webui/assets/**/*"]
[tool.pytest.ini_options]
testpaths = "tests"
faulthandler_timeout = 60
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --workers auto --durations 5"
log_level = "DEBUG"
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail -n auto --durations 5 --maxfail=1 --new-first"
norecursedirs = "tests/helpers"
markers = [ "impure" ]

View File

@@ -53,6 +53,7 @@ mkShell {
register-python-argcomplete --shell fish clan > $tmp_path/share/fish/vendor_completions.d/clan.fish
register-python-argcomplete --shell bash clan > $tmp_path/share/bash-completion/completions/clan
./bin/clan machines create example
./bin/clan flakes create example_clan
./bin/clan machines create example_machine example_clan
'';
}

View File

@@ -8,7 +8,7 @@ import pytest
from root import CLAN_CORE
from clan_cli.dirs import nixpkgs_source
from clan_cli.flakes.types import FlakeName
from clan_cli.types import FlakeName
# substitutes string sin a file.
@@ -28,7 +28,7 @@ def substitute(
print(line, end="")
class TestFlake(NamedTuple):
class FlakeForTest(NamedTuple):
name: FlakeName
path: Path
@@ -39,7 +39,7 @@ def create_flake(
clan_core_flake: Path | None = None,
machines: list[str] = [],
remote: bool = False,
) -> Iterator[TestFlake]:
) -> Iterator[FlakeForTest]:
"""
Creates a flake with the given name and machines.
The machine names map to the machines in ./test_machines
@@ -66,20 +66,20 @@ def create_flake(
with tempfile.TemporaryDirectory() as workdir:
monkeypatch.chdir(workdir)
monkeypatch.setenv("HOME", str(home))
yield TestFlake(flake_name, flake)
yield FlakeForTest(flake_name, flake)
else:
monkeypatch.chdir(flake)
monkeypatch.setenv("HOME", str(home))
yield TestFlake(flake_name, flake)
yield FlakeForTest(flake_name, flake)
@pytest.fixture
def test_flake(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]:
def test_flake(monkeypatch: pytest.MonkeyPatch) -> Iterator[FlakeForTest]:
yield from create_flake(monkeypatch, FlakeName("test_flake"))
@pytest.fixture
def test_flake_with_core(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]:
def test_flake_with_core(monkeypatch: pytest.MonkeyPatch) -> Iterator[FlakeForTest]:
if not (CLAN_CORE / "flake.nix").exists():
raise Exception(
"clan-core flake not found. This test requires the clan-core flake to be present"
@@ -90,7 +90,7 @@ def test_flake_with_core(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]
@pytest.fixture
def test_flake_with_core_and_pass(
monkeypatch: pytest.MonkeyPatch,
) -> Iterator[TestFlake]:
) -> Iterator[FlakeForTest]:
if not (CLAN_CORE / "flake.nix").exists():
raise Exception(
"clan-core flake not found. This test requires the clan-core flake to be present"

View File

@@ -1,13 +1,18 @@
import argparse
from clan_cli import create_parser
import logging
import sys
import shlex
log = logging.getLogger(__name__)
class Cli:
def __init__(self) -> None:
self.parser = create_parser(prog="clan")
def run(self, args: list[str]) -> argparse.Namespace:
cmd = shlex.join(["clan"] + args)
log.debug(f"Command: {cmd}")
parsed = self.parser.parse_args(args)
if hasattr(parsed, "func"):
parsed.func(parsed)

View File

@@ -1,8 +1,8 @@
from fixtures_flakes import TestFlake
from fixtures_flakes import FlakeForTest
from clan_cli.config import machine
def test_schema_for_machine(test_flake: TestFlake) -> None:
def test_schema_for_machine(test_flake: FlakeForTest) -> None:
schema = machine.schema_for_machine(test_flake.name, "machine1")
assert "properties" in schema

View File

@@ -3,23 +3,27 @@ from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING, Iterator
import logging
import pytest
from cli import Cli
from fixtures_flakes import FlakeForTest
from clan_cli.errors import ClanError
if TYPE_CHECKING:
from age_keys import KeyPair
log = logging.getLogger(__name__)
def _test_identities(
what: str,
test_flake: Path,
test_flake: FlakeForTest,
capsys: pytest.CaptureFixture,
age_keys: list["KeyPair"],
) -> None:
cli = Cli()
sops_folder = test_flake / "sops"
sops_folder = test_flake.path / "sops"
cli.run(["secrets", what, "add", "foo", age_keys[0].pubkey])
assert (sops_folder / what / "foo" / "key.json").exists()
@@ -34,6 +38,7 @@ def _test_identities(
"-f",
"foo",
age_keys[0].privkey,
test_flake.name,
]
)
@@ -60,19 +65,19 @@ def _test_identities(
def test_users(
test_flake: Path, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
test_flake: FlakeForTest, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
) -> None:
_test_identities("users", test_flake, capsys, age_keys)
def test_machines(
test_flake: Path, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
test_flake: FlakeForTest, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
) -> None:
_test_identities("machines", test_flake, capsys, age_keys)
def test_groups(
test_flake: Path, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
test_flake: FlakeForTest, capsys: pytest.CaptureFixture, age_keys: list["KeyPair"]
) -> None:
cli = Cli()
capsys.readouterr() # empty the buffer
@@ -100,7 +105,7 @@ def test_groups(
cli.run(["secrets", "groups", "remove-user", "group1", "user1"])
cli.run(["secrets", "groups", "remove-machine", "group1", "machine1"])
groups = os.listdir(test_flake / "sops" / "groups")
groups = os.listdir(test_flake.path / "sops" / "groups")
assert len(groups) == 0

View File

@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING
import pytest
from cli import Cli
from fixtures_flakes import TestFlake
from fixtures_flakes import FlakeForTest
from clan_cli.machines.facts import machine_get_fact
from clan_cli.secrets.folders import sops_secrets_folder
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
@pytest.mark.impure
def test_generate_secret(
monkeypatch: pytest.MonkeyPatch,
test_flake_with_core: TestFlake,
test_flake_with_core: FlakeForTest,
age_keys: list["KeyPair"],
) -> None:
monkeypatch.chdir(test_flake_with_core.path)

View File

@@ -3,7 +3,7 @@ from pathlib import Path
import pytest
from cli import Cli
from fixtures_flakes import TestFlake
from fixtures_flakes import FlakeForTest
from clan_cli.machines.facts import machine_get_fact
from clan_cli.nix import nix_shell
@@ -13,7 +13,7 @@ from clan_cli.ssh import HostGroup
@pytest.mark.impure
def test_upload_secret(
monkeypatch: pytest.MonkeyPatch,
test_flake_with_core_and_pass: TestFlake,
test_flake_with_core_and_pass: FlakeForTest,
temporary_dir: Path,
host_group: HostGroup,
) -> None:

View File

@@ -5,18 +5,18 @@ from typing import TYPE_CHECKING, Iterator
import pytest
from api import TestClient
from cli import Cli
from fixtures_flakes import TestFlake, create_flake
from fixtures_flakes import FlakeForTest, create_flake
from httpx import SyncByteStream
from root import CLAN_CORE
from clan_cli.flakes.types import FlakeName
from clan_cli.types import FlakeName
if TYPE_CHECKING:
from age_keys import KeyPair
@pytest.fixture
def flake_with_vm_with_secrets(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]:
def flake_with_vm_with_secrets(monkeypatch: pytest.MonkeyPatch) -> Iterator[FlakeForTest]:
yield from create_flake(
monkeypatch,
FlakeName("test_flake_with_core_dynamic_machines"),
@@ -28,7 +28,7 @@ def flake_with_vm_with_secrets(monkeypatch: pytest.MonkeyPatch) -> Iterator[Test
@pytest.fixture
def remote_flake_with_vm_without_secrets(
monkeypatch: pytest.MonkeyPatch,
) -> Iterator[TestFlake]:
) -> Iterator[FlakeForTest]:
yield from create_flake(
monkeypatch,
FlakeName("test_flake_with_core_dynamic_machines"),