nixos-rebuild-ng: implement --target-host
This commit is contained in:
parent
fd1cd69315
commit
a2cbe67701
@ -2,11 +2,14 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
from subprocess import run
|
from subprocess import run
|
||||||
|
from tempfile import TemporaryDirectory
|
||||||
from typing import assert_never
|
from typing import assert_never
|
||||||
|
|
||||||
from .models import Action, Flake, NRError, Profile
|
from .models import Action, Flake, NRError, Profile, Ssh
|
||||||
from .nix import (
|
from .nix import (
|
||||||
|
copy_closure,
|
||||||
edit,
|
edit,
|
||||||
find_file,
|
find_file,
|
||||||
get_nixpkgs_rev,
|
get_nixpkgs_rev,
|
||||||
@ -37,8 +40,7 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
parser.add_argument("--flake", nargs="?", const=True)
|
parser.add_argument("--flake", nargs="?", const=True)
|
||||||
parser.add_argument("--no-flake", dest="flake", action="store_false")
|
parser.add_argument("--no-flake", dest="flake", action="store_false")
|
||||||
parser.add_argument("--install-bootloader", action="store_true")
|
parser.add_argument("--install-bootloader", action="store_true")
|
||||||
# TODO: add deprecated=True in Python >=3.13
|
parser.add_argument("--install-grub", action="store_true") # deprecated
|
||||||
parser.add_argument("--install-grub", action="store_true")
|
|
||||||
parser.add_argument("--profile-name", "-p", default="system")
|
parser.add_argument("--profile-name", "-p", default="system")
|
||||||
parser.add_argument("--specialisation", "-c")
|
parser.add_argument("--specialisation", "-c")
|
||||||
parser.add_argument("--rollback", action="store_true")
|
parser.add_argument("--rollback", action="store_true")
|
||||||
@ -46,12 +48,14 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
parser.add_argument("--upgrade-all", action="store_true")
|
parser.add_argument("--upgrade-all", action="store_true")
|
||||||
parser.add_argument("--json", action="store_true")
|
parser.add_argument("--json", action="store_true")
|
||||||
parser.add_argument("--sudo", action="store_true")
|
parser.add_argument("--sudo", action="store_true")
|
||||||
# TODO: add deprecated=True in Python >=3.13
|
parser.add_argument("--use-remote-sudo", action="store_true") # deprecated
|
||||||
parser.add_argument("--use-remote-sudo", dest="sudo", action="store_true")
|
parser.add_argument("--no-ssh-tty", action="store_true")
|
||||||
parser.add_argument("action", choices=Action.values(), nargs="?")
|
# parser.add_argument("--build-host") # TODO
|
||||||
|
parser.add_argument("--target-host")
|
||||||
parser.add_argument("--verbose", "-v", action="count", default=0)
|
parser.add_argument("--verbose", "-v", action="count", default=0)
|
||||||
|
parser.add_argument("action", choices=Action.values(), nargs="?")
|
||||||
|
|
||||||
common_group = parser.add_argument_group("Common flags")
|
common_group = parser.add_argument_group("nix flags")
|
||||||
common_group.add_argument("--include", "-I")
|
common_group.add_argument("--include", "-I")
|
||||||
common_group.add_argument("--max-jobs", "-j")
|
common_group.add_argument("--max-jobs", "-j")
|
||||||
common_group.add_argument("--cores")
|
common_group.add_argument("--cores")
|
||||||
@ -65,10 +69,10 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
common_group.add_argument("--repair", action="store_true")
|
common_group.add_argument("--repair", action="store_true")
|
||||||
common_group.add_argument("--option", nargs=2)
|
common_group.add_argument("--option", nargs=2)
|
||||||
|
|
||||||
nix_group = parser.add_argument_group("Classic Nix flags")
|
nix_group = parser.add_argument_group("nix classic flags")
|
||||||
nix_group.add_argument("--no-build-output", "-Q", action="store_true")
|
nix_group.add_argument("--no-build-output", "-Q", action="store_true")
|
||||||
|
|
||||||
flake_group = parser.add_argument_group("Flake flags")
|
flake_group = parser.add_argument_group("nix flakes flags")
|
||||||
flake_group.add_argument("--accept-flake-config", action="store_true")
|
flake_group.add_argument("--accept-flake-config", action="store_true")
|
||||||
flake_group.add_argument("--refresh", action="store_true")
|
flake_group.add_argument("--refresh", action="store_true")
|
||||||
flake_group.add_argument("--impure", action="store_true")
|
flake_group.add_argument("--impure", action="store_true")
|
||||||
@ -82,6 +86,9 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
flake_group.add_argument("--update-input")
|
flake_group.add_argument("--update-input")
|
||||||
flake_group.add_argument("--override-input", nargs=2)
|
flake_group.add_argument("--override-input", nargs=2)
|
||||||
|
|
||||||
|
copy_group = parser.add_argument_group("nix-copy-closure flags")
|
||||||
|
copy_group.add_argument("--use-substitutes", "-s", action="store_true")
|
||||||
|
|
||||||
args = parser.parse_args(argv[1:])
|
args = parser.parse_args(argv[1:])
|
||||||
|
|
||||||
global VERBOSE
|
global VERBOSE
|
||||||
@ -92,12 +99,20 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
if args.action == Action.DRY_RUN.value:
|
if args.action == Action.DRY_RUN.value:
|
||||||
args.action = Action.DRY_BUILD.value
|
args.action = Action.DRY_BUILD.value
|
||||||
|
|
||||||
|
# TODO: use deprecated=True in Python >=3.13
|
||||||
if args.install_grub:
|
if args.install_grub:
|
||||||
info(
|
info(
|
||||||
f"{parser.prog}: warning: --install-grub deprecated, use --install-bootloader instead"
|
f"{parser.prog}: warning: --install-grub deprecated, use --install-bootloader instead"
|
||||||
)
|
)
|
||||||
args.install_bootloader = True
|
args.install_bootloader = True
|
||||||
|
|
||||||
|
# TODO: use deprecated=True in Python >=3.13
|
||||||
|
if args.use_remote_sudo:
|
||||||
|
info(
|
||||||
|
f"{parser.prog}: warning: --use-remote-sudo deprecated, use --sudo instead"
|
||||||
|
)
|
||||||
|
args.sudo = True
|
||||||
|
|
||||||
if args.action == Action.EDIT.value and (args.file or args.attr):
|
if args.action == Action.EDIT.value and (args.file or args.attr):
|
||||||
parser.error("--file and --attr are not supported with 'edit'")
|
parser.error("--file and --attr are not supported with 'edit'")
|
||||||
|
|
||||||
@ -117,23 +132,28 @@ def execute(argv: list[str]) -> None:
|
|||||||
common_flags = flags_to_dict(
|
common_flags = flags_to_dict(
|
||||||
args,
|
args,
|
||||||
[
|
[
|
||||||
"verbose",
|
|
||||||
"include",
|
|
||||||
"max_jobs",
|
"max_jobs",
|
||||||
"cores",
|
"cores",
|
||||||
"log_format",
|
"log_format",
|
||||||
"quiet",
|
|
||||||
"print_build_logs",
|
|
||||||
"show_trace",
|
|
||||||
"keep_going",
|
"keep_going",
|
||||||
"keep_failed",
|
"keep_failed",
|
||||||
"fallback",
|
"fallback",
|
||||||
"repair",
|
"repair",
|
||||||
|
"verbose",
|
||||||
"option",
|
"option",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
nix_flags = common_flags | flags_to_dict(args, ["no_build_output"])
|
common_build_flags = common_flags | flags_to_dict(
|
||||||
flake_flags = common_flags | flags_to_dict(
|
args,
|
||||||
|
[
|
||||||
|
"include",
|
||||||
|
"quiet",
|
||||||
|
"print_build_logs",
|
||||||
|
"show_trace",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
build_flags = common_build_flags | flags_to_dict(args, ["no_build_output"])
|
||||||
|
flake_build_flags = common_build_flags | flags_to_dict(
|
||||||
args,
|
args,
|
||||||
[
|
[
|
||||||
"accept_flake_config",
|
"accept_flake_config",
|
||||||
@ -150,9 +170,15 @@ def execute(argv: list[str]) -> None:
|
|||||||
"override_input",
|
"override_input",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
copy_flags = common_flags | flags_to_dict(args, ["use_substitutes"])
|
||||||
|
|
||||||
|
# Will be cleaned up on exit automatically.
|
||||||
|
tmpdir = TemporaryDirectory(prefix="nixos-rebuild.")
|
||||||
|
tmpdir_path = Path(tmpdir.name)
|
||||||
|
|
||||||
profile = Profile.from_name(args.profile_name)
|
profile = Profile.from_name(args.profile_name)
|
||||||
flake = Flake.from_arg(args.flake)
|
flake = Flake.from_arg(args.flake)
|
||||||
|
target_host = Ssh.from_arg(args.target_host, not args.no_ssh_tty, tmpdir_path)
|
||||||
|
|
||||||
if args.upgrade or args.upgrade_all:
|
if args.upgrade or args.upgrade_all:
|
||||||
upgrade_channels(bool(args.upgrade_all))
|
upgrade_channels(bool(args.upgrade_all))
|
||||||
@ -165,7 +191,7 @@ def execute(argv: list[str]) -> None:
|
|||||||
# untrusted tree.
|
# untrusted tree.
|
||||||
can_run = action in (Action.SWITCH, Action.BOOT, Action.TEST)
|
can_run = action in (Action.SWITCH, Action.BOOT, Action.TEST)
|
||||||
if can_run and not flake:
|
if can_run and not flake:
|
||||||
nixpkgs_path = find_file("nixpkgs", **nix_flags)
|
nixpkgs_path = find_file("nixpkgs", **build_flags)
|
||||||
rev = get_nixpkgs_rev(nixpkgs_path)
|
rev = get_nixpkgs_rev(nixpkgs_path)
|
||||||
if nixpkgs_path and rev:
|
if nixpkgs_path and rev:
|
||||||
(nixpkgs_path / ".version-suffix").write_text(rev)
|
(nixpkgs_path / ".version-suffix").write_text(rev)
|
||||||
@ -175,26 +201,28 @@ def execute(argv: list[str]) -> None:
|
|||||||
info("building the system configuration...")
|
info("building the system configuration...")
|
||||||
if args.rollback:
|
if args.rollback:
|
||||||
path_to_config = rollback(profile)
|
path_to_config = rollback(profile)
|
||||||
elif flake:
|
|
||||||
path_to_config = nixos_build_flake(
|
|
||||||
"toplevel",
|
|
||||||
flake,
|
|
||||||
no_link=True,
|
|
||||||
**flake_flags,
|
|
||||||
)
|
|
||||||
set_profile(profile, path_to_config, sudo=args.sudo)
|
|
||||||
else:
|
else:
|
||||||
path_to_config = nixos_build(
|
if flake:
|
||||||
"system",
|
path_to_config = nixos_build_flake(
|
||||||
args.attr,
|
"toplevel",
|
||||||
args.file,
|
flake,
|
||||||
no_out_link=True,
|
no_link=True,
|
||||||
**nix_flags,
|
**flake_build_flags,
|
||||||
)
|
)
|
||||||
set_profile(profile, path_to_config, sudo=args.sudo)
|
else:
|
||||||
|
path_to_config = nixos_build(
|
||||||
|
"system",
|
||||||
|
args.attr,
|
||||||
|
args.file,
|
||||||
|
no_out_link=True,
|
||||||
|
**build_flags,
|
||||||
|
)
|
||||||
|
copy_closure(path_to_config, target_host, **copy_flags)
|
||||||
|
set_profile(profile, path_to_config, target_host, sudo=args.sudo)
|
||||||
switch_to_configuration(
|
switch_to_configuration(
|
||||||
path_to_config,
|
path_to_config,
|
||||||
action,
|
action,
|
||||||
|
target_host,
|
||||||
sudo=args.sudo,
|
sudo=args.sudo,
|
||||||
specialisation=args.specialisation,
|
specialisation=args.specialisation,
|
||||||
install_bootloader=args.install_bootloader,
|
install_bootloader=args.install_bootloader,
|
||||||
@ -214,7 +242,7 @@ def execute(argv: list[str]) -> None:
|
|||||||
flake,
|
flake,
|
||||||
keep_going=True,
|
keep_going=True,
|
||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
**flake_flags,
|
**flake_build_flags,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
path_to_config = nixos_build(
|
path_to_config = nixos_build(
|
||||||
@ -223,12 +251,13 @@ def execute(argv: list[str]) -> None:
|
|||||||
args.file,
|
args.file,
|
||||||
keep_going=True,
|
keep_going=True,
|
||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
**nix_flags,
|
**build_flags,
|
||||||
)
|
)
|
||||||
if action in (Action.TEST, Action.DRY_ACTIVATE):
|
if action in (Action.TEST, Action.DRY_ACTIVATE):
|
||||||
switch_to_configuration(
|
switch_to_configuration(
|
||||||
path_to_config,
|
path_to_config,
|
||||||
action,
|
action,
|
||||||
|
target_host,
|
||||||
sudo=args.sudo,
|
sudo=args.sudo,
|
||||||
specialisation=args.specialisation,
|
specialisation=args.specialisation,
|
||||||
)
|
)
|
||||||
@ -240,7 +269,7 @@ def execute(argv: list[str]) -> None:
|
|||||||
attr,
|
attr,
|
||||||
flake,
|
flake,
|
||||||
keep_going=True,
|
keep_going=True,
|
||||||
**flake_flags,
|
**flake_build_flags,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
path_to_config = nixos_build(
|
path_to_config = nixos_build(
|
||||||
@ -248,12 +277,12 @@ def execute(argv: list[str]) -> None:
|
|||||||
args.attr,
|
args.attr,
|
||||||
args.file,
|
args.file,
|
||||||
keep_going=True,
|
keep_going=True,
|
||||||
**nix_flags,
|
**build_flags,
|
||||||
)
|
)
|
||||||
vm_path = next(path_to_config.glob("bin/run-*-vm"), "./result/bin/run-*-vm")
|
vm_path = next(path_to_config.glob("bin/run-*-vm"), "./result/bin/run-*-vm")
|
||||||
print(f"Done. The virtual machine can be started by running '{vm_path}'")
|
print(f"Done. The virtual machine can be started by running '{vm_path}'")
|
||||||
case Action.EDIT:
|
case Action.EDIT:
|
||||||
edit(flake, **flake_flags)
|
edit(flake, **flake_build_flags)
|
||||||
case Action.DRY_RUN:
|
case Action.DRY_RUN:
|
||||||
assert False, "DRY_RUN should be a DRY_BUILD alias"
|
assert False, "DRY_RUN should be a DRY_BUILD alias"
|
||||||
case Action.LIST_GENERATIONS:
|
case Action.LIST_GENERATIONS:
|
||||||
|
@ -116,7 +116,7 @@ class Profile:
|
|||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class SSH:
|
class Ssh:
|
||||||
host: str
|
host: str
|
||||||
opts: list[str]
|
opts: list[str]
|
||||||
tty: bool
|
tty: bool
|
||||||
|
@ -12,6 +12,7 @@ from .models import (
|
|||||||
GenerationJson,
|
GenerationJson,
|
||||||
NRError,
|
NRError,
|
||||||
Profile,
|
Profile,
|
||||||
|
Ssh,
|
||||||
)
|
)
|
||||||
from .process import run_wrapper
|
from .process import run_wrapper
|
||||||
from .utils import Args, dict_to_flags, info
|
from .utils import Args, dict_to_flags, info
|
||||||
@ -19,6 +20,28 @@ from .utils import Args, dict_to_flags, info
|
|||||||
FLAKE_FLAGS: Final = ["--extra-experimental-features", "nix-command flakes"]
|
FLAKE_FLAGS: Final = ["--extra-experimental-features", "nix-command flakes"]
|
||||||
|
|
||||||
|
|
||||||
|
def copy_closure(
|
||||||
|
closure: Path,
|
||||||
|
target_host: Ssh | None,
|
||||||
|
**copy_flags: Args,
|
||||||
|
) -> None:
|
||||||
|
host = target_host
|
||||||
|
if not host:
|
||||||
|
return
|
||||||
|
|
||||||
|
run_wrapper(
|
||||||
|
[
|
||||||
|
"nix-copy-closure",
|
||||||
|
*(dict_to_flags(copy_flags)),
|
||||||
|
"--to",
|
||||||
|
host.host,
|
||||||
|
closure,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
extra_env={"NIX_SSHOPTS": " ".join(host.opts)},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def edit(flake: Flake | None, **flake_flags: Args) -> None:
|
def edit(flake: Flake | None, **flake_flags: Args) -> None:
|
||||||
"Try to find and open NixOS configuration file in editor."
|
"Try to find and open NixOS configuration file in editor."
|
||||||
if flake:
|
if flake:
|
||||||
@ -277,16 +300,25 @@ def rollback_temporary_profile(profile: Profile) -> Path | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def set_profile(profile: Profile, path_to_config: Path, sudo: bool) -> None:
|
def set_profile(
|
||||||
|
profile: Profile,
|
||||||
|
path_to_config: Path,
|
||||||
|
target_host: Ssh | None,
|
||||||
|
sudo: bool,
|
||||||
|
) -> None:
|
||||||
"Set a path as the current active Nix profile."
|
"Set a path as the current active Nix profile."
|
||||||
run_wrapper(
|
run_wrapper(
|
||||||
["nix-env", "-p", profile.path, "--set", path_to_config], check=True, sudo=sudo
|
["nix-env", "-p", profile.path, "--set", path_to_config],
|
||||||
|
check=True,
|
||||||
|
remote=target_host,
|
||||||
|
sudo=sudo,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def switch_to_configuration(
|
def switch_to_configuration(
|
||||||
path_to_config: Path,
|
path_to_config: Path,
|
||||||
action: Action,
|
action: Action,
|
||||||
|
target_host: Ssh | None,
|
||||||
sudo: bool,
|
sudo: bool,
|
||||||
install_bootloader: bool = False,
|
install_bootloader: bool = False,
|
||||||
specialisation: str | None = None,
|
specialisation: str | None = None,
|
||||||
@ -310,6 +342,7 @@ def switch_to_configuration(
|
|||||||
[path_to_config / "bin/switch-to-configuration", str(action)],
|
[path_to_config / "bin/switch-to-configuration", str(action)],
|
||||||
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1" if install_bootloader else "0"},
|
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1" if install_bootloader else "0"},
|
||||||
check=True,
|
check=True,
|
||||||
|
remote=target_host,
|
||||||
sudo=sudo,
|
sudo=sudo,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
from typing import Sequence, TypedDict, Unpack
|
from typing import Sequence, TypedDict, Unpack
|
||||||
|
|
||||||
from .models import SSH
|
from .models import Ssh
|
||||||
|
|
||||||
|
|
||||||
# Not exhaustive, but we can always extend it later.
|
# Not exhaustive, but we can always extend it later.
|
||||||
@ -22,7 +22,7 @@ def run_wrapper(
|
|||||||
check: bool, # make it explicit so we always know if the code is handling errors
|
check: bool, # make it explicit so we always know if the code is handling errors
|
||||||
env: dict[str, str] | None = None, # replaces the current environment
|
env: dict[str, str] | None = None, # replaces the current environment
|
||||||
extra_env: dict[str, str] | None = None, # appends to the current environment
|
extra_env: dict[str, str] | None = None, # appends to the current environment
|
||||||
remote: SSH | None = None,
|
remote: Ssh | None = None,
|
||||||
sudo: bool = False,
|
sudo: bool = False,
|
||||||
**kwargs: Unpack[RunKwargs],
|
**kwargs: Unpack[RunKwargs],
|
||||||
) -> subprocess.CompletedProcess[str]:
|
) -> subprocess.CompletedProcess[str]:
|
||||||
|
@ -208,6 +208,109 @@ def test_execute_nix_switch_flake(mock_run: Any, tmp_path: Path) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@patch.dict(nr.process.os.environ, {}, clear=True)
|
||||||
|
@patch(get_qualified_name(nr.process.subprocess.run), autospec=True)
|
||||||
|
@patch(get_qualified_name(nr.TemporaryDirectory, nr)) # can't autospec
|
||||||
|
def test_execute_nix_switch_flake_remote(
|
||||||
|
mock_tmpdir: Any,
|
||||||
|
mock_run: Any,
|
||||||
|
tmp_path: Path,
|
||||||
|
) -> None:
|
||||||
|
config_path = tmp_path / "test"
|
||||||
|
config_path.touch()
|
||||||
|
mock_run.side_effect = [
|
||||||
|
# nixos_build_flake
|
||||||
|
CompletedProcess([], 0, str(config_path)),
|
||||||
|
# set_profile
|
||||||
|
CompletedProcess([], 0),
|
||||||
|
# copy_closure
|
||||||
|
CompletedProcess([], 0),
|
||||||
|
# switch_to_configuration
|
||||||
|
CompletedProcess([], 0),
|
||||||
|
]
|
||||||
|
mock_tmpdir.return_value.name = "/tmp/test"
|
||||||
|
|
||||||
|
nr.execute(
|
||||||
|
[
|
||||||
|
"nixos-rebuild",
|
||||||
|
"switch",
|
||||||
|
"--flake",
|
||||||
|
"/path/to/config#hostname",
|
||||||
|
"--use-remote-sudo",
|
||||||
|
"--target-host",
|
||||||
|
"user@localhost",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_run.call_count == 4
|
||||||
|
mock_run.assert_has_calls(
|
||||||
|
[
|
||||||
|
call(
|
||||||
|
[
|
||||||
|
"nix",
|
||||||
|
"--extra-experimental-features",
|
||||||
|
"nix-command flakes",
|
||||||
|
"build",
|
||||||
|
"--print-out-paths",
|
||||||
|
"/path/to/config#nixosConfigurations.hostname.config.system.build.toplevel",
|
||||||
|
"--no-link",
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
stdout=PIPE,
|
||||||
|
**DEFAULT_RUN_KWARGS,
|
||||||
|
),
|
||||||
|
call(
|
||||||
|
["nix-copy-closure", "--to", "user@localhost", config_path],
|
||||||
|
check=True,
|
||||||
|
**DEFAULT_RUN_KWARGS,
|
||||||
|
),
|
||||||
|
call(
|
||||||
|
[
|
||||||
|
"ssh",
|
||||||
|
"-t",
|
||||||
|
"-o",
|
||||||
|
"ControlMaster=auto",
|
||||||
|
"-o",
|
||||||
|
"ControlPath=/tmp/test/ssh-%n",
|
||||||
|
"-o",
|
||||||
|
"ControlPersist=60",
|
||||||
|
"user@localhost",
|
||||||
|
"--",
|
||||||
|
"sudo",
|
||||||
|
"nix-env",
|
||||||
|
"-p",
|
||||||
|
Path("/nix/var/nix/profiles/system"),
|
||||||
|
"--set",
|
||||||
|
config_path,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
**DEFAULT_RUN_KWARGS,
|
||||||
|
),
|
||||||
|
call(
|
||||||
|
[
|
||||||
|
"ssh",
|
||||||
|
"-t",
|
||||||
|
"-o",
|
||||||
|
"ControlMaster=auto",
|
||||||
|
"-o",
|
||||||
|
"ControlPath=/tmp/test/ssh-%n",
|
||||||
|
"-o",
|
||||||
|
"ControlPersist=60",
|
||||||
|
"user@localhost",
|
||||||
|
"--",
|
||||||
|
"sudo",
|
||||||
|
"env",
|
||||||
|
"NIXOS_INSTALL_BOOTLOADER=0",
|
||||||
|
config_path / "bin/switch-to-configuration",
|
||||||
|
"switch",
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
**DEFAULT_RUN_KWARGS,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@patch(get_qualified_name(nr.process.subprocess.run), autospec=True)
|
@patch(get_qualified_name(nr.process.subprocess.run), autospec=True)
|
||||||
def test_execute_switch_rollback(mock_run: Any, tmp_path: Path) -> None:
|
def test_execute_switch_rollback(mock_run: Any, tmp_path: Path) -> None:
|
||||||
nixpkgs_path = tmp_path / "nixpkgs"
|
nixpkgs_path = tmp_path / "nixpkgs"
|
||||||
|
@ -101,7 +101,8 @@ def test_profile_from_name(mock_mkdir: Any) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_ssh_from_name(monkeypatch: Any, tmpdir: Path) -> None:
|
def test_ssh_from_name(monkeypatch: Any, tmpdir: Path) -> None:
|
||||||
assert m.SSH.from_arg("user@localhost", None, tmpdir) == m.SSH(
|
monkeypatch.setenv("NIX_SSHOPTS", "")
|
||||||
|
assert m.Ssh.from_arg("user@localhost", None, tmpdir) == m.Ssh(
|
||||||
"user@localhost",
|
"user@localhost",
|
||||||
[
|
[
|
||||||
"-o",
|
"-o",
|
||||||
@ -114,8 +115,8 @@ def test_ssh_from_name(monkeypatch: Any, tmpdir: Path) -> None:
|
|||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
|
|
||||||
monkeypatch.setenv("NIX_SSHOPTS", "-f foo -b bar", tmpdir)
|
monkeypatch.setenv("NIX_SSHOPTS", "-f foo -b bar")
|
||||||
assert m.SSH.from_arg("user@localhost", True, tmpdir) == m.SSH(
|
assert m.Ssh.from_arg("user@localhost", True, tmpdir) == m.Ssh(
|
||||||
"user@localhost",
|
"user@localhost",
|
||||||
[
|
[
|
||||||
"-f",
|
"-f",
|
||||||
|
@ -12,6 +12,21 @@ import nixos_rebuild.nix as n
|
|||||||
from .helpers import get_qualified_name
|
from .helpers import get_qualified_name
|
||||||
|
|
||||||
|
|
||||||
|
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||||
|
def test_copy_closure(mock_run: Any) -> None:
|
||||||
|
closure = Path("/path/to/closure")
|
||||||
|
n.copy_closure(closure, None)
|
||||||
|
mock_run.assert_not_called()
|
||||||
|
|
||||||
|
target_host = m.Ssh("user@host", ["--ssh", "opt"], False)
|
||||||
|
n.copy_closure(closure, target_host)
|
||||||
|
mock_run.assert_called_with(
|
||||||
|
["nix-copy-closure", "--to", "user@host", closure],
|
||||||
|
check=True,
|
||||||
|
extra_env={"NIX_SSHOPTS": "--ssh opt"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||||
def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
|
def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
|
||||||
# Flake
|
# Flake
|
||||||
@ -290,11 +305,17 @@ def test_rollback_temporary_profile(tmp_path: Path) -> None:
|
|||||||
def test_set_profile(mock_run: Any) -> None:
|
def test_set_profile(mock_run: Any) -> None:
|
||||||
profile_path = Path("/path/to/profile")
|
profile_path = Path("/path/to/profile")
|
||||||
config_path = Path("/path/to/config")
|
config_path = Path("/path/to/config")
|
||||||
n.set_profile(m.Profile("system", profile_path), config_path, sudo=False)
|
n.set_profile(
|
||||||
|
m.Profile("system", profile_path),
|
||||||
|
config_path,
|
||||||
|
target_host=None,
|
||||||
|
sudo=False,
|
||||||
|
)
|
||||||
|
|
||||||
mock_run.assert_called_with(
|
mock_run.assert_called_with(
|
||||||
["nix-env", "-p", profile_path, "--set", config_path],
|
["nix-env", "-p", profile_path, "--set", config_path],
|
||||||
check=True,
|
check=True,
|
||||||
|
remote=None,
|
||||||
sudo=False,
|
sudo=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -311,6 +332,7 @@ def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
|
|||||||
profile_path,
|
profile_path,
|
||||||
m.Action.SWITCH,
|
m.Action.SWITCH,
|
||||||
sudo=False,
|
sudo=False,
|
||||||
|
target_host=None,
|
||||||
specialisation=None,
|
specialisation=None,
|
||||||
install_bootloader=False,
|
install_bootloader=False,
|
||||||
)
|
)
|
||||||
@ -319,6 +341,7 @@ def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
|
|||||||
extra_env={"NIXOS_INSTALL_BOOTLOADER": "0"},
|
extra_env={"NIXOS_INSTALL_BOOTLOADER": "0"},
|
||||||
check=True,
|
check=True,
|
||||||
sudo=False,
|
sudo=False,
|
||||||
|
remote=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises(m.NRError) as e:
|
with pytest.raises(m.NRError) as e:
|
||||||
@ -326,6 +349,7 @@ def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
|
|||||||
config_path,
|
config_path,
|
||||||
m.Action.BOOT,
|
m.Action.BOOT,
|
||||||
sudo=False,
|
sudo=False,
|
||||||
|
target_host=None,
|
||||||
specialisation="special",
|
specialisation="special",
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
@ -342,6 +366,7 @@ def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
|
|||||||
Path("/path/to/config"),
|
Path("/path/to/config"),
|
||||||
m.Action.TEST,
|
m.Action.TEST,
|
||||||
sudo=True,
|
sudo=True,
|
||||||
|
target_host=m.Ssh("user@localhost", [], False),
|
||||||
install_bootloader=True,
|
install_bootloader=True,
|
||||||
specialisation="special",
|
specialisation="special",
|
||||||
)
|
)
|
||||||
@ -353,6 +378,7 @@ def test_switch_to_configuration(mock_run: Any, monkeypatch: Any) -> None:
|
|||||||
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1"},
|
extra_env={"NIXOS_INSTALL_BOOTLOADER": "1"},
|
||||||
check=True,
|
check=True,
|
||||||
sudo=True,
|
sudo=True,
|
||||||
|
remote=m.Ssh("user@localhost", [], False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ def test_run(mock_run: Any) -> None:
|
|||||||
p.run_wrapper(
|
p.run_wrapper(
|
||||||
["test", "--with", "flags"],
|
["test", "--with", "flags"],
|
||||||
check=True,
|
check=True,
|
||||||
remote=m.SSH("user@localhost", ["--ssh", "opt"], False),
|
remote=m.Ssh("user@localhost", ["--ssh", "opt"], False),
|
||||||
)
|
)
|
||||||
mock_run.assert_called_with(
|
mock_run.assert_called_with(
|
||||||
["ssh", "--ssh", "opt", "user@localhost", "--", "test", "--with", "flags"],
|
["ssh", "--ssh", "opt", "user@localhost", "--", "test", "--with", "flags"],
|
||||||
@ -69,7 +69,7 @@ def test_run(mock_run: Any) -> None:
|
|||||||
check=True,
|
check=True,
|
||||||
sudo=True,
|
sudo=True,
|
||||||
extra_env={"FOO": "bar"},
|
extra_env={"FOO": "bar"},
|
||||||
remote=m.SSH("user@localhost", ["--ssh", "opt"], True),
|
remote=m.Ssh("user@localhost", ["--ssh", "opt"], True),
|
||||||
)
|
)
|
||||||
mock_run.assert_called_with(
|
mock_run.assert_called_with(
|
||||||
[
|
[
|
||||||
@ -97,5 +97,5 @@ def test_run(mock_run: Any) -> None:
|
|||||||
["test", "--with", "flags"],
|
["test", "--with", "flags"],
|
||||||
check=False,
|
check=False,
|
||||||
env={"foo": "bar"},
|
env={"foo": "bar"},
|
||||||
remote=m.SSH("user@localhost", [], False),
|
remote=m.Ssh("user@localhost", [], False),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user