add virt
This commit is contained in:
259
lib/virt/docker/docker_engine.v
Normal file
259
lib/virt/docker/docker_engine.v
Normal file
@@ -0,0 +1,259 @@
|
||||
module docker
|
||||
|
||||
import freeflowuniverse.herolib.osal { cputype, exec, platform }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.virt.utils
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
// import freeflowuniverse.herolib.installers.swarm
|
||||
|
||||
// https://docs.docker.com/reference/
|
||||
|
||||
@[heap]
|
||||
pub struct DockerEngine {
|
||||
name string
|
||||
pub mut:
|
||||
sshkeys_allowed []string // all keys here have access over ssh into the machine, when ssh enabled
|
||||
images []DockerImage
|
||||
containers []DockerContainer
|
||||
buildpath string
|
||||
localonly bool
|
||||
cache bool = true
|
||||
push bool
|
||||
platform []BuildPlatformType // used to build
|
||||
registries []DockerRegistry // one or more supported DockerRegistries
|
||||
prefix string
|
||||
}
|
||||
|
||||
pub enum BuildPlatformType {
|
||||
linux_arm64
|
||||
linux_amd64
|
||||
}
|
||||
|
||||
// check docker has been installed & enabled on node
|
||||
pub fn (mut e DockerEngine) init() ! {
|
||||
if e.buildpath == '' {
|
||||
e.buildpath = '/tmp/builder'
|
||||
exec(cmd: 'mkdir -p ${e.buildpath}', stdout: false)!
|
||||
}
|
||||
if e.platform == [] {
|
||||
if platform() == .ubuntu && cputype() == .intel {
|
||||
e.platform = [.linux_amd64]
|
||||
} else if platform() == .osx && cputype() == .arm {
|
||||
e.platform = [.linux_arm64]
|
||||
} else {
|
||||
return error('only implemented ubuntu on amd and osx on arm for now for docker engine.')
|
||||
}
|
||||
}
|
||||
e.load()!
|
||||
}
|
||||
|
||||
// reload the state from system
|
||||
pub fn (mut e DockerEngine) load() ! {
|
||||
e.images_load()!
|
||||
e.containers_load()!
|
||||
}
|
||||
|
||||
// load all containers, they can be consulted in e.containers
|
||||
// see obj: DockerContainer as result in e.containers
|
||||
pub fn (mut e DockerEngine) containers_load() ! {
|
||||
e.containers = []DockerContainer{}
|
||||
mut ljob := exec(
|
||||
// we used || because sometimes the command has | in it and this will ruin all subsequent columns
|
||||
cmd: "docker ps -a --no-trunc --format '{{.ID}}||{{.Names}}||{{.Image}}||{{.Command}}||{{.CreatedAt}}||{{.Ports}}||{{.State}}||{{.Size}}||{{.Mounts}}||{{.Networks}}||{{.Labels}}'"
|
||||
ignore_error_codes: [6]
|
||||
stdout: false
|
||||
)!
|
||||
lines := ljob.output
|
||||
for line in lines {
|
||||
if line.trim_space() == '' {
|
||||
continue
|
||||
}
|
||||
fields := line.split('||').map(utils.clear_str)
|
||||
if fields.len < 11 {
|
||||
panic('docker ps needs to output 11 parts.\n${fields}')
|
||||
}
|
||||
id := fields[0]
|
||||
mut container := DockerContainer{
|
||||
engine: &e
|
||||
image: e.image_get(id: fields[2])!
|
||||
}
|
||||
|
||||
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.networks = utils.parse_networks(fields[9])!
|
||||
container.labels = utils.parse_labels(fields[10])!
|
||||
container.ssh_enabled = utils.contains_ssh_port(container.ports)
|
||||
// console.print_debug(container)
|
||||
e.containers << container
|
||||
}
|
||||
}
|
||||
|
||||
// EXISTS, GET
|
||||
|
||||
@[params]
|
||||
pub struct ContainerGetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
id string
|
||||
image_id string
|
||||
// tag string
|
||||
// digest string
|
||||
}
|
||||
|
||||
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 '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')
|
||||
}
|
||||
|
||||
// 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 DockerEngine) containers_get(args_ ContainerGetArgs) ![]&DockerContainer {
|
||||
mut args := args_
|
||||
args.name = texttools.name_fix(args.name)
|
||||
mut res := []&DockerContainer{}
|
||||
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 DockerEngine) container_get(args_ ContainerGetArgs) !&DockerContainer {
|
||||
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 DockerEngine) container_exists(args ContainerGetArgs) !bool {
|
||||
e.container_get(args) or {
|
||||
if err.code() == 1 {
|
||||
return false
|
||||
}
|
||||
return err
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (mut e DockerEngine) container_delete(args ContainerGetArgs) ! {
|
||||
mut c := e.container_get(args)!
|
||||
c.delete()!
|
||||
e.load()!
|
||||
}
|
||||
|
||||
// remove one or more container
|
||||
pub fn (mut e DockerEngine) containers_delete(args ContainerGetArgs) ! {
|
||||
mut cs := e.containers_get(args)!
|
||||
for mut c in cs {
|
||||
c.delete()!
|
||||
}
|
||||
e.load()!
|
||||
}
|
||||
|
||||
// import a container into an image, run docker container with it
|
||||
// image_repo examples ['myimage', 'myimage:latest']
|
||||
// if DockerContainerCreateArgs contains a name, container will be created and restarted
|
||||
pub fn (mut e DockerEngine) container_import(path string, mut args DockerContainerCreateArgs) !&DockerContainer {
|
||||
mut image := args.image_repo
|
||||
if args.image_tag != '' {
|
||||
image = image + ':${args.image_tag}'
|
||||
}
|
||||
|
||||
exec(cmd: 'docker import ${path} ${image}', stdout: false)!
|
||||
// make sure we start from loaded image
|
||||
return e.container_create(args)
|
||||
}
|
||||
|
||||
// reset all images & containers, CAREFUL!
|
||||
pub fn (mut e DockerEngine) reset_all() ! {
|
||||
for mut container in e.containers.clone() {
|
||||
container.delete()!
|
||||
}
|
||||
for mut image in e.images.clone() {
|
||||
image.delete(true)!
|
||||
}
|
||||
exec(cmd: 'docker image prune -a -f', stdout: false) or { panic(err) }
|
||||
exec(cmd: 'docker builder prune -a -f', stdout: false) or { panic(err) }
|
||||
osal.done_reset()!
|
||||
e.load()!
|
||||
}
|
||||
|
||||
// Get free port
|
||||
pub fn (mut e DockerEngine) get_free_port() ?int {
|
||||
mut used_ports := []int{}
|
||||
mut range := []int{}
|
||||
|
||||
for c in e.containers {
|
||||
for p in c.forwarded_ports {
|
||||
used_ports << p.split(':')[0].int()
|
||||
}
|
||||
}
|
||||
|
||||
for i in 20000 .. 40000 {
|
||||
if i !in used_ports {
|
||||
range << i
|
||||
}
|
||||
}
|
||||
// arrays.shuffle<int>(mut range, 0)
|
||||
if range.len == 0 {
|
||||
return none
|
||||
}
|
||||
return range[0]
|
||||
}
|
||||
Reference in New Issue
Block a user