Compare commits
9 commits
aa13b77758
...
d5ea5e64ee
Author | SHA1 | Date | |
---|---|---|---|
d5ea5e64ee | |||
9805419555 | |||
b3fe3b8a10 | |||
94fcd6828f | |||
d67137363f | |||
2e793fd31f | |||
11d6b574f3 | |||
e3125ea4fe | |||
8f156e9f70 |
4 changed files with 92 additions and 25 deletions
49
containerctl
49
containerctl
|
@ -11,9 +11,42 @@ LOGDIR="/var/log/containerctl"
|
|||
TODAY="$(date '+%F')"
|
||||
LOG="${LOGDIR}/${TODAY}"
|
||||
|
||||
get_python_path()
|
||||
{
|
||||
py="python3"
|
||||
pyver="$(/usr/bin/env "${py}" -c 'import sys; print(sys.version_info.minor)')"
|
||||
if [ "${pyver}" -lt "11" ]
|
||||
then
|
||||
py="python3.13"
|
||||
else
|
||||
printf '%b' "${py}"
|
||||
return
|
||||
fi
|
||||
|
||||
if /usr/bin/env "${py}" 2> /dev/null
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
py="python3.12"
|
||||
if /usr/bin/env "${py}" 2> /dev/null
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
py="python3.11"
|
||||
if /usr/bin/env "${py}" 2> /dev/null
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
log_error 'containerctl needs at least Python 3.11 to run!'
|
||||
exit 1
|
||||
}
|
||||
|
||||
log_error()
|
||||
{
|
||||
printf '[%b] (EE) %b\n' "${TODAY}" "${@}" | tee -a "${LOG}"
|
||||
printf '[%b] (EE) %b\n' "${TODAY}" "${@}" | tee -a "${LOG}" 2> /dev/null
|
||||
}
|
||||
|
||||
list_containers()
|
||||
|
@ -106,12 +139,7 @@ generate_container()
|
|||
exit 1
|
||||
fi
|
||||
|
||||
mypython="python3"
|
||||
pyver="$(/usr/bin/env "${mypython}" -c 'import sys; print(sys.version_info.minor)')"
|
||||
if [ "${pyver}" -gt "11" ]
|
||||
then
|
||||
mypython="python3.11"
|
||||
fi
|
||||
mypython="$(get_python_path)"
|
||||
/usr/bin/env "${mypython}" "${BASEDIR}/generate/generate.py" \
|
||||
"${CONFIGDIR}/${config}" "${LOG}" "${CONTAINERDIR}"
|
||||
|
||||
|
@ -130,10 +158,17 @@ generate_all()
|
|||
done
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
printf '%b list-containers|list-configs|generate CONFIG-FILE|generate-all|CONTAINER-NAME ACTION\n' "${0}"
|
||||
}
|
||||
|
||||
case "${1}" in
|
||||
"list-containers") list_containers ;;
|
||||
"list-configs") list_configs ;;
|
||||
"generate-all") generate_all ;;
|
||||
"generate") shift; generate_container "${@}" ;;
|
||||
"help") usage "${0}" ;;
|
||||
"usage") usage "${0}" ;;
|
||||
*) exec_script "${@}" ;;
|
||||
esac
|
||||
|
|
|
@ -415,7 +415,7 @@ class Environment:
|
|||
if cmd == "":
|
||||
return ""
|
||||
|
||||
return header + cmd
|
||||
return header + f"printf '\\n' > {self.file}\n" + cmd
|
||||
|
||||
def remove(self) -> str:
|
||||
"""Remove env file."""
|
||||
|
@ -665,15 +665,44 @@ class ContainerOptions:
|
|||
return ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class ContainerNetwork:
|
||||
"""Wrapper for Network, Dns and Ports."""
|
||||
|
||||
network: Network
|
||||
dns: Dns
|
||||
ports: Ports
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json: ConfigValue, logger: Log) -> Self:
|
||||
"""Create from JSON."""
|
||||
network_config = maybe(json, "network")
|
||||
dns_config = maybe(json, "dns")
|
||||
ports_config = maybe(json, "ports")
|
||||
|
||||
network = Network.from_json(network_config, logger)
|
||||
dns = Dns.from_json(dns_config, logger)
|
||||
ports = Ports.from_json(ports_config, logger)
|
||||
|
||||
return cls(network, dns, ports)
|
||||
|
||||
def command(self) -> str:
|
||||
"""Option for podman container create."""
|
||||
cmd = ""
|
||||
cmd += self.network.command()
|
||||
cmd += self.dns.command()
|
||||
cmd += self.ports.command()
|
||||
|
||||
return cmd
|
||||
|
||||
|
||||
class Container:
|
||||
"""Container."""
|
||||
|
||||
name: str
|
||||
image: Image
|
||||
ct_opts: ContainerOptions
|
||||
network: Network
|
||||
dns: Dns
|
||||
ports: Ports
|
||||
ct_network: ContainerNetwork
|
||||
env: Environment
|
||||
secrets: list
|
||||
volumes: list
|
||||
|
@ -695,9 +724,6 @@ class Container:
|
|||
ct_opts = ContainerOptions.from_json(json, logger)
|
||||
if not ct_opts.is_valid:
|
||||
return
|
||||
network = maybe(json, "network")
|
||||
dns = maybe(json, "dns")
|
||||
ports = maybe(json, "ports")
|
||||
env = maybe(json, "env")
|
||||
secrets = maybe(json, "secrets")
|
||||
volumes = maybe(json, "volumes")
|
||||
|
@ -706,9 +732,7 @@ class Container:
|
|||
self.name = str(name)
|
||||
self.image = Image.from_json(image, logger)
|
||||
self.ct_opts = ct_opts
|
||||
self.network = Network.from_json(network, logger)
|
||||
self.dns = Dns.from_json(dns, logger)
|
||||
self.ports = Ports.from_json(ports, logger)
|
||||
self.ct_network = ContainerNetwork.from_json(json, logger)
|
||||
self.env = Environment.from_json(env, logger)
|
||||
self.env.file = "/var/lib/containerctl/environment-files/"
|
||||
self.env.file += f"{self.name}"
|
||||
|
@ -747,9 +771,7 @@ class Container:
|
|||
cmd += "podman container create \\\n"
|
||||
cmd += f"\t--name={self.name} \\\n"
|
||||
cmd += f"{self.ct_opts.command()}"
|
||||
cmd += f"{self.network.command()}"
|
||||
cmd += f"{self.dns.command()}"
|
||||
cmd += f"{self.ports.command()}"
|
||||
cmd += f"{self.ct_network.command()}"
|
||||
cmd += f"{self.env.command()}"
|
||||
for secret in self.secrets:
|
||||
cmd += f"{secret.command()}"
|
||||
|
|
|
@ -14,7 +14,7 @@ from pathlib import Path
|
|||
from container import ConfigError, Container
|
||||
from log import Log
|
||||
|
||||
GENERATE_VERSION = "0.0.11"
|
||||
GENERATE_VERSION = "0.0.13"
|
||||
HEADER = f"""#!/bin/sh
|
||||
# This script was generated by containerctl v{GENERATE_VERSION}
|
||||
# Report bugs with _this script_ to <tenno+containerctl@suij.in>
|
||||
|
@ -80,6 +80,7 @@ def main() -> None:
|
|||
if data is None:
|
||||
logger.log_error(f"{config_file} is invalid, aborting!")
|
||||
sys.exit(1)
|
||||
logger.set_prefix(Path(config_file).name)
|
||||
ct = create_container_from_config(data, logger)
|
||||
if ct is None:
|
||||
sys.exit(1)
|
||||
|
|
|
@ -15,6 +15,7 @@ class Log:
|
|||
|
||||
messages: list = []
|
||||
logfile: Path
|
||||
prefix: str = ""
|
||||
|
||||
def __init__(self, path: str) -> None:
|
||||
"""Init for Log."""
|
||||
|
@ -25,15 +26,19 @@ class Log:
|
|||
def log_error(self, msg: str) -> None:
|
||||
"""Log an error."""
|
||||
now = self.timestamp()
|
||||
prefix = "EE"
|
||||
log_message = f"[{now}] ({prefix}) {msg}"
|
||||
prefix = "(EE)"
|
||||
if self.prefix != "":
|
||||
prefix += f" {self.prefix}:"
|
||||
log_message = f"[{now}] {prefix} {msg}"
|
||||
self.write_message(log_message)
|
||||
|
||||
def log_warning(self, msg: str) -> None:
|
||||
"""Log a warning."""
|
||||
now = self.timestamp()
|
||||
prefix = "WW"
|
||||
log_message = f"[{now}] ({prefix}) {msg}"
|
||||
prefix = "(WW)"
|
||||
if self.prefix != "":
|
||||
prefix += f" {self.prefix}:"
|
||||
log_message = f"[{now}] {prefix} {msg}"
|
||||
self.write_message(log_message)
|
||||
|
||||
def write_message(self, msg: str) -> None:
|
||||
|
@ -49,3 +54,7 @@ class Log:
|
|||
return datetime.datetime.now(tz=datetime.UTC).strftime(
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
|
||||
def set_prefix(self, prefix: str) -> None:
|
||||
"""Set a prefix."""
|
||||
self.prefix = prefix
|
||||
|
|
Loading…
Add table
Reference in a new issue