Files
herolib/lib/virt/herocontainers/cengine_containers.v
2024-12-25 20:13:02 +01:00

164 lines
4.2 KiB
V

module herocontainers
import freeflowuniverse.herolib.osal { exec }
// import freeflowuniverse.herolib.data.ipaddress { IPAddress }
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.virt.utils
// import freeflowuniverse.herolib.ui.console
// load all containers, they can be consulted in e.containers
// see obj: Container as result in e.containers
fn (mut e CEngine) containers_load() ! {
e.containers = []Container{}
mut ljob := exec(
// we used || because sometimes the command has | in it and this will ruin all subsequent columns
cmd: "podman container list -a --no-trunc --size --format '{{.ID}}||{{.Names}}||{{.ImageID}}||{{.Command}}||{{.CreatedAt}}||{{.Ports}}||{{.State}}||{{.Size}}||{{.Mounts}}||{{.Networks}}||{{.Labels}}'"
ignore_error_codes: [6]
stdout: false
)!
lines := ljob.output.split_into_lines()
for line in lines {
if line.trim_space() == '' {
continue
}
fields := line.split('||').map(utils.clear_str)
if fields.len < 11 {
panic('podman ps needs to output 11 parts.\n${fields}')
}
id := fields[0]
// if image doesn't have id skip this container, maybe ran from filesystme
if fields[2] == '' {
continue
}
mut image := e.image_get(id_full: fields[2])!
mut container := Container{
engine: &e
image: &image
}
container.id = id
container.name = texttools.name_fix(fields[1])
container.command = fields[3]
container.created = utils.parse_time(fields[4])!
container.ports = utils.parse_ports(fields[5])!
container.status = utils.parse_container_state(fields[6])!
container.memsize = utils.parse_size_mb(fields[7])!
container.mounts = utils.parse_mounts(fields[8])!
container.mounts = []
container.networks = utils.parse_networks(fields[9])!
container.labels = utils.parse_labels(fields[10])!
container.ssh_enabled = utils.contains_ssh_port(container.ports)
e.containers << container
}
}
@[params]
pub struct ContainerGetArgs {
pub mut:
name string
id string
image_id string
// tag string
// digest string
}
// get containers from memory
// params:
// name string (can also be a glob e.g. use *,? and [])
// id string
// image_id string
pub fn (mut e CEngine) containers_get(args_ ContainerGetArgs) ![]&Container {
mut args := args_
args.name = texttools.name_fix(args.name)
mut res := []&Container{}
for _, c in e.containers {
if args.name.contains('*') || args.name.contains('?') || args.name.contains('[') {
if c.name.match_glob(args.name) {
res << &c
continue
}
} else {
if c.name == args.name || c.id == args.id {
res << &c
continue
}
}
if args.image_id.len > 0 && c.image.id == args.image_id {
res << &c
}
}
if res.len == 0 {
return ContainerGetError{
args: args
notfound: true
}
}
return res
}
// get container from memory, can use match_glob see https://modules.vlang.io/index.html#string.match_glob
pub fn (mut e CEngine) container_get(args_ ContainerGetArgs) !&Container {
mut args := args_
args.name = texttools.name_fix(args.name)
mut res := e.containers_get(args)!
if res.len > 1 {
return ContainerGetError{
args: args
notfound: true
}
}
return res[0]
}
pub fn (mut e CEngine) container_exists(args ContainerGetArgs) !bool {
e.container_get(args) or {
if err.code() == 1 {
return false
}
return err
}
return true
}
pub fn (mut e CEngine) container_delete(args ContainerGetArgs) ! {
mut c := e.container_get(args)!
c.delete()!
e.load()!
}
// remove one or more container
pub fn (mut e CEngine) containers_delete(args ContainerGetArgs) ! {
mut cs := e.containers_get(args)!
for mut c in cs {
c.delete()!
}
e.load()!
}
pub struct ContainerGetError {
Error
pub:
args ContainerGetArgs
notfound bool
toomany bool
}
pub fn (err ContainerGetError) msg() string {
if err.notfound {
return 'Could not find image with args:\n${err.args}'
}
if err.toomany {
return 'can not get container, Found more than 1 container with args:\n${err.args}'
}
panic('unknown error for ContainerGetError')
}
pub fn (err ContainerGetError) code() int {
if err.notfound {
return 1
}
if err.toomany {
return 2
}
panic('unknown error for ContainerGetError')
}