Merge pull request 'use experimental flags everywhere' (#298) from Mic92-vm-api into main
This commit is contained in:
@@ -8,4 +8,4 @@ jobs:
|
|||||||
runs-on: nix
|
runs-on: nix
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: nix run --refresh github:Mic92/nix-ci-build
|
- run: nix run --refresh github:Mic92/nix-fast-build/ae50c356c2f9e790f3d9d8e00bfa9f4b54f49bdd
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import sys
|
|||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from . import admin, config, machines, secrets, webui, zerotier
|
from . import config, create, machines, secrets, webui, zerotier
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
from .ssh import cli as ssh_cli
|
from .ssh import cli as ssh_cli
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser:
|
|||||||
parser = argparse.ArgumentParser(prog=prog, description="cLAN tool")
|
parser = argparse.ArgumentParser(prog=prog, description="cLAN tool")
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
|
||||||
parser_admin = subparsers.add_parser("admin", help="administrate a clan")
|
parser_create = subparsers.add_parser("create", help="create a clan flake")
|
||||||
admin.register_parser(parser_admin)
|
create.register_parser(parser_create)
|
||||||
|
|
||||||
# DISABLED: this currently crashes if a flake does not define .#clanOptions
|
# DISABLED: this currently crashes if a flake does not define .#clanOptions
|
||||||
if os.environ.get("CLAN_OPTIONS_FILE") is not None:
|
if os.environ.get("CLAN_OPTIONS_FILE") is not None:
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
# !/usr/bin/env python3
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
def create(args: argparse.Namespace) -> None:
|
|
||||||
os.makedirs(args.folder, exist_ok=True)
|
|
||||||
# TODO create clan template in flake
|
|
||||||
subprocess.run(
|
|
||||||
[
|
|
||||||
"nix",
|
|
||||||
"flake",
|
|
||||||
"init",
|
|
||||||
"-t",
|
|
||||||
"git+https://git.clan.lol/clan/clan-core#new-clan",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# takes a (sub)parser and configures it
|
|
||||||
def register_parser(parser: argparse.ArgumentParser) -> None:
|
|
||||||
parser.add_argument(
|
|
||||||
"-f",
|
|
||||||
"--folder",
|
|
||||||
help="the folder where the clan is defined, default to the current folder",
|
|
||||||
default=os.environ["PWD"],
|
|
||||||
)
|
|
||||||
subparser = parser.add_subparsers(
|
|
||||||
title="command",
|
|
||||||
description="the command to run",
|
|
||||||
help="the command to run",
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
parser_create = subparser.add_parser("create", help="create a new clan")
|
|
||||||
parser_create.set_defaults(func=create)
|
|
||||||
@@ -3,7 +3,8 @@ import subprocess
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional, Type, Union
|
from typing import Any, Optional, Type, Union
|
||||||
|
|
||||||
from clan_cli.errors import ClanError
|
from ..errors import ClanError
|
||||||
|
from ..nix import nix_eval
|
||||||
|
|
||||||
script_dir = Path(__file__).parent
|
script_dir = Path(__file__).parent
|
||||||
|
|
||||||
@@ -30,11 +31,9 @@ def schema_from_module_file(
|
|||||||
slib.parseModule {absolute_path}
|
slib.parseModule {absolute_path}
|
||||||
"""
|
"""
|
||||||
# run the nix expression and parse the output as json
|
# run the nix expression and parse the output as json
|
||||||
return json.loads(
|
cmd = nix_eval(["--expr", nix_expr])
|
||||||
subprocess.check_output(
|
proc = subprocess.run(cmd, stdout=subprocess.PIPE, check=True)
|
||||||
["nix", "eval", "--impure", "--json", "--expr", nix_expr]
|
return json.loads(proc.stdout)
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def subtype_from_schema(schema: dict[str, Any]) -> Type:
|
def subtype_from_schema(schema: dict[str, Any]) -> Type:
|
||||||
|
|||||||
25
pkgs/clan-cli/clan_cli/create.py
Normal file
25
pkgs/clan-cli/clan_cli/create.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# !/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from .nix import nix_command
|
||||||
|
|
||||||
|
|
||||||
|
def create(args: argparse.Namespace) -> None:
|
||||||
|
# TODO create clan template in flake
|
||||||
|
subprocess.run(
|
||||||
|
nix_command(
|
||||||
|
[
|
||||||
|
"flake",
|
||||||
|
"init",
|
||||||
|
"-t",
|
||||||
|
"git+https://git.clan.lol/clan/clan-core#new-clan",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# takes a (sub)parser and configures it
|
||||||
|
def register_parser(parser: argparse.ArgumentParser) -> None:
|
||||||
|
parser.set_defaults(func=create)
|
||||||
@@ -5,7 +5,7 @@ import subprocess
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ..dirs import get_clan_flake_toplevel
|
from ..dirs import get_clan_flake_toplevel
|
||||||
from ..nix import nix_eval
|
from ..nix import nix_command, nix_eval
|
||||||
from ..secrets.generate import generate_secrets
|
from ..secrets.generate import generate_secrets
|
||||||
from ..secrets.upload import upload_secrets
|
from ..secrets.upload import upload_secrets
|
||||||
from ..ssh import Host, HostGroup, HostKeyCheck
|
from ..ssh import Host, HostGroup, HostKeyCheck
|
||||||
@@ -22,7 +22,7 @@ def deploy_nixos(hosts: HostGroup) -> None:
|
|||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env["NIX_SSHOPTS"] = ssh_arg
|
env["NIX_SSHOPTS"] = ssh_arg
|
||||||
res = h.run_local(
|
res = h.run_local(
|
||||||
["nix", "flake", "archive", "--to", f"ssh://{target}", "--json"],
|
nix_command(["flake", "archive", "--to", f"ssh://{target}", "--json"]),
|
||||||
check=True,
|
check=True,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
extra_env=env,
|
extra_env=env,
|
||||||
|
|||||||
@@ -4,28 +4,35 @@ import tempfile
|
|||||||
from .dirs import nixpkgs_flake, nixpkgs_source, unfree_nixpkgs
|
from .dirs import nixpkgs_flake, nixpkgs_source, unfree_nixpkgs
|
||||||
|
|
||||||
|
|
||||||
|
def nix_command(flags: list[str]) -> list[str]:
|
||||||
|
return ["nix", "--experimental-features", "nix-command flakes"] + flags
|
||||||
|
|
||||||
|
|
||||||
def nix_build(
|
def nix_build(
|
||||||
flags: list[str],
|
flags: list[str],
|
||||||
) -> list[str]:
|
) -> list[str]:
|
||||||
return [
|
return (
|
||||||
"nix",
|
nix_command(
|
||||||
"build",
|
[
|
||||||
"--no-link",
|
"build",
|
||||||
"--print-out-paths",
|
"--no-link",
|
||||||
"--extra-experimental-features",
|
"--print-out-paths",
|
||||||
"nix-command flakes",
|
"--extra-experimental-features",
|
||||||
] + flags
|
"nix-command flakes",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ flags
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def nix_eval(flags: list[str]) -> list[str]:
|
def nix_eval(flags: list[str]) -> list[str]:
|
||||||
default_flags = [
|
default_flags = nix_command(
|
||||||
"nix",
|
[
|
||||||
"eval",
|
"eval",
|
||||||
"--show-trace",
|
"--show-trace",
|
||||||
"--json",
|
"--json",
|
||||||
"--extra-experimental-features",
|
]
|
||||||
"nix-command flakes",
|
)
|
||||||
]
|
|
||||||
if os.environ.get("IN_NIX_SANDBOX"):
|
if os.environ.get("IN_NIX_SANDBOX"):
|
||||||
with tempfile.TemporaryDirectory() as nix_store:
|
with tempfile.TemporaryDirectory() as nix_store:
|
||||||
return (
|
return (
|
||||||
@@ -51,14 +58,13 @@ def nix_shell(packages: list[str], cmd: list[str]) -> list[str]:
|
|||||||
return cmd
|
return cmd
|
||||||
wrapped_packages = [f"nixpkgs#{p}" for p in packages]
|
wrapped_packages = [f"nixpkgs#{p}" for p in packages]
|
||||||
return (
|
return (
|
||||||
[
|
nix_command(
|
||||||
"nix",
|
[
|
||||||
"shell",
|
"shell",
|
||||||
"--extra-experimental-features",
|
"--inputs-from",
|
||||||
"nix-command flakes",
|
f"{str(nixpkgs_flake())}",
|
||||||
"--inputs-from",
|
]
|
||||||
f"{str(nixpkgs_flake())}",
|
)
|
||||||
]
|
|
||||||
+ wrapped_packages
|
+ wrapped_packages
|
||||||
+ ["-c"]
|
+ ["-c"]
|
||||||
+ cmd
|
+ cmd
|
||||||
@@ -69,14 +75,13 @@ def unfree_nix_shell(packages: list[str], cmd: list[str]) -> list[str]:
|
|||||||
if os.environ.get("IN_NIX_SANDBOX"):
|
if os.environ.get("IN_NIX_SANDBOX"):
|
||||||
return cmd
|
return cmd
|
||||||
return (
|
return (
|
||||||
[
|
nix_command(
|
||||||
"nix",
|
[
|
||||||
"shell",
|
"shell",
|
||||||
"--extra-experimental-features",
|
"-f",
|
||||||
"nix-command flakes",
|
str(unfree_nixpkgs()),
|
||||||
"-f",
|
]
|
||||||
str(unfree_nixpkgs()),
|
)
|
||||||
]
|
|
||||||
+ packages
|
+ packages
|
||||||
+ ["-c"]
|
+ ["-c"]
|
||||||
+ cmd
|
+ cmd
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ clan_cli = [ "config/jsonschema/*", "webui/assets/**/*"]
|
|||||||
faulthandler_timeout = 30
|
faulthandler_timeout = 30
|
||||||
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --workers auto --durations 5"
|
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --workers auto --durations 5"
|
||||||
norecursedirs = "tests/helpers"
|
norecursedirs = "tests/helpers"
|
||||||
|
markers = [ "impure" ]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
python_version = "3.10"
|
python_version = "3.10"
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import pytest
|
|||||||
|
|
||||||
TEST_ROOT = Path(__file__).parent.resolve()
|
TEST_ROOT = Path(__file__).parent.resolve()
|
||||||
PROJECT_ROOT = TEST_ROOT.parent
|
PROJECT_ROOT = TEST_ROOT.parent
|
||||||
|
CLAN_CORE = PROJECT_ROOT.parent.parent
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def project_root() -> Path:
|
def project_root() -> Path:
|
||||||
"""
|
"""
|
||||||
Root directory of the tests
|
Root directory the clan-cli
|
||||||
"""
|
"""
|
||||||
return PROJECT_ROOT
|
return PROJECT_ROOT
|
||||||
|
|
||||||
@@ -20,3 +21,11 @@ def test_root() -> Path:
|
|||||||
Root directory of the tests
|
Root directory of the tests
|
||||||
"""
|
"""
|
||||||
return TEST_ROOT
|
return TEST_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def clan_core() -> Path:
|
||||||
|
"""
|
||||||
|
Directory of the clan-core flake
|
||||||
|
"""
|
||||||
|
return CLAN_CORE
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
from typing import Union
|
|
||||||
|
|
||||||
import pytest_subprocess.fake_process
|
|
||||||
from cli import Cli
|
|
||||||
from pytest_subprocess import utils
|
|
||||||
|
|
||||||
|
|
||||||
# using fp fixture from pytest-subprocess
|
|
||||||
def test_create(fp: pytest_subprocess.fake_process.FakeProcess) -> None:
|
|
||||||
cmd: list[Union[str, utils.Any]] = ["nix", "flake", "init", "-t", fp.any()]
|
|
||||||
fp.register(cmd)
|
|
||||||
cli = Cli()
|
|
||||||
cli.run(["admin", "--folder", "./my-clan", "create"])
|
|
||||||
assert fp.call_count(cmd) == 1
|
|
||||||
12
pkgs/clan-cli/tests/test_clan_template.py
Normal file
12
pkgs/clan-cli/tests/test_clan_template.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from cli import Cli
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.impure
|
||||||
|
def test_template(monkeypatch: pytest.MonkeyPatch, temporary_dir: Path) -> None:
|
||||||
|
monkeypatch.chdir(temporary_dir)
|
||||||
|
cli = Cli()
|
||||||
|
cli.run(["create"])
|
||||||
|
assert (temporary_dir / ".clan-flake").exists()
|
||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from root import PROJECT_ROOT
|
from root import CLAN_CORE
|
||||||
|
|
||||||
from clan_cli.dirs import nixpkgs_source
|
from clan_cli.dirs import nixpkgs_source
|
||||||
|
|
||||||
@@ -46,9 +46,8 @@ def test_flake(monkeymodule: pytest.MonkeyPatch) -> Iterator[Path]:
|
|||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def test_flake_with_core(monkeymodule: pytest.MonkeyPatch) -> Iterator[Path]:
|
def test_flake_with_core(monkeymodule: pytest.MonkeyPatch) -> Iterator[Path]:
|
||||||
clan_core_flake = PROJECT_ROOT.parent.parent
|
if not (CLAN_CORE / "flake.nix").exists():
|
||||||
if not (clan_core_flake / "flake.nix").exists():
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"clan-core flake not found. This test requires the clan-core flake to be present"
|
"clan-core flake not found. This test requires the clan-core flake to be present"
|
||||||
)
|
)
|
||||||
yield from create_flake(monkeymodule, "test_flake_with_core", clan_core_flake)
|
yield from create_flake(monkeymodule, "test_flake_with_core", CLAN_CORE)
|
||||||
|
|||||||
@@ -30,9 +30,8 @@ def test_ssh_no_pass(
|
|||||||
monkeypatch.delenv("IN_NIX_SANDBOX")
|
monkeypatch.delenv("IN_NIX_SANDBOX")
|
||||||
cmd: list[Union[str, utils.Any]] = [
|
cmd: list[Union[str, utils.Any]] = [
|
||||||
"nix",
|
"nix",
|
||||||
|
fp.any(),
|
||||||
"shell",
|
"shell",
|
||||||
"--extra-experimental-features",
|
|
||||||
"nix-command flakes",
|
|
||||||
fp.any(),
|
fp.any(),
|
||||||
"-c",
|
"-c",
|
||||||
"torify",
|
"torify",
|
||||||
@@ -61,9 +60,8 @@ def test_ssh_with_pass(
|
|||||||
monkeypatch.delenv("IN_NIX_SANDBOX")
|
monkeypatch.delenv("IN_NIX_SANDBOX")
|
||||||
cmd: list[Union[str, utils.Any]] = [
|
cmd: list[Union[str, utils.Any]] = [
|
||||||
"nix",
|
"nix",
|
||||||
|
fp.any(),
|
||||||
"shell",
|
"shell",
|
||||||
"--extra-experimental-features",
|
|
||||||
"nix-command flakes",
|
|
||||||
fp.any(),
|
fp.any(),
|
||||||
"-c",
|
"-c",
|
||||||
"torify",
|
"torify",
|
||||||
|
|||||||
Reference in New Issue
Block a user