1
0
Fork 0

Compare commits

..

No commits in common. "d1e4452a5da53d069b144b60e70d73a6bfece716" and "015f2e5a168b4ca291f0ca3dcb090de01f6d7f74" have entirely different histories.

4 changed files with 41 additions and 196 deletions

View file

@ -1,134 +0,0 @@
#!/bin/sh
BASEDIR="/var/lib/containerctl"
CONTAINERDIR="${BASEDIR}/containers"
CONFIGDIR="${BASEDIR}/configs"
LOGDIR="/var/log/containerctl"
TODAY="$(date '+%F')"
LOG="${LOGDIR}/${TODAY}"
log_error()
{
printf '[%b] (EE) %b\n' "${TODAY}" "${@}" | tee -a "${LOG}"
}
list_dir()
{
find "${1}" -mindepth 1 -type d
}
list_containers()
{
list_dir "${CONTAINERDIR}"
}
list_configs()
{
list_dir "${CONFIGDIR}"
}
exec_script()
{
container="${1}"
script="${2}"
if [ -z "${container}" ]
then
log_error "No container passed"
exit 1
fi
if [ -z "${script}" ]
then
log_error "No script passed"
exit 1
fi
if ! [ -e "${CONTAINERDIR}/${container}" ]
then
log_error "${container} does not exist, did you forget to generate it?"
exit 1
fi
if ! [ -d "${CONTAINERDIR}/${container}" ]
then
log_error "${container} does not exist"
exit 1
fi
if ! [ -e "${CONTAINERDIR}/${container}/${script}" ]
then
log_error "${script} is invalid, maybe try regenerating the container?"
exit 1
fi
if ! [ -f "${CONTAINERDIR}/${container}/${script}" ]
then
log_error "${script} is invalid, please recreate the container"
exit 1
fi
/bin/sh "${CONTAINERDIR}/${container}/${script}" || log_error "${script} failed!"
}
generate_container()
{
config="${1}"
if [ -z "${config}" ]
then
log_error "No config was passed."
exit 1
fi
if ! [ -e "${CONFIGDIR}" ]
then
log_error "${CONFIGDIR} does not exist"
exit 1
fi
if ! [ -d "${CONFIGDIR}" ]
then
log_error "${CONFIGDIR} is not a directory"
exit 1
fi
if ! [ -e "${CONFIGDIR}/${config}" ]
then
log_error "${config} does not exist!" \
"Please check the name and or location of the desired config."
exit 1
fi
if ! [ -f "${CONFIGDIR}/${config}" ]
then
log_error "${config} is not a file."
exit 1
fi
/usr/bin/env python3 "${BASEDIR}/generate/generate.py" \
"${CONFIGDIR}/${config}" "${LOG}" "${CONTAINERDIR}"
if [ "${?}" = 1 ]
then
log_error "Container generation failed."
exit 1
fi
}
generate_all()
{
list_configs | while read -r config
do
generate_config "$(printf '%b' "${config}" | sed -e "s|${CONFIGDIR}||g")"
done
}
case "${1}" in
"list-containers") list_containers ;;
"list-configs") list_configs ;;
"generate-all") generate_all ;;
"generate") shift; generate_config "${@}" ;;
*) exec_script "${@}" ;;
esac

View file

