diff --git a/config.toml b/config.toml index d948f28..c0ed9f3 100644 --- a/config.toml +++ b/config.toml @@ -1,5 +1,5 @@ [default] -ROOT_DIR = "." +SRC_DIR = "src" BUILD_DIR = "build" DOCKERFILE_DIR = "docker" SELENIUM_INIT_MESSAGE = "INFO [Standalone.execute] - Started Selenium Standalone" @@ -22,4 +22,5 @@ FUELIGNITION_URL = "https://opensuse.github.io/fuel-ignition/edit" CLI = true [debug] -DEBUG = true \ No newline at end of file +DEBUG = true +CLI = false \ No newline at end of file diff --git a/src/autoignition.py b/src/autoignition.py index a86acdb..0d28700 100644 --- a/src/autoignition.py +++ b/src/autoignition.py @@ -1,19 +1,19 @@ from fnmatch import fnmatch import io +from pathlib import Path import tarfile import time from typing import Annotated +from cli import cli_spinner +import config +from debug import debug_guard import git from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait import typer - -from cli import cli_spinner -import config -from debug import debug_guard from utils import ensure_build_dir @@ -53,7 +53,7 @@ def convert_json_via_fuelignition(container, driver, fuelignition_json, img_path image_file = container.exec_run("ls /home/seluser/Downloads/").output.decode().split()[0] # Finally, fetch the image file from the container client_image_path = f"/home/seluser/Downloads/{image_file}" - host_image_path = config.ROOT_DIR / img_path + host_image_path = config.SRC_DIR / img_path if host_image_path.exists(): host_image_path.unlink() filestream = container.get_archive(client_image_path)[0] @@ -114,11 +114,13 @@ def build_fuelignition(): @cli_spinner(description="Converting json to img", total=None) @ensure_build_dir def json_to_img( - fuelignition_json: Annotated[ - str, typer.Option(help="The fuel-ignition json for configuring the disk image", prompt=True) + json_path: Path = Annotated[ + Path, + typer.Option(help="The fuel-ignition json for configuring the disk image", prompt=True), ], - img_path: Annotated[ - str, typer.Option(help="The file to output the disk image to", prompt=True) + img_path: Path = Annotated[ + Path, + typer.Option(help="The file to output the disk image to", prompt=True), ], ) -> None: """Takes a fuel-ignition json file and produces an ignition disk image file""" @@ -155,7 +157,7 @@ def json_to_img( time.sleep(0.1) # Now, create the webdriver and convert the json to an img driver = create_driver() - convert_json_via_fuelignition(selenium_container, driver, fuelignition_json, img_path) + convert_json_via_fuelignition(selenium_container, driver, json_path, img_path) driver.quit() except Exception as e: raise e diff --git a/src/config.py b/src/config.py index dac69e2..60aa9c2 100644 --- a/src/config.py +++ b/src/config.py @@ -10,7 +10,7 @@ import tomllib CLIENT = docker.from_env(version="auto") -ROOT = Path(__file__).parent.parent.absolute() +PROJECT_ROOT = Path(__file__).parent.parent.absolute() type ConfigLabel = str | list[str] @@ -18,7 +18,7 @@ type ConfigLabel = str | list[str] def get_config(config_label: ConfigLabel = ["default"]) -> dict: if isinstance(config_label, str): config_label = [config_label] - with open(ROOT / "config.toml", "rb") as f: + with open(PROJECT_ROOT / "config.toml", "rb") as f: configs: dict = tomllib.load(f) out_config: dict = {} for c in config_label: @@ -30,22 +30,26 @@ def finalise_config(config: dict) -> None: # First, convert base paths to Path objects for k, v in config.items(): match k: - case "ROOT_DIR" | "BUILD_DIR" | "DOCKERFILE_DIR": + case "SRC_DIR" | "BUILD_DIR": config[k] = Path(v).absolute() case "CWD_MOUNTDIR": config[k] = Path(v) # Then, get required paths from config or globals if not present build_dir = config.get("BUILD_DIR", BUILD_DIR) cwd_mountdir = config.get("CWD_MOUNTDIR", CWD_MOUNTDIR) - root_dir = config.get("ROOT_DIR", ROOT_DIR) + src_dir = config.get("SRC_DIR", SRC_DIR) # Finally, construct the secondary parameters config["FUELIGNITION_BUILD_DIR"] = build_dir / config.get( "FUELIGNITION_BUILD_DIR", FUELIGNITION_BUILD_DIR ) + config["DOCKERFILE_DIR"] = src_dir / config.get( + "DOCKERFILE_DIR", + DOCKERFILE_DIR + ) config["CWD_MOUNT"] = docker.types.Mount( target=str(cwd_mountdir), - source=str(root_dir), + source=str(PROJECT_ROOT), type="bind", ) diff --git a/src/create_disk.py b/src/create_disk.py index d64a0f1..d4ebb63 100644 --- a/src/create_disk.py +++ b/src/create_disk.py @@ -66,9 +66,9 @@ def write_disk(disk: str) -> None: @cli_spinner(description="Creating ignition initialisation disk", total=None) @ensure_build_dir def create_ignition_disk( - disk: Annotated[str, typer.Option(help="Path to the disk to write to", prompt=True)], - hostname: Annotated[str, typer.Option(help="Hostname for the new node", prompt=True)], - password: Annotated[ + disk: str = Annotated[str, typer.Option(help="Path to the disk to write to", prompt=True)], + hostname: str = Annotated[str, typer.Option(help="Hostname for the new node", prompt=True)], + password: str = Annotated[ str, typer.Option( help="Password for the root user on the new node", @@ -77,16 +77,25 @@ def create_ignition_disk( hide_input=True, ), ], - switch_ip_address: Annotated[ + switch_ip_address: str = Annotated[ str, typer.Option(help="IP address of the switch to connect to", prompt=True) ], - switch_port: Annotated[int, typer.Option(help="Port on the switch to connect to", prompt=True)], - swarm_token: Annotated[ + switch_port: int = Annotated[ + int, typer.Option(help="Port on the switch to connect to", prompt=True) + ], + swarm_token: str = Annotated[ str, typer.Option(help="Swarm token for connecting to the swarm", prompt=True) ], ) -> None: - """Writes an ignition image to the specified disk for easy deployment of new nodes to the swarm""" # noqa - create_img(hostname, password, switch_ip_address, switch_port, swarm_token) + """Writes an ignition image to the specified disk for easy deployment of new nodes to the swarm""" # noqa + create_img( + hostname, + password, + switch_ip_address, + switch_port, + swarm_token, + config.BUILD_DIR / "ignition.img", + ) valid, response = validate() if not valid: print(response) diff --git a/src/create_img.py b/src/create_img.py index 573f837..13c070b 100644 --- a/src/create_img.py +++ b/src/create_img.py @@ -1,13 +1,13 @@ import ipaddress import json +from pathlib import Path from typing import Annotated -import typer - from autoignition import json_to_img from cli import cli_spinner import config from debug import debug_guard +import typer from utils import ensure_build_dir @@ -15,7 +15,7 @@ MAX_PORT: int = 65535 def load_template() -> dict: - with open("templates/fuelignition.json", "r") as f: + with open(config.SRC_DIR / "templates" / "fuelignition.json", "r") as f: out = json.load(f) return out @@ -31,8 +31,8 @@ def apply_ignition_settings( ignition_config["login"]["users"][0]["passwd"] = password # Add files that will define a service to ensure that the node joins the swarm - with open("templates/join_swarm.sh", "r") as f1, open( - "templates/join_swarm.service", "r" + with open(config.SRC_DIR / "templates" / "join_swarm.sh", "r") as f1, open( + config.SRC_DIR / "templates" / "join_swarm.service", "r" ) as f2: swarm_script, swarm_service = f1.read(), f2.read() @@ -72,8 +72,8 @@ def apply_ignition_settings( @cli_spinner(description="Creating ignition image", total=None) @ensure_build_dir def create_img( - hostname: Annotated[str, typer.Option(help="Hostname for the new node", prompt=True)], - password: Annotated[ + hostname: str = Annotated[str, typer.Option(help="Hostname for the new node", prompt=True)], + password: str = Annotated[ str, typer.Option( help="Password for the root user on the new node", @@ -82,15 +82,29 @@ def create_img( hide_input=True, ), ], - switch_ip_address: Annotated[ + switch_ip_address: str = Annotated[ str, typer.Option(help="IP address of the switch to connect to", prompt=True) ], - switch_port: Annotated[int, typer.Option(help="Port on the switch to connect to", prompt=True)], - swarm_token: Annotated[ + switch_port: int = Annotated[ + int, typer.Option( + help="Port on the switch to connect to", + prompt=True, + min=1, + max=MAX_PORT, + ) + ], + swarm_token: str = Annotated[ str, typer.Option(help="Swarm token for connecting to the swarm", prompt=True) ], + img_path: Path = Annotated[ + Path, + typer.Option( + help="Path to the JSON file to be converted to an img", + default=Path.cwd() / "ignition.img", + ), + ], ) -> None: - """Creates an ignition image for deploying a new node to the swarm""" + """Creates an ignition image for deploying a new node to the swarm""" switch_ip_address = ipaddress.ip_address(switch_ip_address) if switch_port > MAX_PORT: raise ValueError(f"Port must be less than {MAX_PORT}") @@ -114,11 +128,11 @@ def create_img( ) # export ignition configuration - with open("build/fuelignition.json", "w") as f: + with open(config.BUILD_DIR / "fuelignition.json", "w") as f: json.dump(ignition_config, f, indent=4) # convert ignition configuration to image - json_to_img("build/fuelignition.json", "build/ignition.img") + json_to_img(config.BUILD_DIR / "fuelignition.json", img_path) if __name__ == "__main__": diff --git a/src/debug.py b/src/debug.py index f1ba13e..359385b 100644 --- a/src/debug.py +++ b/src/debug.py @@ -19,6 +19,6 @@ def debug_guard(f: Callable) -> Callable: snoop.install( snoop="ss", ) - + typer.echo(f"Debug mode enabled: {inspect.stack()[1].filename}") wraps(f)(ss)(f) # noqa: F821 #* ss is installed in debug_mode diff --git a/src/docker/validate.dockerfile b/src/docker/validate.dockerfile index 47d6b63..863a454 100644 --- a/src/docker/validate.dockerfile +++ b/src/docker/validate.dockerfile @@ -5,8 +5,8 @@ ARG CWD_MOUNTDIR ENV CWD_MOUNTDIR=$CWD_MOUNTDIR COPY --from=ignition-validate . . -COPY scripts/installs.sh /installs.sh +COPY src/scripts/installs.sh /installs.sh RUN /installs.sh -CMD $CWD_MOUNTDIR/scripts/validate.sh +CMD $CWD_MOUNTDIR/src/scripts/validate.sh diff --git a/src/node_deployer.py b/src/node_deployer.py index b484879..19ebd7f 100755 --- a/src/node_deployer.py +++ b/src/node_deployer.py @@ -1,10 +1,11 @@ #!/usr/bin/env poetry run python +from autoignition import json_to_img +import config +from create_disk import create_ignition_disk +from create_img import create_img import typer -from create_img import create_img -from create_disk import create_ignition_disk -from autoignition import json_to_img app = typer.Typer( help="A tool for creating ignition images for automated deployment to a swarm" @@ -15,4 +16,5 @@ app.command()(create_ignition_disk) app.command()(json_to_img) if __name__ == "__main__": + config.update_config("cli") app() \ No newline at end of file diff --git a/src/scripts/validate.sh b/src/scripts/validate.sh index 733b293..7202397 100755 --- a/src/scripts/validate.sh +++ b/src/scripts/validate.sh @@ -1,2 +1,2 @@ -${CWD_MOUNTDIR}/scripts/fetch_config.sh +${CWD_MOUNTDIR}/src/scripts/fetch_config.sh /usr/local/bin/ignition-validate ${CWD_MOUNTDIR}/build/config.ign \ No newline at end of file