]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Adding an Enum class for verb comparison across Mkosi's code.
authorgsegatti <gabrielsegatti2@gmail.com>
Tue, 22 Feb 2022 11:05:35 +0000 (03:05 -0800)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 23 Feb 2022 13:27:37 +0000 (13:27 +0000)
mkosi/__init__.py
mkosi/backend.py
mkosi/machine.py
tests/test_config_parser.py
tests/test_parse_load_args.py

index 28538f44b86c947b7d44f8a8f2aea08df1fe121f..eed7c2a995869013fa5c2ab545f276c6c6868440 100644 (file)
@@ -77,6 +77,7 @@ from .backend import (
     PartitionIdentifier,
     PartitionTable,
     SourceFileTransfer,
+    Verb,
     die,
     install_grub,
     nspawn_params_for_blockdev_access,
@@ -115,10 +116,9 @@ else:
 SomeIO = Union[BinaryIO, TextIO]
 PathString = Union[Path, str]
 
-MKOSI_COMMANDS_CMDLINE = ("build", "shell", "boot", "qemu", "ssh")
-MKOSI_COMMANDS_NEED_BUILD = ("shell", "boot", "qemu", "serve")
-MKOSI_COMMANDS_SUDO = ("build", "clean", "shell", "boot", "qemu", "serve")
-MKOSI_COMMANDS = ("build", "clean", "help", "summary", "genkey", "bump", "serve") + MKOSI_COMMANDS_CMDLINE
+MKOSI_COMMANDS_NEED_BUILD = (Verb.shell, Verb.boot, Verb.qemu, Verb.serve)
+MKOSI_COMMANDS_SUDO = (Verb.build, Verb.clean, Verb.shell, Verb.boot, Verb.qemu, Verb.serve)
+MKOSI_COMMANDS_CMDLINE = (Verb.build, Verb.shell, Verb.boot, Verb.qemu, Verb.ssh)
 
 DRACUT_SYSTEMD_EXTRAS = [
     "/usr/bin/systemd-repart",
@@ -5083,9 +5083,9 @@ def create_parser() -> ArgumentParserMkosi:
     parser = ArgumentParserMkosi(prog="mkosi", description="Build Bespoke OS Images", add_help=False)
 
     group = parser.add_argument_group("Commands")
-    group.add_argument("verb", choices=MKOSI_COMMANDS, default="build", help="Operation to execute")
+    group.add_argument("verb", type=Verb, choices=list(Verb), default=Verb.build, help="Operation to execute")
     group.add_argument(
-        "cmdline", nargs=argparse.REMAINDER, help="The command line to use for " + str(MKOSI_COMMANDS_CMDLINE)[1:-1]
+        "cmdline", nargs=argparse.REMAINDER, help="The command line to use for " + str([verb.name for verb in MKOSI_COMMANDS_CMDLINE])[1:-1]
     )
     group.add_argument("-h", "--help", action="help", help="Show this help")
     group.add_argument("--version", action="version", version="%(prog)s " + __version__)
@@ -5703,9 +5703,9 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> Dict[str, argparse.Names
     # values of positional arguments. Make sure the verb command gets explicitly passed.
     # Insert a -- before the positional verb argument otherwise it might be considered as an argument of
     # a parameter with nargs='?'. For example mkosi -i summary would be treated as -i=summary.
-    for verb in MKOSI_COMMANDS:
+    for verb in Verb:
         try:
-            v_i = argv.index(verb)
+            v_i = argv.index(verb.name)
         except ValueError:
             continue
 
@@ -5718,7 +5718,7 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> Dict[str, argparse.Names
     # First run of command line arguments parsing to get the directory of mkosi.default file and the verb argument.
     args_pre_parsed, _ = parser.parse_known_args(argv)
 
-    if args_pre_parsed.verb == "help":
+    if args_pre_parsed.verb == Verb.help:
         parser.print_help()
         sys.exit(0)
 
@@ -5902,7 +5902,7 @@ def empty_directory(path: Path) -> None:
 
 
 def unlink_output(args: MkosiArgs) -> None:
-    if not args.force and args.verb != "clean":
+    if not args.force and args.verb != Verb.clean:
         return
 
     if not args.skip_final_phase:
@@ -5942,7 +5942,7 @@ def unlink_output(args: MkosiArgs) -> None:
     # remove the downloaded package cache if the user specified one
     # additional "--force".
 
-    if args.verb == "clean":
+    if args.verb == Verb.clean:
         remove_build_cache = args.force > 0
         remove_package_cache = args.force > 1
     else:
@@ -6196,7 +6196,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs:
     args.extra_search_paths = expand_paths(args.extra_search_paths)
 
     if args.cmdline and args.verb not in MKOSI_COMMANDS_CMDLINE:
-        die("Additional parameters only accepted for " + str(MKOSI_COMMANDS_CMDLINE)[1:-1] + " invocations.")
+        die("Additional parameters only accepted for " + str([verb.name for verb in MKOSI_COMMANDS_CMDLINE])[1:-1] + " invocations.")
 
     if args.output_format is None:
         args.output_format = OutputFormat.gpt_ext4
@@ -6348,7 +6348,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs:
         else:
             warn("Ignoring configured output directory as output file is a qualified path.")
 
-    if args.incremental or args.verb == "clean":
+    if args.incremental or args.verb == Verb.clean:
         if args.image_id is not None:
             # If the image ID is specified, use cache file names that are independent of the image versions, so that
             # rebuilding and bumping versions is cheap and reuses previous versions if cached.
@@ -6479,8 +6479,8 @@ def load_args(args: argparse.Namespace) -> MkosiArgs:
                 "UEFI SecureBoot or signed Verity enabled, but couldn't find certificate. (Consider placing it in mkosi.secure-boot.crt?)"
             )  # NOQA: E501
 
-    if args.verb in ("shell", "boot"):
-        opname = "acquire shell" if args.verb == "shell" else "boot"
+    if args.verb in (Verb.shell, Verb.boot):
+        opname = "acquire shell" if args.verb == Verb.shell else "boot"
         if args.output_format in (OutputFormat.tar, OutputFormat.cpio):
             die(f"Sorry, can't {opname} with a {args.output_format} archive.")
         if should_compress_output(args):
@@ -6488,11 +6488,11 @@ def load_args(args: argparse.Namespace) -> MkosiArgs:
         if args.qcow2:
             die(f"Sorry, can't {opname} using a qcow2 image.")
 
-    if args.verb == "qemu":
+    if args.verb == Verb.qemu:
         if not args.output_format.is_disk():
             die("Sorry, can't boot non-disk images with qemu.")
 
-    if needs_build(args) and args.verb == "qemu" and not args.bootable:
+    if needs_build(args) and args.verb == Verb.qemu and not args.bootable:
         die("Images built without the --bootable option cannot be booted using qemu")
 
     if needs_build(args) and args.qemu_headless and not args.bootable:
@@ -6542,7 +6542,7 @@ def load_args(args: argparse.Namespace) -> MkosiArgs:
     if args.source_file_transfer_final == SourceFileTransfer.mount:
         die("Sorry, --source-file-transfer-final=mount is not supported")
 
-    if args.skip_final_phase and args.verb != "build":
+    if args.skip_final_phase and args.verb != Verb.build:
         die("--skip-final-phase can only be used when building an image using 'mkosi build'")
 
     if args.ssh_timeout < 0:
@@ -6643,7 +6643,7 @@ def line_join_list(array: Sequence[PathString]) -> str:
 def print_summary(args: MkosiArgs) -> None:
     # FIXME: normal print
     MkosiPrinter.info("COMMANDS:")
-    MkosiPrinter.info("                      verb: " + args.verb)
+    MkosiPrinter.info(f"                      verb: {args.verb}")
     MkosiPrinter.info("                   cmdline: " + " ".join(args.cmdline))
     MkosiPrinter.info("\nDISTRIBUTION:")
     MkosiPrinter.info("              Distribution: " + args.distribution.name)
@@ -7378,14 +7378,14 @@ def has_networkd_vm_vt() -> bool:
 def ensure_networkd(args: MkosiArgs) -> bool:
     networkd_is_running = run(["systemctl", "is-active", "--quiet", "systemd-networkd"], check=False).returncode == 0
     if not networkd_is_running:
-        if args.verb != "ssh":
+        if args.verb != Verb.ssh:
             # Some programs will use 'mkosi ssh' with pexpect, so don't print warnings that will break
             # them.
             warn("--network-veth requires systemd-networkd to be running to initialize the host interface "
                  "of the veth link ('systemctl enable --now systemd-networkd')")
         return False
 
-    if args.verb == "qemu" and not has_networkd_vm_vt():
+    if args.verb == Verb.qemu and not has_networkd_vm_vt():
         warn(dedent(r"""\
             mkosi didn't find 80-vm-vt.network. This is one of systemd's built-in
             systemd-networkd config files which configures vt-* interfaces.
@@ -7432,7 +7432,7 @@ def run_shell_cmdline(args: MkosiArgs) -> List[str]:
     if args.nspawn_settings is not None:
         cmdline += ["--settings=trusted"]
 
-    if args.verb == "boot":
+    if args.verb == Verb.boot:
         cmdline += ["--boot"]
     else:
         cmdline += nspawn_rlimit_params()
@@ -7452,7 +7452,7 @@ def run_shell_cmdline(args: MkosiArgs) -> List[str]:
     if args.cmdline:
         # If the verb is 'shell', args.cmdline contains the command to run.
         # Otherwise, the verb is 'boot', and we assume args.cmdline contains nspawn arguments.
-        if args.verb == "shell":
+        if args.verb == Verb.shell:
             cmdline += ["--"]
         cmdline += args.cmdline
 
@@ -7697,7 +7697,7 @@ def find_address(args: MkosiArgs) -> Tuple[str, str]:
 
 
 def run_command_image(args: MkosiArgs, commands: Sequence[str], timeout: int, check: bool, stdout: _FILE = sys.stdout, stderr: _FILE = sys.stderr) -> CompletedProcess:
-    if args.verb == "qemu":
+    if args.verb == Verb.qemu:
         return run_ssh(args, commands, check, stdout, stderr, timeout)
     else:
         cmdline = ["systemd-run", "--quiet", "--wait", "--pipe", "-M", virt_name(args), "/usr/bin/env", *commands]
@@ -7877,7 +7877,7 @@ def expand_specifier(s: str) -> str:
 
 
 def needs_build(args: Union[argparse.Namespace, MkosiArgs]) -> bool:
-    return args.verb == "build" or (args.verb in MKOSI_COMMANDS_NEED_BUILD and (not args.output.exists() or args.force > 0))
+    return args.verb == Verb.build or (args.verb in MKOSI_COMMANDS_NEED_BUILD and (not args.output.exists() or args.force > 0))
 
 
 def run_verb(raw: argparse.Namespace) -> None:
@@ -7885,20 +7885,20 @@ def run_verb(raw: argparse.Namespace) -> None:
 
     prepend_to_environ_path(args.extra_search_paths)
 
-    if args.verb == "genkey":
+    if args.verb == Verb.genkey:
         generate_secure_boot_key(args)
 
-    if args.verb == "bump":
+    if args.verb == Verb.bump:
         bump_image_version(args)
 
     if args.verb in MKOSI_COMMANDS_SUDO:
         check_root()
         unlink_output(args)
 
-    if args.verb == "build":
+    if args.verb == Verb.build:
         check_output(args)
 
-    if args.verb == "summary":
+    if args.verb == Verb.summary:
         print_summary(args)
 
     if needs_build(args):
@@ -7914,14 +7914,14 @@ def run_verb(raw: argparse.Namespace) -> None:
 
         print_output_size(args)
 
-    if args.verb in ("shell", "boot"):
+    if args.verb in (Verb.shell, Verb.boot):
         run_shell(args)
 
-    if args.verb == "qemu":
+    if args.verb == Verb.qemu:
         run_qemu(args)
 
-    if args.verb == "ssh":
+    if args.verb == Verb.ssh:
         run_ssh(args)
 
-    if args.verb == "serve":
+    if args.verb == Verb.serve:
         run_serve(args)
index a01ab76e2f4af99cd53a8d6beed1994a8d4b89e3..710fb93f7f1e6e016f05ad4e4cb99b652fc54a8c 100644 (file)
@@ -112,6 +112,24 @@ class PackageType(enum.Enum):
     ebuild = 5
 
 
+class Verb(enum.Enum):
+    build   = "build"
+    clean   = "clean"
+    summary = "summary"
+    shell   = "shell"
+    boot    = "boot"
+    qemu    = "qemu"
+    ssh     = "ssh"
+    serve   = "serve"
+    bump    = "bump"
+    help    = "help"
+    genkey  = "genkey"
+
+    # Defining __str__ is required to get "print_help()" output to include the human readable (values) of Verb.
+    def __str__(self) -> str:
+        return self.value
+
+
 class Distribution(enum.Enum):
     package_type: PackageType
 
@@ -225,17 +243,17 @@ class ManifestFormat(Parseable, enum.Enum):
 
 
 class PartitionIdentifier(enum.Enum):
-    esp        = 'esp'
-    bios       = 'bios'
-    xbootldr   = 'xbootldr'
-    root       = 'root'
-    swap       = 'swap'
-    home       = 'home'
-    srv        = 'srv'
-    var        = 'var'
-    tmp        = 'tmp'
-    verity     = 'verity'
-    verity_sig = 'verity-sig'
+    esp        = "esp"
+    bios       = "bios"
+    xbootldr   = "xbootldr"
+    root       = "root"
+    swap       = "swap"
+    home       = "home"
+    srv        = "srv"
+    var        = "var"
+    tmp        = "tmp"
+    verity     = "verity"
+    verity_sig = "verity-sig"
 
 
 @dataclasses.dataclass
@@ -371,7 +389,7 @@ class PartitionTable:
 class MkosiArgs:
     """Type-hinted storage for command line arguments."""
 
-    verb: str
+    verb: Verb
     cmdline: List[str]
     force: int
 
index e618f6ee058d619fd8b679c25efd8a75f15c9183..cd0141c91e9fae8967c24785dc3eded99cd2bf23 100644 (file)
@@ -27,7 +27,7 @@ from . import (
     run_shell_cmdline,
     unlink_output,
 )
-from .backend import MkosiArgs, die
+from .backend import MkosiArgs, Verb, die
 
 
 class Machine:
@@ -43,13 +43,13 @@ class Machine:
         tmp = parse_args(args)["default"]
         tmp.force = 1
         tmp.autologin = True
-        if tmp.verb == "qemu":
+        if tmp.verb == Verb.qemu:
             tmp.bootable = True
             tmp.qemu_headless = True
             tmp.hostonly_initrd = True
             tmp.network_veth = True
             tmp.ssh = True
-        elif tmp.verb == "boot":
+        elif tmp.verb == Verb.boot:
             pass
         else:
             die("No valid verb was entered.")
@@ -79,7 +79,7 @@ class Machine:
             check_root()
             unlink_output(self.args)
 
-        if self.args.verb == "build":
+        if self.args.verb == Verb.build:
             check_output(self.args)
 
         if needs_build(self.args):
@@ -91,9 +91,9 @@ class Machine:
         with contextlib.ExitStack() as stack:
             prepend_to_environ_path(self.args.extra_search_paths)
 
-            if self.args.verb in ("shell", "boot"):
+            if self.args.verb in (Verb.shell, Verb.boot):
                 cmdline = run_shell_cmdline(self.args)
-            elif self.args.verb == "qemu":
+            elif self.args.verb == Verb.qemu:
                 # We must keep the temporary file opened at run_qemu_cmdline accessible, hence the context stack.
                 cmdline = stack.enter_context(run_qemu_cmdline(self.args))
             else:
@@ -105,7 +105,7 @@ class Machine:
             # We use pexpect to boot an image that we will be able to interact with in the future
             # Then we tell the process to look for the # sign, which indicates the CLI for that image is active
             # Once we've build/boot an image the CLI will prompt "root@image ~]# "
-            # Then, when pexpects finds the "#" it means we're ready to interact with the process
+            # Then, when pexpects finds the '#' it means we're ready to interact with the process
             self._serial = pexpect.spawnu(cmd, logfile=None, timeout=240)
             self._serial.expect("#")
             self.stack = stack.pop_all()
index a2113f8fddb92546bce6dc17ab604b5130e48e31..ddb50aa80a26cac2356c282ebe125684545712d6 100644 (file)
@@ -10,6 +10,7 @@ from typing import Any, Generator, Mapping
 import pytest
 
 import mkosi
+from mkosi.backend import Verb
 
 
 @contextlib.contextmanager
@@ -119,7 +120,7 @@ class MkosiConfig:
             "tmp_size": None,
             "usr_only": False,
             "var_size": None,
-            "verb": "build",
+            "verb": Verb.build,
             "verity": False,
             "with_docs": False,
             "with_network": False,
@@ -453,7 +454,7 @@ class MkosiConfigSummary(MkosiConfigOne):
     def __init__(self):
         super().__init__()
         for ref_c in self.reference_config.values():
-            ref_c["verb"] = "summary"
+            ref_c["verb"] = Verb.summary
         self.cli_arguments = ["summary"]
 
 
@@ -518,7 +519,7 @@ class MkosiConfigDistroDir(MkosiConfigDistro):
     def __init__(self):
         super().__init__("a_sub_dir")
         for ref_c in self.reference_config.values():
-            ref_c["verb"] = "summary"
+            ref_c["verb"] = Verb.summary
 
 
 class MkosiConfigManyParams(MkosiConfigOne):
@@ -832,20 +833,20 @@ def tested_config(request):
 def test_verb_none(tmpdir):
     with change_cwd(tmpdir.strpath):
         args = mkosi.parse_args([])
-        assert args["default"].verb == "build"
+        assert args["default"].verb == Verb.build
 
 
 def test_verb_build(tmpdir):
     with change_cwd(tmpdir.strpath):
         args = mkosi.parse_args(["build"])
-        assert args["default"].verb == "build"
+        assert args["default"].verb == Verb.build
 
 
 def test_verb_boot_no_cli_args1(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["boot", "--par-for-sub", "--pom", "--for_sub", "1234"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "boot"
+        assert args["default"].verb == Verb.boot
         assert args["default"].cmdline == cmdline_ref[1:]
 
 
@@ -853,7 +854,7 @@ def test_verb_boot_no_cli_args2(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-pa-package", "boot", "--par-for-sub", "--popenssl", "--for_sub", "1234"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "boot"
+        assert args["default"].verb == Verb.boot
         assert "a-package" in args["default"].packages
         assert args["default"].cmdline == cmdline_ref[2:]
 
@@ -862,7 +863,7 @@ def test_verb_boot_no_cli_args3(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-pa-package", "-p", "another-package", "build"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "build"
+        assert args["default"].verb == Verb.build
         assert args["default"].packages == ["a-package", "another-package"]
 
 
@@ -870,7 +871,7 @@ def test_verb_summary_no_cli_args4(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-pa-package", "-p", "another-package", "summary"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "summary"
+        assert args["default"].verb == Verb.summary
         assert args["default"].packages == ["a-package", "another-package"]
 
 
@@ -878,7 +879,7 @@ def test_verb_shell_cli_args5(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-pa-package", "-p", "another-package", "shell", "python3 -foo -bar;", "ls --inode"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "shell"
+        assert args["default"].verb == Verb.shell
         assert args["default"].packages == ["a-package", "another-package"]
         assert args["default"].cmdline == cmdline_ref[4:]
 
@@ -887,7 +888,7 @@ def test_verb_shell_cli_args6(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-i", "yes", "summary"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "summary"
+        assert args["default"].verb == Verb.summary
         assert args["default"].incremental == True
 
 
@@ -895,7 +896,7 @@ def test_verb_shell_cli_args7(tmpdir):
     with change_cwd(tmpdir.strpath):
         cmdline_ref = ["-i", "summary"]
         args = mkosi.parse_args(cmdline_ref)
-        assert args["default"].verb == "summary"
+        assert args["default"].verb == Verb.summary
         assert args["default"].incremental == True
 
 
index 6a6e46f9d54aefedffa56be27e74863da424f186..0052243a35840d81c3172afb1e697614c045004e 100644 (file)
@@ -9,9 +9,10 @@ from os import chdir, getcwd
 from pathlib import Path
 from typing import List, Optional
 
-import mkosi
 import pytest
-from mkosi.backend import Distribution, MkosiArgs, MkosiException
+
+import mkosi
+from mkosi.backend import Distribution, MkosiArgs, MkosiException, Verb
 
 
 def parse(argv: Optional[List[str]] = None) -> MkosiArgs:
@@ -29,17 +30,17 @@ def cd_temp_dir():
             chdir(old_dir)
 
 def test_parse_load_verb():
-    assert parse(["build"]).verb == "build"
-    assert parse(["clean"]).verb == "clean"
+    assert parse(["build"]).verb == Verb.build
+    assert parse(["clean"]).verb == Verb.clean
     with pytest.raises(SystemExit):
         parse(["help"])
-    assert parse(["genkey"]).verb == "genkey"
-    assert parse(["bump"]).verb == "bump"
-    assert parse(["serve"]).verb == "serve"
-    assert parse(["build"]).verb == "build"
-    assert parse(["shell"]).verb == "shell"
-    assert parse(["boot"]).verb == "boot"
-    assert parse(["--bootable", "qemu"]).verb == "qemu"
+    assert parse(["genkey"]).verb == Verb.genkey
+    assert parse(["bump"]).verb == Verb.bump
+    assert parse(["serve"]).verb == Verb.serve
+    assert parse(["build"]).verb == Verb.build
+    assert parse(["shell"]).verb == Verb.shell
+    assert parse(["boot"]).verb == Verb.boot
+    assert parse(["--bootable", "qemu"]).verb == Verb.qemu
     with pytest.raises(SystemExit):
         parse(["invalid"])