219 lines
5.5 KiB
V
219 lines
5.5 KiB
V
module herocontainers
|
|
|
|
import time
|
|
import freeflowuniverse.herolib.osal { exec }
|
|
import freeflowuniverse.herolib.data.ipaddress
|
|
import freeflowuniverse.herolib.core.texttools
|
|
import freeflowuniverse.herolib.virt.utils
|
|
import freeflowuniverse.herolib.ui.console
|
|
|
|
// info see https://docs.podman.io/en/latest/markdown/podman-run.1.html
|
|
|
|
@[params]
|
|
pub struct ContainerCreateArgs {
|
|
name string
|
|
hostname string
|
|
forwarded_ports []string // ["80:9000/tcp", "1000, 10000/udp"]
|
|
mounted_volumes []string // ["/root:/root", ]
|
|
env map[string]string // map of environment variables that will be passed to the container
|
|
privileged bool
|
|
remove_when_done bool = true // remove the container when it shuts down
|
|
// Resource limits
|
|
memory string // Memory limit (e.g. "100m", "2g")
|
|
memory_reservation string // Memory soft limit
|
|
memory_swap string // Memory + swap limit
|
|
cpus f64 // Number of CPUs (e.g. 1.5)
|
|
cpu_shares int // CPU shares (relative weight)
|
|
cpu_period int // CPU CFS period in microseconds (default: 100000)
|
|
cpu_quota int // CPU CFS quota in microseconds (e.g. 50000 for 0.5 CPU)
|
|
cpuset_cpus string // CPUs in which to allow execution (e.g. "0-3", "1,3")
|
|
// Network configuration
|
|
network string // Network mode (bridge, host, none, container:id)
|
|
network_aliases []string // Add network-scoped aliases
|
|
exposed_ports []string // Ports to expose without publishing (e.g. "80/tcp", "53/udp")
|
|
// DNS configuration
|
|
dns_servers []string // Set custom DNS servers
|
|
dns_options []string // Set custom DNS options
|
|
dns_search []string // Set custom DNS search domains
|
|
// Device configuration
|
|
devices []string // Host devices to add (e.g. "/dev/sdc:/dev/xvdc:rwm")
|
|
device_cgroup_rules []string // Add rules to cgroup allowed devices list
|
|
// Runtime configuration
|
|
detach bool = true // Run container in background
|
|
attach []string // Attach to STDIN, STDOUT, and/or STDERR
|
|
interactive bool // Keep STDIN open even if not attached (-i)
|
|
// Storage configuration
|
|
rootfs string // Use directory as container's root filesystem
|
|
mounts []string // Mount filesystem (type=bind,src=,dst=,etc)
|
|
volumes []string // Bind mount a volume (alternative to mounted_volumes)
|
|
published_ports []string // Publish container ports to host (alternative to forwarded_ports)
|
|
pub mut:
|
|
image_repo string
|
|
image_tag string
|
|
command string = '/bin/bash'
|
|
}
|
|
|
|
// create a new container from an image
|
|
pub fn (mut e CEngine) container_create(args_ ContainerCreateArgs) !&Container {
|
|
mut args := args_
|
|
|
|
mut cmd := 'podman run --systemd=false'
|
|
|
|
// Handle detach/attach options
|
|
if args.detach {
|
|
cmd += ' -d'
|
|
}
|
|
for stream in args.attach {
|
|
cmd += ' -a ${stream}'
|
|
}
|
|
|
|
if args.name != '' {
|
|
cmd += ' --name ${texttools.name_fix(args.name)}'
|
|
}
|
|
|
|
if args.hostname != '' {
|
|
cmd += ' --hostname ${args.hostname}'
|
|
}
|
|
|
|
if args.privileged {
|
|
cmd += ' --privileged'
|
|
}
|
|
|
|
if args.remove_when_done {
|
|
cmd += ' --rm'
|
|
}
|
|
|
|
// Handle interactive mode
|
|
if args.interactive {
|
|
cmd += ' -i'
|
|
}
|
|
|
|
// Handle rootfs
|
|
if args.rootfs != '' {
|
|
cmd += ' --rootfs ${args.rootfs}'
|
|
}
|
|
|
|
// Add mount points
|
|
for mount in args.mounts {
|
|
cmd += ' --mount ${mount}'
|
|
}
|
|
|
|
// Add volumes (--volume syntax)
|
|
for volume in args.volumes {
|
|
cmd += ' --volume ${volume}'
|
|
}
|
|
|
|
// Add published ports (--publish syntax)
|
|
for port in args.published_ports {
|
|
cmd += ' --publish ${port}'
|
|
}
|
|
|
|
// Add resource limits
|
|
if args.memory != '' {
|
|
cmd += ' --memory ${args.memory}'
|
|
}
|
|
|
|
if args.memory_reservation != '' {
|
|
cmd += ' --memory-reservation ${args.memory_reservation}'
|
|
}
|
|
|
|
if args.memory_swap != '' {
|
|
cmd += ' --memory-swap ${args.memory_swap}'
|
|
}
|
|
|
|
if args.cpus > 0 {
|
|
cmd += ' --cpus ${args.cpus}'
|
|
}
|
|
|
|
if args.cpu_shares > 0 {
|
|
cmd += ' --cpu-shares ${args.cpu_shares}'
|
|
}
|
|
|
|
if args.cpu_period > 0 {
|
|
cmd += ' --cpu-period ${args.cpu_period}'
|
|
}
|
|
|
|
if args.cpu_quota > 0 {
|
|
cmd += ' --cpu-quota ${args.cpu_quota}'
|
|
}
|
|
|
|
if args.cpuset_cpus != '' {
|
|
cmd += ' --cpuset-cpus ${args.cpuset_cpus}'
|
|
}
|
|
|
|
// Add network configuration
|
|
if args.network != '' {
|
|
cmd += ' --network ${args.network}'
|
|
}
|
|
|
|
// Add network aliases
|
|
for alias in args.network_aliases {
|
|
cmd += ' --network-alias ${alias}'
|
|
}
|
|
|
|
// Add exposed ports
|
|
for port in args.exposed_ports {
|
|
cmd += ' --expose ${port}'
|
|
}
|
|
|
|
// Add devices
|
|
for device in args.devices {
|
|
cmd += ' --device ${device}'
|
|
}
|
|
|
|
// Add device cgroup rules
|
|
for rule in args.device_cgroup_rules {
|
|
cmd += ' --device-cgroup-rule ${rule}'
|
|
}
|
|
|
|
// Add DNS configuration
|
|
for server in args.dns_servers {
|
|
cmd += ' --dns ${server}'
|
|
}
|
|
|
|
for opt in args.dns_options {
|
|
cmd += ' --dns-option ${opt}'
|
|
}
|
|
|
|
for search in args.dns_search {
|
|
cmd += ' --dns-search ${search}'
|
|
}
|
|
|
|
// Add port forwarding
|
|
for port in args.forwarded_ports {
|
|
cmd += ' -p ${port}'
|
|
}
|
|
|
|
// Add volume mounts
|
|
for volume in args.mounted_volumes {
|
|
cmd += ' -v ${volume}'
|
|
}
|
|
|
|
// Add environment variables
|
|
for key, value in args.env {
|
|
cmd += ' -e ${key}=${value}'
|
|
}
|
|
|
|
// Add image name and tag
|
|
mut image_name := args.image_repo
|
|
if args.image_tag != '' {
|
|
image_name += ':${args.image_tag}'
|
|
}
|
|
cmd += ' ${image_name}'
|
|
|
|
// Add command if specified
|
|
if args.command != '' {
|
|
cmd += ' ${args.command}'
|
|
}
|
|
|
|
// Create the container
|
|
mut ljob := exec(cmd: cmd, stdout: false)!
|
|
container_id := ljob.output.trim_space()
|
|
|
|
// Reload containers to get the new one
|
|
e.load()!
|
|
|
|
// Return the newly created container
|
|
return e.container_get(name: args.name, id: container_id)!
|
|
}
|