remade the steps runner and improved some functions
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
0473d7b9da
commit
099638570f
@ -1,11 +1,8 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from . import lxc_utils
|
from ..utils import steps_utils
|
||||||
from ..utils import conditions_utils
|
|
||||||
from ..utils.resources_utils import get_path
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .lxc import LXC
|
from .lxc import LXC
|
||||||
@ -20,54 +17,7 @@ def run_steps(lxc: LXC):
|
|||||||
The LXC object used to run the creation steps
|
The LXC object used to run the creation steps
|
||||||
"""
|
"""
|
||||||
|
|
||||||
creation = lxc.creation
|
creation_steps = lxc.creation["steps"]
|
||||||
creation_steps = creation["steps"]
|
|
||||||
|
|
||||||
for index, step in enumerate(creation_steps):
|
# Run the steps
|
||||||
|
steps_utils.run_steps(lxc, creation_steps)
|
||||||
if conditions_utils.verify_step_conditions(lxc, step):
|
|
||||||
logging.info(f"Conditions already met for step {index + 1}/{len(creation_steps)} for LXC {lxc.id}, "
|
|
||||||
f"skipping...")
|
|
||||||
continue
|
|
||||||
|
|
||||||
logging.info(f"Running step {index + 1}/{len(creation_steps)} for LXC {lxc.id}...")
|
|
||||||
|
|
||||||
match step["type"]:
|
|
||||||
|
|
||||||
# Support for scripts
|
|
||||||
case "script":
|
|
||||||
lxc_utils.run_script_step_parser(lxc, step)
|
|
||||||
case "file_create":
|
|
||||||
lxc.create_file(step["path"], step.get("permission", 644), step.get("owner", "root"))
|
|
||||||
case "file_copy":
|
|
||||||
lxc.pve.copy_file_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"])
|
|
||||||
case "folder_create":
|
|
||||||
lxc.create_directory(step["path"], step.get("permission", 755), step.get("owner", "root"))
|
|
||||||
case "folder_copy":
|
|
||||||
lxc.pve.copy_folder_to_lxc(lxc, get_path(lxc, step["path"]), step["destination"])
|
|
||||||
case "command":
|
|
||||||
lxc.run_command(command=step["command"], working_directory=step.get("working_directory"),
|
|
||||||
return_status_code=True)
|
|
||||||
case "docker":
|
|
||||||
lxc.run_docker_command(step["container"], step["command"])
|
|
||||||
case "docker_compose":
|
|
||||||
lxc.run_docker_compose_command(command=step["command"],
|
|
||||||
working_directory=step.get("working_directory"))
|
|
||||||
case "git":
|
|
||||||
lxc.run_command(command=f"git clone {step['url']} {step['destination']}", return_status_code=True)
|
|
||||||
case "download":
|
|
||||||
lxc.download_file(step["url"], step["destination"])
|
|
||||||
case "unzip":
|
|
||||||
lxc.unzip_file(step["path"], step.get("destination"))
|
|
||||||
case "install-package":
|
|
||||||
lxc.install_package(step["package"])
|
|
||||||
case "remove-package":
|
|
||||||
lxc.remove_package(step["package"])
|
|
||||||
case "start":
|
|
||||||
lxc.start()
|
|
||||||
case "stop":
|
|
||||||
lxc.stop()
|
|
||||||
case "reboot":
|
|
||||||
lxc.reboot()
|
|
||||||
case "replace-in-files":
|
|
||||||
lxc.replace_in_files(step["files"], step["search"], step["replace"])
|
|
||||||
|
@ -7,6 +7,7 @@ class LinuxMachine:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.known_programs = []
|
self.known_programs = []
|
||||||
|
self.id = None
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -144,7 +145,7 @@ class LinuxMachine:
|
|||||||
|
|
||||||
self.run_command(f"rm -rf {directory}", return_status_code=True)
|
self.run_command(f"rm -rf {directory}", return_status_code=True)
|
||||||
|
|
||||||
def run_docker_command(self, container, command):
|
def run_docker_command(self, container, command: str or list):
|
||||||
"""Run a command inside a docker container on a linux host
|
"""Run a command inside a docker container on a linux host
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@ -159,6 +160,9 @@ class LinuxMachine:
|
|||||||
>>> self.run_docker_command(linux_machine, "<container-name>", "<command>")
|
>>> self.run_docker_command(linux_machine, "<container-name>", "<command>")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if type(command) == list:
|
||||||
|
command = " && ".join(command)
|
||||||
|
|
||||||
if not self.has_program("docker"):
|
if not self.has_program("docker"):
|
||||||
raise Exception(f"Docker is not installed on this machine {self.get_hostname()}")
|
raise Exception(f"Docker is not installed on this machine {self.get_hostname()}")
|
||||||
|
|
||||||
@ -188,12 +192,12 @@ class LinuxMachine:
|
|||||||
else:
|
else:
|
||||||
self.run_command(f"{docker_compose_exec} {command}", return_status_code=True)
|
self.run_command(f"{docker_compose_exec} {command}", return_status_code=True)
|
||||||
|
|
||||||
def download_file(self, url: str, destination: str):
|
def download_file(self, url: str or list, destination: str):
|
||||||
"""Download a file from a URL to the Linux Machine and save it to the destination
|
"""Download a file from a URL to the Linux Machine and save it to the destination
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
url: str
|
url: str or list
|
||||||
URL of the file to download
|
URL of the file to download
|
||||||
destination: str
|
destination: str
|
||||||
Path to the destination to save the file to
|
Path to the destination to save the file to
|
||||||
@ -206,7 +210,7 @@ class LinuxMachine:
|
|||||||
|
|
||||||
if type(url) is list:
|
if type(url) is list:
|
||||||
for u in url:
|
for u in url:
|
||||||
self.run_command(f"wget {u} --directory-prefix={destination}", return_status_code=True)
|
self.download_file(u, destination)
|
||||||
else:
|
else:
|
||||||
self.run_command(f"wget {url} --directory-prefix={destination}", return_status_code=True)
|
self.run_command(f"wget {url} --directory-prefix={destination}", return_status_code=True)
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .lxc.lxc_utils import load_lxc, get_all_lxcs
|
from .lxc.lxc_utils import load_lxc, get_all_lxcs
|
||||||
from .utils import git_utils
|
|
||||||
from .proxmox.proxmox import ProxmoxHost
|
from .proxmox.proxmox import ProxmoxHost
|
||||||
|
from .utils import git_utils
|
||||||
|
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
@ -20,11 +20,11 @@ def run(args):
|
|||||||
# Check if the repo is already cloned
|
# Check if the repo is already cloned
|
||||||
if not pve.has_directory(pve.repo_path):
|
if not pve.has_directory(pve.repo_path):
|
||||||
logging.info(f"Cloning repository {args.repo} to {args.path}...")
|
logging.info(f"Cloning repository {args.repo} to {args.path}...")
|
||||||
git_utils.clone_repo(url=args.repo, path=pve.repo_path, linux_machine=pve)
|
git_utils.clone_repo(linux_machine=pve, url=args.repo, path=pve.repo_path)
|
||||||
|
|
||||||
if pve.has_directory(Path(pve.repo_path).joinpath(".git")):
|
if pve.has_directory(Path(pve.repo_path).joinpath(".git")):
|
||||||
logging.info(f"Repository already cloned at {pve.repo_path}, updating...")
|
logging.info(f"Repository already cloned at {pve.repo_path}, updating...")
|
||||||
git_utils.update_repo(path=pve.repo_path, linux_machine=pve)
|
git_utils.update_repo(linux_machine=pve, path=pve.repo_path)
|
||||||
|
|
||||||
if not pve.has_directory(pve.repo_path):
|
if not pve.has_directory(pve.repo_path):
|
||||||
raise FileNotFoundError(f"Repo not found at {pve.repo_path}")
|
raise FileNotFoundError(f"Repo not found at {pve.repo_path}")
|
||||||
|
@ -78,7 +78,7 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
self.connection = Connection(host=self.host, user=self.user, port=self.port)
|
self.connection = Connection(host=self.host, user=self.user, port=self.port)
|
||||||
|
|
||||||
def run_command(self, command: str, return_status_code: bool = False, exception_on_exit: bool = True,
|
def run_command(self, command: str, return_status_code: bool = False, exception_on_exit: bool = True,
|
||||||
exception_on_empty_stdout: bool = False, **kwargs):
|
exception_on_empty_stdout: bool = False, working_directory=None, **kwargs):
|
||||||
"""Run a command on the Proxmox VE host
|
"""Run a command on the Proxmox VE host
|
||||||
The default behavior is as follows :
|
The default behavior is as follows :
|
||||||
- runs the command on the Proxmox VE host
|
- runs the command on the Proxmox VE host
|
||||||
@ -92,7 +92,7 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
command_result: str
|
command: str
|
||||||
command to run
|
command to run
|
||||||
return_status_code: bool, optional
|
return_status_code: bool, optional
|
||||||
should it return the exit code and not the stdout, disables exception_on_exit
|
should it return the exit code and not the stdout, disables exception_on_exit
|
||||||
@ -121,6 +121,12 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
if the stdout is empty and exception_on_empty_stdout is True
|
if the stdout is empty and exception_on_empty_stdout is True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if type(command) == list:
|
||||||
|
command = ' && '.join(command)
|
||||||
|
|
||||||
|
if working_directory:
|
||||||
|
command = f"cd {working_directory} && {command}"
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# Check if host is None, if it is, run the command locally, else run it on the host via SSH
|
# Check if host is None, if it is, run the command locally, else run it on the host via SSH
|
||||||
@ -242,7 +248,8 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
|
|
||||||
self.run_command(f"qm reboot {vm_id}")
|
self.run_command(f"qm reboot {vm_id}")
|
||||||
|
|
||||||
def copy_file_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path, use_ssh: bool = True):
|
def copy_file_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path, permission: int = 644,
|
||||||
|
owner: str = "root", use_ssh: bool = True):
|
||||||
"""Copy the given file to the given LXC."""
|
"""Copy the given file to the given LXC."""
|
||||||
if isinstance(source, Path):
|
if isinstance(source, Path):
|
||||||
source = str(source.as_posix())
|
source = str(source.as_posix())
|
||||||
@ -252,7 +259,13 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
lxc.create_directory(destination.parent.as_posix(), use_ssh=use_ssh)
|
lxc.create_directory(destination.parent.as_posix(), use_ssh=use_ssh)
|
||||||
self.run_command(f"pct push {lxc.id} {source} {destination.as_posix()}")
|
self.run_command(f"pct push {lxc.id} {source} {destination.as_posix()}")
|
||||||
|
|
||||||
def copy_folder_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path):
|
if permission != 755:
|
||||||
|
lxc.run_command(f"chmod {permission} {destination}", return_status_code=True, use_ssh=use_ssh)
|
||||||
|
if owner != "root":
|
||||||
|
lxc.run_command(f"chown {owner} {destination}", return_status_code=True)
|
||||||
|
|
||||||
|
def copy_folder_to_lxc(self, lxc: LXC, source: str or Path, destination: str or Path, permission: int = 755,
|
||||||
|
owner: str = "root"):
|
||||||
"""Copy the given folder to the given LXC."""
|
"""Copy the given folder to the given LXC."""
|
||||||
if isinstance(source, Path):
|
if isinstance(source, Path):
|
||||||
source = str(source.as_posix())
|
source = str(source.as_posix())
|
||||||
@ -261,6 +274,11 @@ class ProxmoxHost(LinuxMachine):
|
|||||||
|
|
||||||
self.run_command(f"scp -o StrictHostKeyChecking=no -B -r {source} {lxc.get_ssh_string()}:{destination}")
|
self.run_command(f"scp -o StrictHostKeyChecking=no -B -r {source} {lxc.get_ssh_string()}:{destination}")
|
||||||
|
|
||||||
|
if permission != 755:
|
||||||
|
lxc.run_command(f"chmod -R {permission} {destination}", return_status_code=True)
|
||||||
|
if owner != "root":
|
||||||
|
lxc.run_command(f"chown -R {owner} {destination}", return_status_code=True)
|
||||||
|
|
||||||
def list_dir(self, directory: str or Path, glob_filter: str = '*'):
|
def list_dir(self, directory: str or Path, glob_filter: str = '*'):
|
||||||
"""List the given directory."""
|
"""List the given directory."""
|
||||||
if isinstance(directory, Path):
|
if isinstance(directory, Path):
|
||||||
|
@ -3,13 +3,13 @@ import logging
|
|||||||
from ..machine.machine import LinuxMachine
|
from ..machine.machine import LinuxMachine
|
||||||
|
|
||||||
|
|
||||||
def clone_repo(url, path, linux_machine: LinuxMachine):
|
def clone_repo(linux_machine: LinuxMachine, url, path):
|
||||||
"""Clone the given repository to the given path"""
|
"""Clone the given repository to the given path"""
|
||||||
logging.info(f"Cloning repository {url} to {path}...")
|
logging.info(f"Cloning repository {url} to {path}...")
|
||||||
linux_machine.run_command(f"git clone {url} {path}")
|
linux_machine.run_command(f"git clone {url} {path}")
|
||||||
|
|
||||||
|
|
||||||
def update_repo(path, linux_machine: LinuxMachine):
|
def update_repo(linux_machine: LinuxMachine, path):
|
||||||
"""Update the given repository"""
|
"""Update the given repository"""
|
||||||
logging.info(f"Updating repository at {path}...")
|
logging.info(f"Updating repository at {path}...")
|
||||||
linux_machine.run_command(f"git -C {path} pull")
|
linux_machine.run_command(f"git -C {path} pull")
|
||||||
|
177
src/utils/steps_utils.py
Normal file
177
src/utils/steps_utils.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
from . import git_utils
|
||||||
|
from .resources_utils import get_path
|
||||||
|
from ..lxc import lxc_utils
|
||||||
|
from ..lxc.lxc import LXC
|
||||||
|
from ..machine.machine import LinuxMachine
|
||||||
|
from ..utils import conditions_utils
|
||||||
|
|
||||||
|
|
||||||
|
def _run_script_step(linux_machine, step):
|
||||||
|
if isinstance(linux_machine, LXC):
|
||||||
|
lxc_utils.run_script_step_parser(linux_machine, step)
|
||||||
|
else:
|
||||||
|
logging.warning(f"Script step only supported on LXCs")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_file_create_step(linux_machine, step):
|
||||||
|
linux_machine.create_file(step["path"], step.get("permission", 644), step.get("owner", "root"))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_file_copy_step(linux_machine, step):
|
||||||
|
if isinstance(linux_machine, LXC):
|
||||||
|
linux_machine.pve.copy_file_to_lxc(linux_machine, get_path(linux_machine, step["path"]), step["destination"],
|
||||||
|
step.get("permission", 644), step.get("owner", "root"))
|
||||||
|
else:
|
||||||
|
logging.warning(f"File copy step only supported on LXCs")
|
||||||
|
|
||||||
|
|
||||||
|
def _run_folder_create_step(linux_machine, step):
|
||||||
|
linux_machine.create_directory(step["path"], step.get("permission", 755), step.get("owner", "root"))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_folder_copy_step(linux_machine, step):
|
||||||
|
linux_machine.pve.copy_folder_to_lxc(linux_machine, get_path(linux_machine, step["path"]), step["destination"],
|
||||||
|
step.get("permission", 644), step.get("owner", "root"))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_command_step(linux_machine, step):
|
||||||
|
linux_machine.run_command(command=step["command"], working_directory=step.get("workdir"),
|
||||||
|
return_status_code=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _run_docker_step(linux_machine, step):
|
||||||
|
linux_machine.run_docker_command(step["container"], step["command"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_docker_compose_step(linux_machine, step):
|
||||||
|
linux_machine.run_docker_compose_command(command=step["command"], working_directory=step.get("working_directory"))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_git_clone_step(linux_machine, step):
|
||||||
|
git_utils.clone_repo(linux_machine=linux_machine, url=step["url"], path=step["destination"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_git_pull_step(linux_machine, step):
|
||||||
|
git_utils.update_repo(linux_machine=linux_machine, path=step["path"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_download_step(linux_machine, step):
|
||||||
|
linux_machine.download_file(step["url"], step["destination"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_install_package_step(linux_machine, step):
|
||||||
|
linux_machine.install_package(step["package"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_remove_package_step(linux_machine, step):
|
||||||
|
linux_machine.remove_package(step["package"])
|
||||||
|
|
||||||
|
|
||||||
|
def _run_start_step(linux_machine, step):
|
||||||
|
linux_machine.start()
|
||||||
|
|
||||||
|
|
||||||
|
def _run_stop_step(linux_machine, step):
|
||||||
|
linux_machine.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def _run_reboot_step(linux_machine, step):
|
||||||
|
linux_machine.reboot()
|
||||||
|
|
||||||
|
|
||||||
|
def _run_service_start_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_service_stop_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_service_restart_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_service_enable_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_service_disable_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_replace_in_file_step(linux_machine, step):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _run_unzip_step(linux_machine, step):
|
||||||
|
linux_machine.unzip_file(step["path"], step.get("destination"))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_wait_step(step):
|
||||||
|
time.sleep(step["seconds"])
|
||||||
|
|
||||||
|
|
||||||
|
def run_steps(linux_machine: LinuxMachine, steps: dict):
|
||||||
|
for index, step in enumerate(steps):
|
||||||
|
|
||||||
|
if conditions_utils.verify_step_conditions(linux_machine, step):
|
||||||
|
logging.info(f"Conditions already met for step {index + 1}/{len(steps)} for LXC {linux_machine.id}, "
|
||||||
|
f"skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
logging.info(f"Running step {index + 1}/{len(steps)} for LXC {linux_machine.id}...")
|
||||||
|
|
||||||
|
# Run command step
|
||||||
|
match step['type']:
|
||||||
|
case "script":
|
||||||
|
_run_script_step(linux_machine, step)
|
||||||
|
case "file_create":
|
||||||
|
_run_file_create_step(linux_machine, step)
|
||||||
|
case "file_copy":
|
||||||
|
_run_file_copy_step(linux_machine, step)
|
||||||
|
case "folder_create":
|
||||||
|
_run_folder_create_step(linux_machine, step)
|
||||||
|
case "folder_copy":
|
||||||
|
_run_folder_copy_step(linux_machine, step)
|
||||||
|
case "command":
|
||||||
|
_run_command_step(linux_machine, step)
|
||||||
|
case "docker":
|
||||||
|
_run_docker_step(linux_machine, step)
|
||||||
|
case "docker_compose":
|
||||||
|
_run_docker_compose_step(linux_machine, step)
|
||||||
|
case "git_clone":
|
||||||
|
_run_git_clone_step(linux_machine, step)
|
||||||
|
case "git_pull":
|
||||||
|
_run_git_pull_step(linux_machine, step)
|
||||||
|
case "download":
|
||||||
|
_run_download_step(linux_machine, step)
|
||||||
|
case "install_package":
|
||||||
|
_run_install_package_step(linux_machine, step)
|
||||||
|
case "remove_package":
|
||||||
|
_run_remove_package_step(linux_machine, step)
|
||||||
|
case "start":
|
||||||
|
_run_start_step(linux_machine, step)
|
||||||
|
case "stop":
|
||||||
|
_run_stop_step(linux_machine, step)
|
||||||
|
case "reboot":
|
||||||
|
_run_reboot_step(linux_machine, step)
|
||||||
|
case "service_start":
|
||||||
|
_run_service_start_step(linux_machine, step)
|
||||||
|
case "service_stop":
|
||||||
|
_run_service_stop_step(linux_machine, step)
|
||||||
|
case "service_restart":
|
||||||
|
_run_service_restart_step(linux_machine, step)
|
||||||
|
case "service_enable":
|
||||||
|
_run_service_enable_step(linux_machine, step)
|
||||||
|
case "service_disable":
|
||||||
|
_run_service_disable_step(linux_machine, step)
|
||||||
|
case "replace_in_file":
|
||||||
|
_run_replace_in_file_step(linux_machine, step)
|
||||||
|
case "unzip":
|
||||||
|
_run_unzip_step(linux_machine, step)
|
||||||
|
case "wait":
|
||||||
|
_run_wait_step(step)
|
Loading…
Reference in New Issue
Block a user