@ -17,13 +17,25 @@ class ConfigError(Exception):
def __init__(self, message: str = "") -> None: def __init__(self, message: str = "") -> None:
"""Create Exception object.""" """Create Exception object."""
self.message = message self.message = message
super().__init__(message) self.super.__init__(message)
def __str__(self) -> str: def __str__(self) -> str:
"""Convert Exception object to a string.""" """Convert Exception object to a string."""
return f"Configuration error: {self.message}" return f"Configuration error: {self.message}"
def join(data: list, separator: str = ",") -> str:
"""Join a list together."""
ret: str = ""
x = data.copy()
if len(x) == 0:
return ret
while len(x) > 1:
ret += x.pop() + separator
ret += x.pop()
return ret
def maybe(json: dict, key: str) -> str | dict | list | bool | None: def maybe(json: dict, key: str) -> str | dict | list | bool | None:
"""Maybe get a value.""" """Maybe get a value."""
try: try:
@ -32,11 +44,20 @@ def maybe(json: dict, key: str) -> str | dict | list | bool | None:
return None return None
def command_join(items: list | None) -> str:
"""Like join(), but call command()."""
joined = ""
if items is not None:
for item in items:
joined += " " + item.command()
return joined
def trim(s: str) -> str: def trim(s: str) -> str:
"""Remove sequential whitespace.""" """Remove sequential whitespace."""
s = s.replace("\t ", "\t") s = s.replace("\t ", "\t")
s = s.replace("\t\\\n", " ") s = s.replace("\t\\\n", " ")
while " " in s: while s.__contains__(" "):
s = s.replace(" ", " ") s = s.replace(" ", " ")
return s return s
@ -120,8 +141,7 @@ class Secret:
cmd = ( cmd = (
f"--secret {self.name},type={self.secret_type},target={self.target}" f"--secret {self.name},type={self.secret_type},target={self.target}"
) )
# Not a password, ruff... if self.target == "mount" and self.options != "":
if self.secret_type == "mount" and self.options != "": # noqa: S105
cmd = f"{cmd},{self.options}" cmd = f"{cmd},{self.options}"
return cmd return cmd
@ -216,15 +236,10 @@ class Ports:
def command(self) -> str: def command(self) -> str:
"""Option for podman container create.""" """Option for podman container create."""
ports = "" ports = ""
seperator = " \\\n" for port in self.tcp_ports:
ports += seperator.join( ports += f"\t--port {port}/tcp \\\n"
[f"\t--port {port}/tcp" for port in self.tcp_ports] for port in self.udp_ports:
) ports += f"\t--port {port}/udp \\\n"
ports += seperator
ports += seperator.join(
[f"\t--port {port}/udp" for port in self.udp_ports]
)
ports += seperator
return ports return ports
@ -254,7 +269,7 @@ class Network:
if self.mode == "": if self.mode == "":
return "" return ""
cmd = f"--network={self.mode}" cmd = f"--network={self.mode}"
opts = ",".join(self.options) opts = join(self.options)
if opts != "": if opts != "":
cmd += f":{opts}" cmd += f":{opts}"
return cmd return cmd
@ -330,15 +345,15 @@ class Dns:
def command(self) -> str: def command(self) -> str:
"""Option for podman container create.""" """Option for podman container create."""
if len(self.servers) == 0 and self.search == "": if len(self.servers) == 0 and self.serach == "":
return "" return ""
if len(self.servers) == 0: if len(self.servers) == 0:
return f"--dns-search={self.search}" return f"--dns-search={self.search}"
if self.search == "": if self.search == "":
return f"--dns={','.join(self.servers)}" return f"--dns={join(self.servers)}"
cmd = f"--dns-search={self.search} \\\n\t--dns=" cmd = f"--dns-search={self.search} \\\n\t--dns="
cmd += ",".join(self.servers) cmd += join(self.servers)
return cmd return cmd
@ -432,7 +447,7 @@ class Container:
def create_container(self) -> str: def create_container(self) -> str:
"""Generate podman container create command.""" """Generate podman container create command."""
cmd = f"# Create container {self.name}\n" cmd = f"# Create container {self.name}"
cmd += "podman container crate \\\n" cmd += "podman container crate \\\n"
cmd += f"\t--name={self.name} \\\n" cmd += f"\t--name={self.name} \\\n"
if self.privileged: if self.privileged:

View file

@ -2,7 +2,6 @@
"""Generate the control files..""" """Generate the control files.."""
import json import json
import stat
import sys import sys
from pathlib import Path from pathlib import Path
@ -49,21 +48,17 @@ def create_container_from_config(data: dict, log: Log) -> Container | None:
def main() -> None: def main() -> None:
"""Run the program.""" """Run the program."""
config_threshold = 2 argc_threshold = 2
log_threshold = 3 if len(sys.argv) < argc_threshold:
if len(sys.argv) < config_threshold:
logger = Log("/dev/stdout") logger = Log("/dev/stdout")
logger.log_error("No arguments passed!") logger.log_error("No arguments passed!")
sys.exit(1) sys.exit(1)
config_file = "" config_file = ""
log_file = "" log_file = ""
base = "/var/lib/containerctl/containers" if len(sys.argv) >= argc_threshold:
if len(sys.argv) >= config_threshold:
config_file = sys.argv[1] config_file = sys.argv[1]
if len(sys.argv) >= log_threshold: if len(sys.argv) > argc_threshold:
log_file = sys.argv[2] log_file = sys.argv[2]
if len(sys.argv) > log_threshold:
base = sys.argv[3]
logger = Log(log_file) logger = Log(log_file)
data = load_container_config(Path(config_file), logger) data = load_container_config(Path(config_file), logger)
if data is None: if data is None:
@ -71,42 +66,11 @@ def main() -> None:
sys.exit(1) sys.exit(1)
try: try:
ct = create_container_from_config(data, logger) ct = create_container_from_config(data, logger)
except ConfigError as e: except Exception as e: # noqa: BLE001
logger.log_error(e) logger.log_error(e)
sys.exit(1) sys.exit(1)
scripts = { print(ct)
"create-volumes": ct.create_volumes, print(vars(ct))
"create-secrets": ct.create_secrets,
"create-environment": ct.create_environment,
"remove-volumes": ct.remove_volumes,
"remove-secrets": ct.remove_secrets,
"create": ct.create_container,
"remove": ct.remove_container,
"purge": ct.purge_container,
"start": ct.start_container,
"stop": ct.stop_container,
"restart": ct.restart_container,
"upgrade": ct.upgrade_container,
}
base = f"{base}/{ct.name}"
if not Path(base).exists():
Path(base).mkdir()
for script, method in scripts.items():
s = Path(f"{base}/{script}")
with s.open("w+", encoding="utf-8") as f:
f.write("#!/bin/sh\n")
if script == "create":
f.write(ct.create_volumes())
f.write(ct.create_secrets())
f.write(ct.create_environment())
f.write(method())
s.chmod(
stat.S_IRWXU
| stat.S_IRGRP
| stat.S_IXGRP
| stat.S_IROTH
| stat.S_IXOTH,
)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -64,7 +64,7 @@ class Log:
print(msg) print(msg)
if self.logfile == Path("/dev/stdout"): if self.logfile == Path("/dev/stdout"):
return return
with self.logfile.open("a+", encoding="utf-8") as f: with self.logfile.open("a+") as f:
f.write(msg) f.write(msg)
def timestamp(self) -> str: def timestamp(self) -> str: