Compare commits
No commits in common. "aa13b777585f80b8e88d46a4a50b832d0b37106e" and "fb6aadb63cf04061308616829a9a8179529dfb27" have entirely different histories.
aa13b77758
...
fb6aadb63c
3 changed files with 67 additions and 113 deletions
|
@ -16,9 +16,6 @@
|
|||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -55,7 +52,11 @@
|
|||
"type": "array",
|
||||
"items": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"options"
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"type": "object",
|
||||
|
@ -71,7 +72,11 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"search",
|
||||
"servers"
|
||||
]
|
||||
},
|
||||
"ports": {
|
||||
"type": "object",
|
||||
|
@ -92,7 +97,11 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"env": {
|
||||
"type": "object"
|
||||
|
@ -123,7 +132,11 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"add",
|
||||
"drop"
|
||||
]
|
||||
},
|
||||
"accounting": {
|
||||
"type": "object",
|
||||
|
|
|
@ -244,7 +244,7 @@ class Volume:
|
|||
"""Container Volume."""
|
||||
|
||||
name: str
|
||||
path: list
|
||||
path: str
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, val: ConfigValue, logger: Log) -> list:
|
||||
|
@ -254,16 +254,7 @@ class Volume:
|
|||
if not isinstance(val, dict):
|
||||
logger.log_warning("Volume key is present, but malformed.")
|
||||
return []
|
||||
return [
|
||||
Volume.from_json_entry(key, value) for key, value in val.items()
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def from_json_entry(cls, key: str, value: str | list) -> Self:
|
||||
"""Create from JSON entry."""
|
||||
if isinstance(value, str):
|
||||
return cls(key, [value])
|
||||
return cls(key, value)
|
||||
return [cls(key, value) for key, value in val.items()]
|
||||
|
||||
def is_host_volume(self) -> bool:
|
||||
"""Check if this Volume is a named or a host volume."""
|
||||
|
@ -271,10 +262,7 @@ class Volume:
|
|||
|
||||
def command(self) -> str:
|
||||
"""Option for podman container create."""
|
||||
cmd = ""
|
||||
for path in self.path:
|
||||
cmd += f"\t--volume {self.name}:{path} \\\n"
|
||||
return cmd
|
||||
return f"--volume {self.name}:{self.path}"
|
||||
|
||||
def create(self) -> str:
|
||||
"""Create volume, if it does not exist."""
|
||||
|
@ -310,7 +298,7 @@ class Secret:
|
|||
|
||||
name: str
|
||||
secret_type: str
|
||||
target: list
|
||||
target: str
|
||||
options: str
|
||||
|
||||
@classmethod
|
||||
|
@ -328,33 +316,26 @@ class Secret:
|
|||
continue
|
||||
name = key
|
||||
secret_type = maybe_or(val[key], "type", "")
|
||||
target = maybe(val[key], "target")
|
||||
if isinstance(target, str):
|
||||
target = [target]
|
||||
if not isinstance(target, list):
|
||||
target = []
|
||||
target = maybe_or(val[key], "target", "")
|
||||
options = maybe_or(val[key], "options", "")
|
||||
if options is None:
|
||||
options = ""
|
||||
secrets.append(cls(name, str(secret_type), target, str(options)))
|
||||
secrets.append(
|
||||
cls(name, str(secret_type), str(target), str(options))
|
||||
)
|
||||
|
||||
return secrets
|
||||
|
||||
def command(self) -> str:
|
||||
"""Option for podman container create."""
|
||||
cmd = ""
|
||||
for target in self.target:
|
||||
cmd += (
|
||||
f"\t--secret {self.name},:"
|
||||
cmd = (
|
||||
f"--secret {self.name},:"
|
||||
f"type={self.secret_type},"
|
||||
f"target={target}"
|
||||
f"target={self.target}"
|
||||
)
|
||||
# Not a password, ruff...
|
||||
has_option = self.secret_type == "mount" # noqa: S105
|
||||
has_option = has_option and self.options != ""
|
||||
if has_option:
|
||||
if self.secret_type == "mount" and self.options != "": # noqa: S105
|
||||
cmd = f"{cmd},{self.options}"
|
||||
cmd += " \\\n"
|
||||
|
||||
return cmd
|
||||
|
||||
|
@ -525,7 +506,6 @@ class Image:
|
|||
registry: str
|
||||
image: str
|
||||
tag: str
|
||||
cmd: str
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, val: ConfigValue, logger: Log) -> Self | None:
|
||||
|
@ -536,13 +516,10 @@ class Image:
|
|||
registry = maybe_or(val, "registry", "")
|
||||
image = maybe_or(val, "image", "")
|
||||
tag = maybe_or(val, "tag", "")
|
||||
cmd = maybe_or(val, "command", "")
|
||||
return cls(str(registry), str(image), str(tag), cmd)
|
||||
return cls(str(registry), str(image), str(tag))
|
||||
|
||||
def command(self) -> str:
|
||||
"""Option for podman container create."""
|
||||
if self.cmd != "":
|
||||
return f"{self.registry}/{self.image}:{self.tag} {self.cmd}"
|
||||
return f"{self.registry}/{self.image}:{self.tag}"
|
||||
|
||||
|
||||
|
@ -608,69 +585,17 @@ class Dns:
|
|||
return cmd
|
||||
|
||||
|
||||
@dataclass
|
||||
class ContainerOptions:
|
||||
"""Container-Meta settings."""
|
||||
|
||||
privileged: bool = False
|
||||
read_only: bool = False
|
||||
replace: bool = False
|
||||
restart: str = "no"
|
||||
pull_policy: str = "always"
|
||||
timezone: str = "local"
|
||||
is_valid: bool = False
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, val: ConfigValue, logger: Log) -> Self:
|
||||
"""Create from JSON."""
|
||||
if val is None:
|
||||
# Should not happen!
|
||||
return cls()
|
||||
if not isinstance(val, dict):
|
||||
logger.log_error("Container config is invalid!")
|
||||
return cls()
|
||||
|
||||
privileged = maybe_or(val, "privileged", _or=False)
|
||||
read_only = maybe_or(val, "read_only", _or=False)
|
||||
replace = maybe_or(val, "replace", _or=False)
|
||||
restart = maybe_or(val, "restart", "no")
|
||||
pull_policy = maybe_or(val, "pull_policy", "always")
|
||||
timezone = maybe_or(val, "timezone", "local")
|
||||
|
||||
return cls(
|
||||
privileged,
|
||||
read_only,
|
||||
replace,
|
||||
restart,
|
||||
pull_policy,
|
||||
timezone,
|
||||
is_valid=True,
|
||||
)
|
||||
|
||||
def command(self) -> str:
|
||||
"""Option for podman conainter create."""
|
||||
cmd = ""
|
||||
if self.privileged:
|
||||
cmd += "\t--privileged \\\n"
|
||||
if self.read_only:
|
||||
cmd += "\t--read-only \\\n"
|
||||
if self.replace:
|
||||
cmd += "\t--replace \\\n"
|
||||
if self.restart != "":
|
||||
cmd += f"\t--restart={self.restart} \\\n"
|
||||
if self.pull_policy != "":
|
||||
cmd += f"\t--pull-policy={self.pull_policy} \\\n"
|
||||
if self.timezone != "":
|
||||
cmd += f"\t--tz={self.timezone} \\\n"
|
||||
return ""
|
||||
|
||||
|
||||
class Container:
|
||||
"""Container."""
|
||||
|
||||
name: str
|
||||
image: Image
|
||||
ct_opts: ContainerOptions
|
||||
privileged: bool
|
||||
read_only: bool
|
||||
replace: bool
|
||||
restart: str
|
||||
pull_policy: str
|
||||
timezone: str
|
||||
network: Network
|
||||
dns: Dns
|
||||
ports: Ports
|
||||
|
@ -692,9 +617,12 @@ class Container:
|
|||
if image is None:
|
||||
logger.log_error("No image set, aborting!")
|
||||
return
|
||||
ct_opts = ContainerOptions.from_json(json, logger)
|
||||
if not ct_opts.is_valid:
|
||||
return
|
||||
privileged = maybe(json, "privileged")
|
||||
read_only = maybe(json, "read_only")
|
||||
replace = maybe(json, "replace")
|
||||
pull_policy = maybe_or(json, "pull_policy", "always")
|
||||
restart = maybe_or(json, "restart", "no")
|
||||
timezone = maybe_or(json, "timezone", "local")
|
||||
network = maybe(json, "network")
|
||||
dns = maybe(json, "dns")
|
||||
ports = maybe(json, "ports")
|
||||
|
@ -705,7 +633,12 @@ class Container:
|
|||
accounting = maybe(json, "accounting")
|
||||
self.name = str(name)
|
||||
self.image = Image.from_json(image, logger)
|
||||
self.ct_opts = ct_opts
|
||||
self.privileged = privileged is not None and bool(privileged)
|
||||
self.read_only = read_only is not None and bool(read_only)
|
||||
self.replace = replace is not None and bool(replace)
|
||||
self.pull_policy = str(pull_policy)
|
||||
self.restart = str(restart)
|
||||
self.timezone = str(timezone)
|
||||
self.network = Network.from_json(network, logger)
|
||||
self.dns = Dns.from_json(dns, logger)
|
||||
self.ports = Ports.from_json(ports, logger)
|
||||
|
@ -746,15 +679,23 @@ class Container:
|
|||
cmd = f"# Create container {self.name}\n"
|
||||
cmd += "podman container create \\\n"
|
||||
cmd += f"\t--name={self.name} \\\n"
|
||||
cmd += f"{self.ct_opts.command()}"
|
||||
if self.privileged:
|
||||
cmd += "\t--privileged \\\n"
|
||||
if self.replace:
|
||||
cmd += "\t--replace \\\n"
|
||||
if self.read_only:
|
||||
cmd += "\t--read-only \\\n"
|
||||
cmd += f"\t--restart={self.restart} \\\n"
|
||||
cmd += f"\t--pull={self.pull_policy} \\\n"
|
||||
cmd += f"\t--tz={self.timezone} \\\n"
|
||||
cmd += f"{self.network.command()}"
|
||||
cmd += f"{self.dns.command()}"
|
||||
cmd += f"{self.ports.command()}"
|
||||
cmd += f"{self.env.command()}"
|
||||
for secret in self.secrets:
|
||||
cmd += f"{secret.command()}"
|
||||
cmd += f"\t{secret.command()} \\\n"
|
||||
for volume in self.volumes:
|
||||
cmd += f"{volume.command()}"
|
||||
cmd += f"\t{volume.command()} \\\n"
|
||||
for capability in self.capabilities:
|
||||
cmd += f"\t{capability.command()} \\\n"
|
||||
cmd += f"{self.accounting.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.9"
|
||||
HEADER = f"""#!/bin/sh
|
||||
# This script was generated by containerctl v{GENERATE_VERSION}
|
||||
# Report bugs with _this script_ to <tenno+containerctl@suij.in>
|
||||
|
|
Loading…
Add table
Reference in a new issue