Compare commits
2 commits
d164f502a1
...
744bbdb245
Author | SHA1 | Date | |
---|---|---|---|
June | 744bbdb245 | ||
June | a7772aa154 |
|
@ -20,7 +20,7 @@ However to override aspects of the target host for specific or all hosts, infra-
|
|||
|
||||
## Configuration
|
||||
|
||||
infra-rebuild accepts optional configuration in a `deployment_configuration.json`. \
|
||||
infra-rebuild accepts optional configuration in a `deployment_configuration.json` present in the flake repos root. \
|
||||
The following keys are available to be set for configuring various aspects of deployment for specific or all hosts:
|
||||
|
||||
- `default.targetPort`: A default port to use for connecting to all host.
|
||||
|
|
|
@ -3,54 +3,118 @@ import click
|
|||
from infra_rebuild import operations
|
||||
|
||||
reboot_option_help_text = "Reboot the target hosts after running the operation."
|
||||
flake_option_help_text = "URI of the flake to use. Defaults to the current direcory."
|
||||
|
||||
|
||||
@click.group(context_settings={"help_option_names": ["-h", "--help"]}, invoke_without_command=True)
|
||||
def initialize_recursive_option(ctx, option_name, default_value):
|
||||
"""Helper function for initializing a recursive option.
|
||||
|
||||
Arguments:
|
||||
`ctx` -- The click context passed to the calling command.
|
||||
`option_name` -- The name of the option in question.
|
||||
`default_value` -- A default value for the option.
|
||||
|
||||
Simply sets the value of the recursive option (`ctx.obj[option_name]`) to `default_value`.
|
||||
"""
|
||||
ctx.obj[option_name] = default_value
|
||||
|
||||
|
||||
def update_recursive_option(ctx, option_name, given_value):
|
||||
"""Helper function for updating a recursive option.
|
||||
|
||||
Arguments:
|
||||
ctx -- The click context passed to the calling command.
|
||||
option_name -- The name of the option in question.
|
||||
given_value -- The value the calling command received for the option.
|
||||
|
||||
It overrides the current value for the recursive option (`ctx.obj[option_name]`) with `given_value`, if `given_value` isn't `None`.
|
||||
This ensure precedence of the innermost command (since the innermost command would call this function last).
|
||||
""" # noqa: E501
|
||||
if given_value is not None:
|
||||
ctx.obj[option_name] = given_value
|
||||
|
||||
|
||||
@click.group(
|
||||
context_settings={"help_option_names": ["-h", "--help"]},
|
||||
invoke_without_command=True,
|
||||
help="""Runs COMMAND for each given host.
|
||||
|
||||
The commands mirror the operations of nixos-rebuild (with the exception of reboot, which is simply a convenience alias for "boot --reboot").
|
||||
|
||||
For commands acting remotely (boot, reboot, switch, test) infra-rebuild tries to be useful without any configuration by taking the FQDN from the hosts NixOS configuration as the target host.
|
||||
However infra-rebuild also accepts configuration to override various aspects of the target host for specific or all hosts.
|
||||
See the documentation on configuration for more information.""", # noqa: E501
|
||||
)
|
||||
@click.version_option(prog_name="infra-rebuild")
|
||||
def infra_rebuild():
|
||||
pass
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
def infra_rebuild(ctx, flake):
|
||||
ctx.ensure_object(dict)
|
||||
initialize_recursive_option(ctx, "flake", ".")
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def build(hosts):
|
||||
operations.run("build", hosts)
|
||||
def build(ctx, flake, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("build", hosts, ctx.obj["flake"])
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def build_vm(hosts):
|
||||
operations.run("build-vm", hosts)
|
||||
def build_vm(ctx, flake, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("build-vm", hosts, ctx.obj["flake"])
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def build_vm_with_bootloader(hosts):
|
||||
operations.run("build-vm-with-bootloader", hosts)
|
||||
def build_vm_with_bootloader(ctx, flake, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("build-vm-with-bootloader", hosts, ctx.obj["flake"])
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.option("--reboot", is_flag=True, help=reboot_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def switch(hosts, reboot):
|
||||
operations.run("switch", hosts, reboot)
|
||||
def switch(ctx, flake, reboot, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("switch", hosts, ctx.obj["flake"], reboot)
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.option("--reboot", is_flag=True, help=reboot_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def boot(hosts, reboot):
|
||||
operations.run("boot", hosts, reboot)
|
||||
def boot(ctx, flake, reboot, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("boot", hosts, ctx.obj["flake"], reboot)
|
||||
|
||||
|
||||
@infra_rebuild.command()
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.option("--reboot", is_flag=True, help=reboot_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def test(hosts, reboot):
|
||||
operations.run("test", hosts, reboot)
|
||||
def test(ctx, flake, reboot, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("test", hosts, ctx.obj["flake"], reboot)
|
||||
|
||||
|
||||
@infra_rebuild.command(short_help=" ", help="This operation is a convenience alias for boot --reboot.")
|
||||
@click.pass_context
|
||||
@click.option("--flake", help=flake_option_help_text)
|
||||
@click.argument("hosts", nargs=-1)
|
||||
def reboot(hosts):
|
||||
operations.run("boot", hosts, True)
|
||||
def reboot(ctx, flake, hosts):
|
||||
update_recursive_option(ctx, "flake", flake)
|
||||
operations.run("boot", hosts, ctx.obj["flake"], True)
|
||||
|
|
|
@ -6,7 +6,27 @@ import sys
|
|||
from infra_rebuild import msg
|
||||
|
||||
|
||||
def run(operation, hosts, reboot=False): # noqa: FBT002 - having reboot as a Boolean positional argument is fine I think # fmt: skip
|
||||
def run(operation, hosts, flake_uri, reboot=False): # noqa: FBT002 - having reboot as a Boolean positional argument is fine I think # fmt: skip
|
||||
try:
|
||||
flake_archive_json = subprocess.run(
|
||||
["nix", "flake", "archive", "--json", f"{flake_uri}"], # noqa: S607, S603 - can't know what the users system looks like, maybe do some kind of validation for the flake_uri in the future?
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
) # fmt: skip
|
||||
try:
|
||||
flake_archive = json.loads(flake_archive_json.stdout)
|
||||
except json.JSONDecodeError:
|
||||
msg.error("Internal Error: Couldn't parse the output of \"nix flake archive\".")
|
||||
sys.exit(1)
|
||||
|
||||
if not flake_archive["path"]:
|
||||
msg.error("Internal Error: The \"nix flake archive\" output doesn't include a path.")
|
||||
sys.exit(1)
|
||||
except subprocess.CalledProcessError:
|
||||
msg.error("Error: Couldn't archive the provided flake.")
|
||||
sys.exit(1)
|
||||
|
||||
match operation:
|
||||
case "build" | "build-vm" | "build-vm-with-bootloader":
|
||||
act_remotely = False
|
||||
|
@ -22,23 +42,23 @@ def run(operation, hosts, reboot=False): # noqa: FBT002 - having reboot as a Bo
|
|||
continue
|
||||
|
||||
if act_remotely:
|
||||
remote(operation, host, reboot)
|
||||
remote(operation, host, flake_archive, reboot)
|
||||
else:
|
||||
local(operation, host)
|
||||
local(operation, host, flake_archive)
|
||||
|
||||
|
||||
def local(operation, host):
|
||||
def local(operation, host, flake_archive):
|
||||
msg.info(f"Running nixos-rebuild {operation} for {host}...")
|
||||
subprocess.run(
|
||||
["nixos-rebuild", operation, "--flake", f".#{host}"], # noqa: S607, S603 - can't know what the users system looks like, maybe do some kind of validation for the given host in the future?
|
||||
["nixos-rebuild", operation, "--flake", f"{flake_archive['path']}#{host}"], # noqa: S607, S603 - can't know what the users system looks like, maybe do some kind of validation for the given host in the future?
|
||||
check=False
|
||||
) # fmt: skip
|
||||
|
||||
|
||||
def remote(operation, host, reboot=False): # noqa: FBT002 - having reboot as a Boolean positional argument is fine I think # fmt: skip
|
||||
def remote(operation, host, flake_archive, reboot=False): # noqa: FBT002 - having reboot as a Boolean positional argument is fine I think # fmt: skip
|
||||
config = None
|
||||
try:
|
||||
with open("deployment_configuration.json") as config_file:
|
||||
with open(f"{flake_archive['path']}/deployment_configuration.json") as config_file:
|
||||
try:
|
||||
config = json.load(config_file)
|
||||
except json.JSONDecodeError:
|
||||
|
@ -62,7 +82,7 @@ def remote(operation, host, reboot=False): # noqa: FBT002 - having reboot as a
|
|||
pass
|
||||
if not target_hostname:
|
||||
nix_config_fqdn = subprocess.run(
|
||||
["nix", "eval", "--raw", f".#nixosConfigurations.{host}.config.networking.fqdn"], # noqa: S607, S603 - can't know what the users system looks like, maybe do some kind of validation for host in the future?
|
||||
["nix", "eval", "--raw", f"{flake_archive['path']}#nixosConfigurations.{host}.config.networking.fqdn"], # noqa: S607, S603 - can't know what the users system looks like, maybe do some kind of validation for host in the future?
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
|
@ -119,7 +139,7 @@ def remote(operation, host, reboot=False): # noqa: FBT002 - having reboot as a
|
|||
msg.info(f"Running nixos-rebuild {operation} for {host} on {target_host}...")
|
||||
|
||||
nixos_rebuild = subprocess.run(
|
||||
["nixos-rebuild", operation, "--flake", f".#{host}", "--target-host", target_host, "--use-substitutes", "--use-remote-sudo"], # noqa: S607, S603, E501 - can't know what the users system looks like, maybe do some kind of validation for the given host in the future?, not breaking up the command makes it more readable
|
||||
["nixos-rebuild", operation, "--flake", f"{flake_archive['path']}#{host}", "--target-host", target_host, "--use-substitutes", "--use-remote-sudo"], # noqa: S607, S603, E501 - can't know what the users system looks like, maybe do some kind of validation for the given host in the future?, not breaking up the command makes it more readable
|
||||
env=nixos_rebuild_env,
|
||||
check=False,
|
||||
) # fmt: skip
|
||||
|
|
Loading…
Reference in a new issue