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