...
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
module builder
|
|
||||||
|
|
||||||
fn test_nodedb() {
|
|
||||||
// TODO URGENT create tests for nodedb
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_nodedone() {
|
|
||||||
// TODO URGENT create tests for nodedone
|
|
||||||
}
|
|
||||||
311
lib/freeflowuniverse/herolib/core/playcmds/play_osal_core.v
Normal file
311
lib/freeflowuniverse/herolib/core/playcmds/play_osal_core.v
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
module playcmds
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.core.playbook { PlayBook }
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
|
||||||
|
pub fn play_osal_core(mut plbook PlayBook) ! {
|
||||||
|
if !plbook.exists(filter: 'osal.') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
play_done(mut plbook)!
|
||||||
|
play_env(mut plbook)!
|
||||||
|
play_exec(mut plbook)!
|
||||||
|
play_package(mut plbook)!
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_done(mut plbook PlayBook) ! {
|
||||||
|
// Handle !!osal.done_set actions
|
||||||
|
mut done_set_actions := plbook.find(filter: 'osal.done_set')!
|
||||||
|
for mut action in done_set_actions {
|
||||||
|
mut p := action.params
|
||||||
|
key := p.get('key')!
|
||||||
|
value := p.get('value')!
|
||||||
|
|
||||||
|
console.print_header('Setting done key: ${key} = ${value}')
|
||||||
|
osal.done_set(key, value)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.done_delete actions
|
||||||
|
mut done_delete_actions := plbook.find(filter: 'osal.done_delete')!
|
||||||
|
for mut action in done_delete_actions {
|
||||||
|
mut p := action.params
|
||||||
|
key := p.get('key')!
|
||||||
|
|
||||||
|
console.print_header('Deleting done key: ${key}')
|
||||||
|
osal.done_delete(key)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.done_reset actions
|
||||||
|
mut done_reset_actions := plbook.find(filter: 'osal.done_reset')!
|
||||||
|
for mut action in done_reset_actions {
|
||||||
|
console.print_header('Resetting all done keys')
|
||||||
|
osal.done_reset()!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.done_print actions
|
||||||
|
mut done_print_actions := plbook.find(filter: 'osal.done_print')!
|
||||||
|
for mut action in done_print_actions {
|
||||||
|
console.print_header('Printing all done keys')
|
||||||
|
osal.done_print()!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_env(mut plbook PlayBook) ! {
|
||||||
|
// Handle !!osal.env_set actions
|
||||||
|
mut env_set_actions := plbook.find(filter: 'osal.env_set')!
|
||||||
|
for mut action in env_set_actions {
|
||||||
|
mut p := action.params
|
||||||
|
key := p.get('key')!
|
||||||
|
value := p.get('value')!
|
||||||
|
overwrite := p.get_default_true('overwrite')
|
||||||
|
|
||||||
|
console.print_header('Setting environment variable: ${key}')
|
||||||
|
osal.env_set(key: key, value: value, overwrite: overwrite)
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.env_unset actions
|
||||||
|
mut env_unset_actions := plbook.find(filter: 'osal.env_unset')!
|
||||||
|
for mut action in env_unset_actions {
|
||||||
|
mut p := action.params
|
||||||
|
key := p.get('key')!
|
||||||
|
|
||||||
|
console.print_header('Unsetting environment variable: ${key}')
|
||||||
|
osal.env_unset(key)
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.env_unset_all actions
|
||||||
|
mut env_unset_all_actions := plbook.find(filter: 'osal.env_unset_all')!
|
||||||
|
for mut action in env_unset_all_actions {
|
||||||
|
console.print_header('Unsetting all environment variables')
|
||||||
|
osal.env_unset_all()
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.env_set_all actions
|
||||||
|
mut env_set_all_actions := plbook.find(filter: 'osal.env_set_all')!
|
||||||
|
for mut action in env_set_all_actions {
|
||||||
|
mut p := action.params
|
||||||
|
clear_before_set := p.get_default_false('clear_before_set')
|
||||||
|
overwrite_if_exists := p.get_default_true('overwrite_if_exists')
|
||||||
|
|
||||||
|
// Parse environment variables from parameters
|
||||||
|
mut env_map := map[string]string{}
|
||||||
|
param_map := p.get_map()
|
||||||
|
for key, value in param_map {
|
||||||
|
if key !in ['clear_before_set', 'overwrite_if_exists'] {
|
||||||
|
env_map[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.print_header('Setting multiple environment variables')
|
||||||
|
osal.env_set_all(
|
||||||
|
env: env_map
|
||||||
|
clear_before_set: clear_before_set
|
||||||
|
overwrite_if_exists: overwrite_if_exists
|
||||||
|
)
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.load_env_file actions
|
||||||
|
mut load_env_file_actions := plbook.find(filter: 'osal.load_env_file')!
|
||||||
|
for mut action in load_env_file_actions {
|
||||||
|
mut p := action.params
|
||||||
|
file_path := p.get('file_path')!
|
||||||
|
|
||||||
|
console.print_header('Loading environment from file: ${file_path}')
|
||||||
|
osal.load_env_file(file_path)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_exec(mut plbook PlayBook) ! {
|
||||||
|
// Handle !!osal.exec actions
|
||||||
|
mut exec_actions := plbook.find(filter: 'osal.exec')!
|
||||||
|
for mut action in exec_actions {
|
||||||
|
mut p := action.params
|
||||||
|
cmd := p.get('cmd')!
|
||||||
|
|
||||||
|
console.print_header('Executing command: ${cmd}')
|
||||||
|
|
||||||
|
mut job := osal.exec(
|
||||||
|
name: p.get_default('name', '')!
|
||||||
|
cmd: cmd
|
||||||
|
description: p.get_default('description', '')!
|
||||||
|
timeout: p.get_int_default('timeout', 3600)!
|
||||||
|
stdout: p.get_default_true('stdout')
|
||||||
|
stdout_log: p.get_default_true('stdout_log')
|
||||||
|
raise_error: p.get_default_true('raise_error')
|
||||||
|
ignore_error: p.get_default_false('ignore_error')
|
||||||
|
work_folder: p.get_default('work_folder', '')!
|
||||||
|
scriptkeep: p.get_default_false('scriptkeep')
|
||||||
|
debug: p.get_default_false('debug')
|
||||||
|
shell: p.get_default_false('shell')
|
||||||
|
retry: p.get_int_default('retry', 0)!
|
||||||
|
interactive: p.get_default_true('interactive')
|
||||||
|
async: p.get_default_false('async')
|
||||||
|
)!
|
||||||
|
|
||||||
|
// Store job output in done if specified
|
||||||
|
if output_key := p.get_default('output_key', '') {
|
||||||
|
if output_key != '' {
|
||||||
|
osal.done_set(output_key, job.output)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.exec_silent actions
|
||||||
|
mut exec_silent_actions := plbook.find(filter: 'osal.exec_silent')!
|
||||||
|
for mut action in exec_silent_actions {
|
||||||
|
mut p := action.params
|
||||||
|
cmd := p.get('cmd')!
|
||||||
|
|
||||||
|
console.print_header('Executing command silently: ${cmd}')
|
||||||
|
output := osal.execute_silent(cmd)!
|
||||||
|
|
||||||
|
// Store output in done if specified
|
||||||
|
if output_key := p.get_default('output_key', '') {
|
||||||
|
if output_key != '' {
|
||||||
|
osal.done_set(output_key, output)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.exec_debug actions
|
||||||
|
mut exec_debug_actions := plbook.find(filter: 'osal.exec_debug')!
|
||||||
|
for mut action in exec_debug_actions {
|
||||||
|
mut p := action.params
|
||||||
|
cmd := p.get('cmd')!
|
||||||
|
|
||||||
|
console.print_header('Executing command with debug: ${cmd}')
|
||||||
|
output := osal.execute_debug(cmd)!
|
||||||
|
|
||||||
|
// Store output in done if specified
|
||||||
|
if output_key := p.get_default('output_key', '') {
|
||||||
|
if output_key != '' {
|
||||||
|
osal.done_set(output_key, output)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.exec_stdout actions
|
||||||
|
mut exec_stdout_actions := plbook.find(filter: 'osal.exec_stdout')!
|
||||||
|
for mut action in exec_stdout_actions {
|
||||||
|
mut p := action.params
|
||||||
|
cmd := p.get('cmd')!
|
||||||
|
|
||||||
|
console.print_header('Executing command to stdout: ${cmd}')
|
||||||
|
output := osal.execute_stdout(cmd)!
|
||||||
|
|
||||||
|
// Store output in done if specified
|
||||||
|
if output_key := p.get_default('output_key', '') {
|
||||||
|
if output_key != '' {
|
||||||
|
osal.done_set(output_key, output)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.exec_interactive actions
|
||||||
|
mut exec_interactive_actions := plbook.find(filter: 'osal.exec_interactive')!
|
||||||
|
for mut action in exec_interactive_actions {
|
||||||
|
mut p := action.params
|
||||||
|
cmd := p.get('cmd')!
|
||||||
|
|
||||||
|
console.print_header('Executing command interactively: ${cmd}')
|
||||||
|
osal.execute_interactive(cmd)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_package(mut plbook PlayBook) ! {
|
||||||
|
// Handle !!osal.package_refresh actions
|
||||||
|
mut package_refresh_actions := plbook.find(filter: 'osal.package_refresh')!
|
||||||
|
for mut action in package_refresh_actions {
|
||||||
|
console.print_header('Refreshing package lists')
|
||||||
|
osal.package_refresh()!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.package_install actions
|
||||||
|
mut package_install_actions := plbook.find(filter: 'osal.package_install')!
|
||||||
|
for mut action in package_install_actions {
|
||||||
|
mut p := action.params
|
||||||
|
|
||||||
|
// Get package name(s) - can be a single package or comma-separated list
|
||||||
|
mut packages := []string{}
|
||||||
|
if p.exists('name') {
|
||||||
|
packages << p.get('name')!
|
||||||
|
}
|
||||||
|
if p.exists('names') {
|
||||||
|
packages = p.get_list('names')!
|
||||||
|
}
|
||||||
|
// Also check for positional arguments
|
||||||
|
for i in 0 .. 10 {
|
||||||
|
if arg := p.get_arg_default(i, '') {
|
||||||
|
if arg != '' {
|
||||||
|
packages << arg
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if packages.len == 0 {
|
||||||
|
return error('No packages specified for installation')
|
||||||
|
}
|
||||||
|
|
||||||
|
package_name := packages.join(' ')
|
||||||
|
console.print_header('Installing packages: ${package_name}')
|
||||||
|
osal.package_install(package_name)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle !!osal.package_remove actions
|
||||||
|
mut package_remove_actions := plbook.find(filter: 'osal.package_remove')!
|
||||||
|
for mut action in package_remove_actions {
|
||||||
|
mut p := action.params
|
||||||
|
|
||||||
|
// Get package name(s) - can be a single package or comma-separated list
|
||||||
|
mut packages := []string{}
|
||||||
|
if p.exists('name') {
|
||||||
|
packages << p.get('name')!
|
||||||
|
}
|
||||||
|
if p.exists('names') {
|
||||||
|
packages = p.get_list('names')!
|
||||||
|
}
|
||||||
|
// Also check for positional arguments
|
||||||
|
for i in 0 .. 10 {
|
||||||
|
if arg := p.get_arg_default(i, '') {
|
||||||
|
if arg != '' {
|
||||||
|
packages << arg
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if packages.len == 0 {
|
||||||
|
return error('No packages specified for removal')
|
||||||
|
}
|
||||||
|
|
||||||
|
package_name := packages.join(' ')
|
||||||
|
console.print_header('Removing packages: ${package_name}')
|
||||||
|
osal.package_remove(package_name)!
|
||||||
|
action.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
153
lib/virt/buildah/buildah_core.v
Normal file
153
lib/virt/buildah/buildah_core.v
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
// import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.installers.lang.herolib
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
import freeflowuniverse.herolib.builder
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
// is builderah containers
|
||||||
|
|
||||||
|
pub enum ContainerStatus {
|
||||||
|
up
|
||||||
|
down
|
||||||
|
restarting
|
||||||
|
paused
|
||||||
|
dead
|
||||||
|
created
|
||||||
|
}
|
||||||
|
pub struct IPAddress {
|
||||||
|
pub mut:
|
||||||
|
ipv4 string
|
||||||
|
ipv6 string
|
||||||
|
}
|
||||||
|
// need to fill in what is relevant
|
||||||
|
@[heap]
|
||||||
|
pub struct BuildahContainer {
|
||||||
|
pub mut:
|
||||||
|
id string
|
||||||
|
builder bool
|
||||||
|
imageid string
|
||||||
|
imagename string
|
||||||
|
containername string
|
||||||
|
//TODO: not sure all below is needed
|
||||||
|
hero_in_container bool //once the hero has been installed this is on, does it once per session
|
||||||
|
created time.Time
|
||||||
|
ssh_enabled bool // if yes make sure ssh is enabled to the container
|
||||||
|
ipaddr IPAddress
|
||||||
|
forwarded_ports []string
|
||||||
|
mounts []ContainerVolume
|
||||||
|
ssh_port int // ssh port on node that is used to get ssh
|
||||||
|
ports []string
|
||||||
|
networks []string
|
||||||
|
labels map[string]string @[str: skip]
|
||||||
|
image &Image @[str: skip]
|
||||||
|
engine &CEngine @[str: skip]
|
||||||
|
status ContainerStatus
|
||||||
|
memsize int // in MB
|
||||||
|
command string
|
||||||
|
factory &BuildAHFactory
|
||||||
|
node_host &builder.Node
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct RunArgs {
|
||||||
|
pub mut:
|
||||||
|
cmd string
|
||||||
|
// TODO:/..
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct PackageInstallArgs {
|
||||||
|
pub mut:
|
||||||
|
names string
|
||||||
|
// TODO:/..
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: mimic osal.package_install('mc,tmux,git,rsync,curl,screen,redis,wget,git-lfs')!
|
||||||
|
|
||||||
|
// pub fn (mut self BuildahContainer) package_install(args PackageInstallArgs) !{
|
||||||
|
// //TODO
|
||||||
|
// names := texttools.to_array(args.names)
|
||||||
|
// //now check which OS, need to make platform function on container level so we know which platform it is
|
||||||
|
// panic("implement")
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) copy(src string, dest string) ! {
|
||||||
|
cmd := 'buildah copy ${self.id} ${src} ${dest}'
|
||||||
|
self.exec(cmd: cmd, stdout: false)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) shell() ! {
|
||||||
|
cmd := 'buildah run --terminal --env TERM=xterm ${self.id} /bin/bash'
|
||||||
|
self.node_host.execute_interactive(cmd)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) clean() ! {
|
||||||
|
cmd := '
|
||||||
|
#set -x
|
||||||
|
set +e
|
||||||
|
rm -rf /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/share/doc
|
||||||
|
#pacman -Rns $(pacman -Qtdq) --noconfirm
|
||||||
|
#pacman -Scc --noconfirm
|
||||||
|
rm -rf /var/lib/pacman/sync/*
|
||||||
|
rm -rf /tmp/*
|
||||||
|
rm -rf /var/tmp/*
|
||||||
|
find /var/log -type f -name "*.log" -exec truncate -s 0 {} \\;
|
||||||
|
rm -rf /home/*/.cache/*
|
||||||
|
rm -rf /usr/share/doc/*
|
||||||
|
rm -rf /usr/share/man/*
|
||||||
|
rm -rf /usr/share/info/*
|
||||||
|
rm -rf /usr/share/licenses/*
|
||||||
|
find /usr/share/locale -mindepth 1 -maxdepth 1 ! -name "en*" -exec rm -rf {} \\;
|
||||||
|
rm -rf /usr/share/i18n
|
||||||
|
rm -rf /usr/share/icons/*
|
||||||
|
rm -rf /usr/lib/modules/*
|
||||||
|
rm -rf /var/cache/pacman
|
||||||
|
journalctl --vacuum-time=1s
|
||||||
|
|
||||||
|
'
|
||||||
|
self.exec(cmd: cmd, stdout: false)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) delete() ! {
|
||||||
|
self.engine.builder_delete(self.containername)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) inspect() !BuilderInfo {
|
||||||
|
cmd := 'buildah inspect ${self.containername}'
|
||||||
|
out := self.host_exec(cmd:(cmd)!
|
||||||
|
mut r := json.decode(BuilderInfo, out) or {
|
||||||
|
return error('Failed to decode JSON for inspect: ${err}')
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// mount the build container to a path and return the path where its mounted
|
||||||
|
pub fn (mut self BuildahContainer) mount_to_path() !string {
|
||||||
|
cmd := 'buildah mount ${self.containername}'
|
||||||
|
out := self.exec(cmd:cmd)!
|
||||||
|
return out.trim_space()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) commit(image_name string) ! {
|
||||||
|
cmd := 'buildah commit ${self.containername} ${image_name}'
|
||||||
|
self.exec(cmd: cmd)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (self BuildahContainer) set_entrypoint(entrypoint string) ! {
|
||||||
|
cmd := 'buildah config --entrypoint \'${entrypoint}\' ${self.containername}'
|
||||||
|
self.exec(cmd: cmd)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (self BuildahContainer) set_workingdir(workdir string) ! {
|
||||||
|
cmd := 'buildah config --workingdir ${workdir} ${self.containername}'
|
||||||
|
self.exec(cmd: cmd)!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (self BuildahContainer) set_cmd(command string) ! {
|
||||||
|
cmd := 'buildah config --cmd ${command} ${self.containername}'
|
||||||
|
self.exec(cmd: cmd)!
|
||||||
|
}
|
||||||
33
lib/virt/buildah/buildah_core_installers.v
Normal file
33
lib/virt/buildah/buildah_core_installers.v
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
// import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.installers.lang.herolib
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) install_zinit() ! {
|
||||||
|
// https://github.com/threefoldtech/zinit
|
||||||
|
self.hero_copy()!
|
||||||
|
self.hero_play_execute('!!installer.zinit')
|
||||||
|
// TODO: implement by making sure hero is in the build context and then use hero cmd to install this
|
||||||
|
self.set_entrypoint('/sbin/zinit init --container')!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) install_herodb() ! {
|
||||||
|
self.install_zinit()!
|
||||||
|
// the hero database gets installed and put in zinit for automatic start
|
||||||
|
self.hero_play_execute('!!installer.herodb')
|
||||||
|
//TODO: the hero_play needs to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// copies the hero from host into guest
|
||||||
|
pub fn (mut self BuildahContainer) install_mycelium() ! {
|
||||||
|
self.install_zinit()!
|
||||||
|
// the mycelium database gets installed and put in zinit for automatic start
|
||||||
|
self.hero_play_execute('!!installer.mycelium')
|
||||||
|
//TODO: the hero_play needs to be implemented
|
||||||
|
}
|
||||||
91
lib/virt/buildah/buildah_exec.v
Normal file
91
lib/virt/buildah/buildah_exec.v
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
// import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.installers.lang.herolib
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct Command {
|
||||||
|
pub mut:
|
||||||
|
name string // to give a name to your command, good to see logs...
|
||||||
|
cmd string
|
||||||
|
description string
|
||||||
|
timeout int = 3600 // timeout in sec
|
||||||
|
stdout bool = true
|
||||||
|
stdout_log bool = true
|
||||||
|
raise_error bool = true // if false, will not raise an error but still error report
|
||||||
|
ignore_error bool // means if error will just exit and not raise, there will be no error reporting
|
||||||
|
work_folder string // location where cmd will be executed
|
||||||
|
environment map[string]string // env variables
|
||||||
|
ignore_error_codes []int
|
||||||
|
scriptpath string // is the path where the script will be put which is executed
|
||||||
|
scriptkeep bool // means we don't remove the script
|
||||||
|
debug bool // if debug will put +ex in the script which is being executed and will make sure script stays
|
||||||
|
shell bool // means we will execute it in a shell interactive
|
||||||
|
retry int
|
||||||
|
interactive bool = true
|
||||||
|
async bool
|
||||||
|
runtime osal.RunTime
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RunTime {
|
||||||
|
bash
|
||||||
|
python
|
||||||
|
heroscript
|
||||||
|
herocmd
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
|
//should use builders underneith
|
||||||
|
pub fn (mut self BuildahContainer) exec(cmd Command) ! {
|
||||||
|
|
||||||
|
//make sure we have hero in the hostnode of self
|
||||||
|
self.hero_copy()!
|
||||||
|
|
||||||
|
mut rt := RunTime.bash
|
||||||
|
|
||||||
|
scriptpath := osal.cmd_to_script_path(cmd: cmd.cmd, runtime: cmd.runtime)!
|
||||||
|
|
||||||
|
if cmd.runtime == .heroscript || cmd.runtime == .herocmd {
|
||||||
|
self.hero_copy()!
|
||||||
|
}
|
||||||
|
|
||||||
|
script_basename := os.base(scriptpath)
|
||||||
|
script_path_in_container := '/tmp/${script_basename}'
|
||||||
|
|
||||||
|
self.copy(scriptpath, script_path_in_container)!
|
||||||
|
// console.print_debug("copy ${scriptpath} into container '${self.containername}'")
|
||||||
|
cmd_str := 'buildah run ${self.id} ${script_path_in_container}'
|
||||||
|
// console.print_debug(cmd_str)
|
||||||
|
|
||||||
|
if cmd.runtime == .heroscript || cmd.runtime == .herocmd {
|
||||||
|
self.hero_copy()!
|
||||||
|
}
|
||||||
|
mut node:=self.node()!
|
||||||
|
//TODO: need to check, the node exec needs to be as much as possible same as osal.exec
|
||||||
|
node.exec(
|
||||||
|
name: cmd.name
|
||||||
|
cmd: cmd_str
|
||||||
|
description: cmd.description
|
||||||
|
timeout: cmd.timeout
|
||||||
|
stdout: cmd.stdout
|
||||||
|
stdout_log: cmd.stdout_log
|
||||||
|
raise_error: cmd.raise_error
|
||||||
|
ignore_error: cmd.ignore_error
|
||||||
|
ignore_error_codes: cmd.ignore_error_codes
|
||||||
|
scriptpath: cmd.scriptpath
|
||||||
|
scriptkeep: cmd.scriptkeep
|
||||||
|
debug: cmd.debug
|
||||||
|
shell: cmd.shell
|
||||||
|
retry: cmd.retry
|
||||||
|
interactive: cmd.interactive
|
||||||
|
async: cmd.async
|
||||||
|
) or {
|
||||||
|
mut epath := pathlib.get_file(path: scriptpath, create: false)!
|
||||||
|
c := epath.read()!
|
||||||
|
return error('cannot execute:\n${c}\nerror:\n${err}')
|
||||||
|
}
|
||||||
|
}
|
||||||
118
lib/virt/buildah/buildah_factory.v
Normal file
118
lib/virt/buildah/buildah_factory.v
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.installers.virt.podman as podman_installer
|
||||||
|
import freeflowuniverse.herolib.installers.lang.herolib
|
||||||
|
import freeflowuniverse.herolib.core
|
||||||
|
import freeflowuniverse.herolib.builder
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct BuildAHNewArgs {
|
||||||
|
pub mut:
|
||||||
|
herocompile bool
|
||||||
|
reset bool
|
||||||
|
default_image string = 'docker.io/ubuntu:latest'
|
||||||
|
install bool = true //make sure buildah is installed
|
||||||
|
node string //normally empty then localhost, also support root@server.example.com:22
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOD: this to allow crossplatform builds
|
||||||
|
pub enum BuildPlatformType {
|
||||||
|
linux_arm64
|
||||||
|
linux_amd64
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct BuildAHFactory {
|
||||||
|
pub mut:
|
||||||
|
host_node &builder.Node
|
||||||
|
default_image string
|
||||||
|
platform BuildPlatformType
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn new(args BuildAHNewArgs)!BuildAHFactory {
|
||||||
|
|
||||||
|
mut b:= builder:builder.new()!
|
||||||
|
|
||||||
|
mut n := self.builder.node_local()!
|
||||||
|
|
||||||
|
if self.node !=""{
|
||||||
|
// Create a node for remote execution, need to see if this is cached on builder, otherwise will be too slow
|
||||||
|
n = b.node_new(ipaddr: args.node)!
|
||||||
|
}
|
||||||
|
|
||||||
|
mut bahf := BuildAHFactory{
|
||||||
|
host_node: n
|
||||||
|
default_image: args.default_image
|
||||||
|
}
|
||||||
|
if args.reset {
|
||||||
|
//TODO
|
||||||
|
panic("implement")
|
||||||
|
}
|
||||||
|
// if args.herocompile {
|
||||||
|
// bahf.builder = builder.hero_compile()!
|
||||||
|
// }
|
||||||
|
return bahf
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct BuildAhContainerNewArgs {
|
||||||
|
pub mut:
|
||||||
|
name string = 'default'
|
||||||
|
from string
|
||||||
|
delete bool = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: implement, missing parts
|
||||||
|
//TODO: need to supprot a docker builder if we are on osx or windows, so we use the builders functionality as base for executing, not directly osal
|
||||||
|
pub fn (mut self BuildAHFactory) new(args_ BuilderNewArgs) !BuildahContainer {
|
||||||
|
mut args := args_
|
||||||
|
if args.delete {
|
||||||
|
self.delete(args.name)!
|
||||||
|
}
|
||||||
|
if args.from != "" {
|
||||||
|
args.from = self.default_image
|
||||||
|
}
|
||||||
|
mut c := BuildahContainer{
|
||||||
|
name: args.name
|
||||||
|
from: args.from
|
||||||
|
factory: &self
|
||||||
|
node_host: self.host_node
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn (mut self BuildAHFactory) list() ![]string {
|
||||||
|
panic(implement)
|
||||||
|
cmd := 'buildah containers --json'
|
||||||
|
out := self.host_exec(cmd:cmd)!
|
||||||
|
mut r := json.decode([]BuildahContainer, out) or { return error('Failed to decode JSON: ${err}') }
|
||||||
|
for mut item in r {
|
||||||
|
item.engine = &e
|
||||||
|
}
|
||||||
|
e.builders = r
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete all builders
|
||||||
|
pub fn (mut self BuildAHFactory) reset() ! {
|
||||||
|
console.print_debug('remove all')
|
||||||
|
osal.execute_stdout('buildah rm -a')!
|
||||||
|
self.builders_load()!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut self BuildAHFactory) delete(name string) ! {
|
||||||
|
if self.exists(name)! {
|
||||||
|
console.print_debug('remove ${name}')
|
||||||
|
osal.execute_stdout('buildah rm ${name}')!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
42
lib/virt/buildah/buildah_hero.v
Normal file
42
lib/virt/buildah/buildah_hero.v
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
// copies the hero from host into guest and then execute the heroscript or commandline
|
||||||
|
pub fn (mut self BuildahContainer) hero_cmd_execute(cmd string) ! {
|
||||||
|
self.hero_copy()!
|
||||||
|
self.exec(cmd: cmd, runtime: .herocmd)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// send a hero play command to the buildah container
|
||||||
|
pub fn (mut self BuildahContainer) hero_play_execute(cmd string) ! {
|
||||||
|
self.hero_copy()!
|
||||||
|
panic("implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn (mut self BuildahContainer) hero_execute_script(cmd string) ! {
|
||||||
|
self.hero_copy()!
|
||||||
|
self.exec(cmd: cmd, runtime: .heroscript)!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// copies the hero from host into guest
|
||||||
|
pub fn (mut self BuildahContainer) hero_copy() ! {
|
||||||
|
|
||||||
|
//TODO: check we are on linux, check also the platformtype arm or intel, if not right platform then build hero in container
|
||||||
|
|
||||||
|
panic("implement")
|
||||||
|
|
||||||
|
if !osal.cmd_exists('hero') {
|
||||||
|
herolib.hero_compile()!
|
||||||
|
}
|
||||||
|
heropath := osal.cmd_path('hero')!
|
||||||
|
self.copy(heropath, '/usr/local/bin/hero')!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get a container where we build hero and export hero from the container so we can use it for hero_copy
|
||||||
|
pub fn (mut self BuildahContainer) hero_build() ! {
|
||||||
|
panic("implement")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module herocontainers
|
module buildah
|
||||||
|
|
||||||
struct BuilderInfo {
|
struct BuilderInfo {
|
||||||
type_ string @[json: 'Type']
|
type_ string @[json: 'Type']
|
||||||
179
lib/virt/buildah/buildah_solutions.v
Normal file
179
lib/virt/buildah/buildah_solutions.v
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
module buildah
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.osal.core as osal
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import os
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct GetArgs {
|
||||||
|
pub mut:
|
||||||
|
reset bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// builder machine based on arch and install vlang
|
||||||
|
// TODO need to change, go to ubuntu
|
||||||
|
pub fn builder_base(args GetArgs) !BuildahContainer {
|
||||||
|
name := 'base'
|
||||||
|
if !args.reset && e.builder_exists(name)! {
|
||||||
|
return e.builder_get(name)!
|
||||||
|
}
|
||||||
|
console.print_header('buildah base build')
|
||||||
|
|
||||||
|
mut builder := e.builder_new(name: name, from: 'scratch', delete: true)!
|
||||||
|
mount_path := builder.mount_to_path()!
|
||||||
|
if mount_path.len < 4 {
|
||||||
|
return error('mount_path needs to be +4 chars')
|
||||||
|
}
|
||||||
|
self.exec(
|
||||||
|
cmd: '
|
||||||
|
|
||||||
|
export MOUNT_PATH=\'${mount_path}\'
|
||||||
|
|
||||||
|
mmdebstrap --variant=minbase --components="main,universe" --include="apt,base-files,base-passwd,bash,coreutils" noble \${MOUNT_PATH}
|
||||||
|
|
||||||
|
echo "Binding essential directories..."
|
||||||
|
mount --bind /dev "\${MOUNT_PATH}/dev"
|
||||||
|
mount --bind /proc "\${MOUNT_PATH}/proc"
|
||||||
|
mount --bind /sys "\${MOUNT_PATH}/sys"
|
||||||
|
|
||||||
|
echo "tzdata tzdata/Areas select Europe" | chroot "\${MOUNT_PATH}" debconf-set-selections
|
||||||
|
echo "tzdata tzdata/Zones/Europe select Brussels" | chroot "\${MOUNT_PATH}" debconf-set-selections
|
||||||
|
|
||||||
|
chroot \${MOUNT_PATH} apt update
|
||||||
|
|
||||||
|
# Set up APT for non-interactive installation
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export DEBCONF_NONINTERACTIVE_SEEN=true
|
||||||
|
|
||||||
|
# Update package lists
|
||||||
|
echo "Updating package lists in chroot..."
|
||||||
|
chroot \${MOUNT_PATH} apt-get update -yq
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
echo "Installing essential packages..."
|
||||||
|
chroot \${MOUNT_PATH} apt-get install -yq screen bash coreutils curl mc unzip sudo which openssh-client openssh-server redis wget
|
||||||
|
|
||||||
|
echo "Cleaning up..."
|
||||||
|
umount "\${MOUNT_PATH}/dev" || true
|
||||||
|
umount "\${MOUNT_PATH}/proc" || true
|
||||||
|
umount "\${MOUNT_PATH}/sys" || true
|
||||||
|
|
||||||
|
'
|
||||||
|
)!
|
||||||
|
builder.install_zinit()!
|
||||||
|
// builder.set_entrypoint('redis-server')!
|
||||||
|
builder.commit('localhost/${name}')!
|
||||||
|
return builder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: all below are not good, need to use play cmd over hero remotely. see how we did it with core_installers
|
||||||
|
|
||||||
|
// // builder machine based on arch and install vlang
|
||||||
|
// pub fn (mut e CEngine) builder_go_rust(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder go rust')
|
||||||
|
// name := 'builder_go_rust'
|
||||||
|
// e.builder_base(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder := e.builder_new(name: name, from: 'localhost/base', delete: true)!
|
||||||
|
// builder.hero_execute_cmd('installers -n golang,rust')!
|
||||||
|
// // builder.clean()!
|
||||||
|
// builder.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn (mut e CEngine) builder_js(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder js')
|
||||||
|
// name := 'builder_js'
|
||||||
|
// e.builder_base(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder := e.builder_new(name: name, from: 'localhost/base', delete: true)!
|
||||||
|
// builder.hero_execute_cmd('installers -n nodejs')!
|
||||||
|
// // builder.clean()!
|
||||||
|
// builder.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn (mut e CEngine) builder_js_python(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder js python')
|
||||||
|
// name := 'builder_js_python'
|
||||||
|
// e.builder_js(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder := e.builder_new(name: name, from: 'localhost/builder_js', delete: true)!
|
||||||
|
// builder.hero_execute_cmd('installers -n python')!
|
||||||
|
// // builder.clean()!
|
||||||
|
// builder.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn (mut e CEngine) builder_hero(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder hero dev')
|
||||||
|
// name := 'builder_hero'
|
||||||
|
// e.builder_js_python(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder := e.builder_new(name: name, from: 'localhost/builder_js_python', delete: true)!
|
||||||
|
// builder.hero_execute_cmd('installers -n hero')!
|
||||||
|
// // builder.clean()!
|
||||||
|
// builder.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn (mut e CEngine) builder_herodev(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder hero dev')
|
||||||
|
// name := 'builder_herodev'
|
||||||
|
// e.builder_js_python(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder := e.builder_new(name: name, from: 'localhost/builder_hero', delete: true)!
|
||||||
|
// builder.hero_execute_cmd('installers -n herodev')!
|
||||||
|
// // builder.clean()!
|
||||||
|
// builder.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn (mut e CEngine) builder_heroweb(args GetArgs) !BuildahContainer {
|
||||||
|
// console.print_header('buildah builder hero web')
|
||||||
|
// name := 'builder_heroweb'
|
||||||
|
// e.builder_go_rust(reset: false)!
|
||||||
|
// e.builder_hero(reset: false)!
|
||||||
|
// if !args.reset && e.builder_exists(name)! {
|
||||||
|
// return e.builder_get(name)!
|
||||||
|
// }
|
||||||
|
// mut builder0 := e.builder_new(
|
||||||
|
// name: 'builder_heroweb_temp'
|
||||||
|
// from: 'localhost/builder_go_rust'
|
||||||
|
// delete: true
|
||||||
|
// )!
|
||||||
|
// builder0.hero_execute_cmd('installers -n heroweb')!
|
||||||
|
// // builder0.hero_execute_cmd("installers -n heroweb")!
|
||||||
|
// mpath := builder0.mount_to_path()!
|
||||||
|
|
||||||
|
// // copy the built binary to host
|
||||||
|
// self.exec(
|
||||||
|
// cmd: '
|
||||||
|
// mkdir -p ${os.home_dir()}/hero/var/bin
|
||||||
|
// cp ${mpath}/usr/local/bin/* ${os.home_dir()}/hero/var/bin/
|
||||||
|
// '
|
||||||
|
// )!
|
||||||
|
|
||||||
|
// builder0.delete()!
|
||||||
|
// mut builder2 := e.builder_new(name: name, from: 'localhost/builder_hero', delete: true)!
|
||||||
|
// builder2.copy('${os.home_dir()}/hero/var/bin/', '/usr/local/bin/')!
|
||||||
|
// builder2.commit('localhost/${name}')!
|
||||||
|
// e.load()!
|
||||||
|
// return builder2
|
||||||
|
// }
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
module herocontainers
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.osal.core as osal
|
|
||||||
// import freeflowuniverse.herolib.ui.console
|
|
||||||
import freeflowuniverse.herolib.installers.lang.herolib
|
|
||||||
import freeflowuniverse.herolib.core.pathlib
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
// is builderah containers
|
|
||||||
|
|
||||||
// pub enum ContainerStatus {
|
|
||||||
// up
|
|
||||||
// down
|
|
||||||
// restarting
|
|
||||||
// paused
|
|
||||||
// dead
|
|
||||||
// created
|
|
||||||
// }
|
|
||||||
|
|
||||||
// need to fill in what is relevant
|
|
||||||
@[heap]
|
|
||||||
pub struct Builder {
|
|
||||||
pub mut:
|
|
||||||
id string
|
|
||||||
builder bool
|
|
||||||
imageid string
|
|
||||||
imagename string
|
|
||||||
containername string
|
|
||||||
engine &CEngine @[skip; str: skip]
|
|
||||||
// hero_in_container bool //once the hero has been installed this is on, does it once per session
|
|
||||||
// created time.Time
|
|
||||||
// ssh_enabled bool // if yes make sure ssh is enabled to the container
|
|
||||||
// ipaddr IPAddress
|
|
||||||
// forwarded_ports []string
|
|
||||||
// mounts []ContainerVolume
|
|
||||||
// ssh_port int // ssh port on node that is used to get ssh
|
|
||||||
// ports []string
|
|
||||||
// networks []string
|
|
||||||
// labels map[string]string @[str: skip]
|
|
||||||
// image &Image @[str: skip]
|
|
||||||
// engine &CEngine @[str: skip]
|
|
||||||
// status ContainerStatus
|
|
||||||
// memsize int // in MB
|
|
||||||
// command string
|
|
||||||
}
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct RunArgs {
|
|
||||||
pub mut:
|
|
||||||
cmd string
|
|
||||||
// TODO:/..
|
|
||||||
}
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct PackageInstallArgs {
|
|
||||||
pub mut:
|
|
||||||
names string
|
|
||||||
// TODO:/..
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: mimic osal.package_install('mc,tmux,git,rsync,curl,screen,redis,wget,git-lfs')!
|
|
||||||
|
|
||||||
// pub fn (mut self Builder) package_install(args PackageInstallArgs) !{
|
|
||||||
// //TODO
|
|
||||||
// names := texttools.to_array(args.names)
|
|
||||||
// //now check which OS, need to make platform function on container level so we know which platform it is
|
|
||||||
// panic("implement")
|
|
||||||
// }
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct Command {
|
|
||||||
pub mut:
|
|
||||||
name string // to give a name to your command, good to see logs...
|
|
||||||
cmd string
|
|
||||||
description string
|
|
||||||
timeout int = 3600 // timeout in sec
|
|
||||||
stdout bool = true
|
|
||||||
stdout_log bool = true
|
|
||||||
raise_error bool = true // if false, will not raise an error but still error report
|
|
||||||
ignore_error bool // means if error will just exit and not raise, there will be no error reporting
|
|
||||||
work_folder string // location where cmd will be executed
|
|
||||||
environment map[string]string // env variables
|
|
||||||
ignore_error_codes []int
|
|
||||||
scriptpath string // is the path where the script will be put which is executed
|
|
||||||
scriptkeep bool // means we don't remove the script
|
|
||||||
debug bool // if debug will put +ex in the script which is being executed and will make sure script stays
|
|
||||||
shell bool // means we will execute it in a shell interactive
|
|
||||||
retry int
|
|
||||||
interactive bool = true
|
|
||||||
async bool
|
|
||||||
runtime osal.RunTime
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum RunTime {
|
|
||||||
bash
|
|
||||||
python
|
|
||||||
heroscript
|
|
||||||
herocmd
|
|
||||||
v
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) run(cmd Command) ! {
|
|
||||||
mut rt := RunTime.bash
|
|
||||||
|
|
||||||
scriptpath := osal.cmd_to_script_path(cmd: cmd.cmd, runtime: cmd.runtime)!
|
|
||||||
|
|
||||||
if cmd.runtime == .heroscript || cmd.runtime == .herocmd {
|
|
||||||
self.hero_copy()!
|
|
||||||
}
|
|
||||||
|
|
||||||
script_basename := os.base(scriptpath)
|
|
||||||
script_path_in_container := '/tmp/${script_basename}'
|
|
||||||
|
|
||||||
self.copy(scriptpath, script_path_in_container)!
|
|
||||||
// console.print_debug("copy ${scriptpath} into container '${self.containername}'")
|
|
||||||
cmd_str := 'buildah run ${self.id} ${script_path_in_container}'
|
|
||||||
// console.print_debug(cmd_str)
|
|
||||||
|
|
||||||
if cmd.runtime == .heroscript || cmd.runtime == .herocmd {
|
|
||||||
self.hero_copy()!
|
|
||||||
}
|
|
||||||
osal.exec(
|
|
||||||
name: cmd.name
|
|
||||||
cmd: cmd_str
|
|
||||||
description: cmd.description
|
|
||||||
timeout: cmd.timeout
|
|
||||||
stdout: cmd.stdout
|
|
||||||
stdout_log: cmd.stdout_log
|
|
||||||
raise_error: cmd.raise_error
|
|
||||||
ignore_error: cmd.ignore_error
|
|
||||||
ignore_error_codes: cmd.ignore_error_codes
|
|
||||||
scriptpath: cmd.scriptpath
|
|
||||||
scriptkeep: cmd.scriptkeep
|
|
||||||
debug: cmd.debug
|
|
||||||
shell: cmd.shell
|
|
||||||
retry: cmd.retry
|
|
||||||
interactive: cmd.interactive
|
|
||||||
async: cmd.async
|
|
||||||
) or {
|
|
||||||
mut epath := pathlib.get_file(path: scriptpath, create: false)!
|
|
||||||
c := epath.read()!
|
|
||||||
return error('cannot execute:\n${c}\nerror:\n${err}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) copy(src string, dest string) ! {
|
|
||||||
cmd := 'buildah copy ${self.id} ${src} ${dest}'
|
|
||||||
osal.exec(cmd: cmd, stdout: false)!
|
|
||||||
}
|
|
||||||
|
|
||||||
// copies the hero from host into guest
|
|
||||||
pub fn (mut self Builder) hero_copy() ! {
|
|
||||||
if !osal.cmd_exists('hero') {
|
|
||||||
herolib.hero_compile()!
|
|
||||||
}
|
|
||||||
heropath := osal.cmd_path('hero')!
|
|
||||||
self.copy(heropath, '/usr/local/bin/hero')!
|
|
||||||
}
|
|
||||||
|
|
||||||
// copies the hero from host into guest and then execute the heroscript or commandline
|
|
||||||
pub fn (mut self Builder) hero_execute_cmd(cmd string) ! {
|
|
||||||
self.hero_copy()!
|
|
||||||
self.run(cmd: cmd, runtime: .herocmd)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) hero_execute_script(cmd string) ! {
|
|
||||||
self.hero_copy()!
|
|
||||||
self.run(cmd: cmd, runtime: .heroscript)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) shell() ! {
|
|
||||||
cmd := 'buildah run --terminal --env TERM=xterm ${self.id} /bin/bash'
|
|
||||||
osal.execute_interactive(cmd)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) clean() ! {
|
|
||||||
cmd := '
|
|
||||||
#set -x
|
|
||||||
set +e
|
|
||||||
rm -rf /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/share/doc
|
|
||||||
#pacman -Rns $(pacman -Qtdq) --noconfirm
|
|
||||||
#pacman -Scc --noconfirm
|
|
||||||
rm -rf /var/lib/pacman/sync/*
|
|
||||||
rm -rf /tmp/*
|
|
||||||
rm -rf /var/tmp/*
|
|
||||||
find /var/log -type f -name "*.log" -exec truncate -s 0 {} \\;
|
|
||||||
rm -rf /home/*/.cache/*
|
|
||||||
rm -rf /usr/share/doc/*
|
|
||||||
rm -rf /usr/share/man/*
|
|
||||||
rm -rf /usr/share/info/*
|
|
||||||
rm -rf /usr/share/licenses/*
|
|
||||||
find /usr/share/locale -mindepth 1 -maxdepth 1 ! -name "en*" -exec rm -rf {} \\;
|
|
||||||
rm -rf /usr/share/i18n
|
|
||||||
rm -rf /usr/share/icons/*
|
|
||||||
rm -rf /usr/lib/modules/*
|
|
||||||
rm -rf /var/cache/pacman
|
|
||||||
journalctl --vacuum-time=1s
|
|
||||||
|
|
||||||
'
|
|
||||||
self.run(cmd: cmd, stdout: false)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) delete() ! {
|
|
||||||
self.engine.builder_delete(self.containername)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) inspect() !BuilderInfo {
|
|
||||||
cmd := 'buildah inspect ${self.containername}'
|
|
||||||
out := osal.execute_silent(cmd)!
|
|
||||||
mut r := json.decode(BuilderInfo, out) or {
|
|
||||||
return error('Failed to decode JSON for inspect: ${err}')
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// mount the build container to a path and return the path where its mounted
|
|
||||||
pub fn (mut self Builder) mount_to_path() !string {
|
|
||||||
cmd := 'buildah mount ${self.containername}'
|
|
||||||
out := osal.execute_silent(cmd)!
|
|
||||||
return out.trim_space()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut self Builder) commit(image_name string) ! {
|
|
||||||
cmd := 'buildah commit ${self.containername} ${image_name}'
|
|
||||||
osal.exec(cmd: cmd)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (self Builder) set_entrypoint(entrypoint string) ! {
|
|
||||||
cmd := 'buildah config --entrypoint \'${entrypoint}\' ${self.containername}'
|
|
||||||
osal.exec(cmd: cmd)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (self Builder) set_workingdir(workdir string) ! {
|
|
||||||
cmd := 'buildah config --workingdir ${workdir} ${self.containername}'
|
|
||||||
osal.exec(cmd: cmd)!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (self Builder) set_cmd(command string) ! {
|
|
||||||
cmd := 'buildah config --cmd ${command} ${self.containername}'
|
|
||||||
osal.exec(cmd: cmd)!
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
module herocontainers
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.osal.core as osal
|
|
||||||
// import freeflowuniverse.herolib.ui.console
|
|
||||||
import freeflowuniverse.herolib.installers.lang.herolib
|
|
||||||
import freeflowuniverse.herolib.core.pathlib
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
// copies the hero from host into guest
|
|
||||||
pub fn (mut self Builder) install_zinit() ! {
|
|
||||||
self.run(
|
|
||||||
cmd: '
|
|
||||||
wget https://github.com/threefoldtech/zinit/releases/download/v0.2.5/zinit -O /sbin/zinit
|
|
||||||
chmod +x /sbin/zinit
|
|
||||||
touch /etc/environment
|
|
||||||
mkdir -p /etc/zinit/
|
|
||||||
'
|
|
||||||
)!
|
|
||||||
|
|
||||||
self.set_entrypoint('/sbin/zinit init --container')!
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
module herocontainers
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.osal.core as osal
|
|
||||||
import freeflowuniverse.herolib.ui.console
|
|
||||||
import os
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct GetArgs {
|
|
||||||
pub mut:
|
|
||||||
reset bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// builder machine based on arch and install vlang
|
|
||||||
pub fn (mut e CEngine) builder_base(args GetArgs) !Builder {
|
|
||||||
name := 'base'
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
console.print_header('buildah base build')
|
|
||||||
|
|
||||||
mut builder := e.builder_new(name: name, from: 'scratch', delete: true)!
|
|
||||||
mount_path := builder.mount_to_path()!
|
|
||||||
if mount_path.len < 4 {
|
|
||||||
return error('mount_path needs to be +4 chars')
|
|
||||||
}
|
|
||||||
osal.exec(
|
|
||||||
cmd: '
|
|
||||||
|
|
||||||
export MOUNT_PATH=\'${mount_path}\'
|
|
||||||
|
|
||||||
mmdebstrap --variant=minbase --components="main,universe" --include="apt,base-files,base-passwd,bash,coreutils" noble \${MOUNT_PATH}
|
|
||||||
|
|
||||||
echo "Binding essential directories..."
|
|
||||||
mount --bind /dev "\${MOUNT_PATH}/dev"
|
|
||||||
mount --bind /proc "\${MOUNT_PATH}/proc"
|
|
||||||
mount --bind /sys "\${MOUNT_PATH}/sys"
|
|
||||||
|
|
||||||
echo "tzdata tzdata/Areas select Europe" | chroot "\${MOUNT_PATH}" debconf-set-selections
|
|
||||||
echo "tzdata tzdata/Zones/Europe select Brussels" | chroot "\${MOUNT_PATH}" debconf-set-selections
|
|
||||||
|
|
||||||
chroot \${MOUNT_PATH} apt update
|
|
||||||
|
|
||||||
# Set up APT for non-interactive installation
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
export DEBCONF_NONINTERACTIVE_SEEN=true
|
|
||||||
|
|
||||||
# Update package lists
|
|
||||||
echo "Updating package lists in chroot..."
|
|
||||||
chroot \${MOUNT_PATH} apt-get update -yq
|
|
||||||
|
|
||||||
# Install required packages
|
|
||||||
echo "Installing essential packages..."
|
|
||||||
chroot \${MOUNT_PATH} apt-get install -yq screen bash coreutils curl mc unzip sudo which openssh-client openssh-server redis wget
|
|
||||||
|
|
||||||
echo "Cleaning up..."
|
|
||||||
umount "\${MOUNT_PATH}/dev" || true
|
|
||||||
umount "\${MOUNT_PATH}/proc" || true
|
|
||||||
umount "\${MOUNT_PATH}/sys" || true
|
|
||||||
|
|
||||||
'
|
|
||||||
)!
|
|
||||||
builder.install_zinit()!
|
|
||||||
// builder.set_entrypoint('redis-server')!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
// builder machine based on arch and install vlang
|
|
||||||
pub fn (mut e CEngine) builder_go_rust(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder go rust')
|
|
||||||
name := 'builder_go_rust'
|
|
||||||
e.builder_base(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder := e.builder_new(name: name, from: 'localhost/base', delete: true)!
|
|
||||||
builder.hero_execute_cmd('installers -n golang,rust')!
|
|
||||||
// builder.clean()!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_js(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder js')
|
|
||||||
name := 'builder_js'
|
|
||||||
e.builder_base(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder := e.builder_new(name: name, from: 'localhost/base', delete: true)!
|
|
||||||
builder.hero_execute_cmd('installers -n nodejs')!
|
|
||||||
// builder.clean()!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_js_python(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder js python')
|
|
||||||
name := 'builder_js_python'
|
|
||||||
e.builder_js(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder := e.builder_new(name: name, from: 'localhost/builder_js', delete: true)!
|
|
||||||
builder.hero_execute_cmd('installers -n python')!
|
|
||||||
// builder.clean()!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_hero(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder hero dev')
|
|
||||||
name := 'builder_hero'
|
|
||||||
e.builder_js_python(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder := e.builder_new(name: name, from: 'localhost/builder_js_python', delete: true)!
|
|
||||||
builder.hero_execute_cmd('installers -n hero')!
|
|
||||||
// builder.clean()!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_herodev(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder hero dev')
|
|
||||||
name := 'builder_herodev'
|
|
||||||
e.builder_js_python(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder := e.builder_new(name: name, from: 'localhost/builder_hero', delete: true)!
|
|
||||||
builder.hero_execute_cmd('installers -n herodev')!
|
|
||||||
// builder.clean()!
|
|
||||||
builder.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_heroweb(args GetArgs) !Builder {
|
|
||||||
console.print_header('buildah builder hero web')
|
|
||||||
name := 'builder_heroweb'
|
|
||||||
e.builder_go_rust(reset: false)!
|
|
||||||
e.builder_hero(reset: false)!
|
|
||||||
if !args.reset && e.builder_exists(name)! {
|
|
||||||
return e.builder_get(name)!
|
|
||||||
}
|
|
||||||
mut builder0 := e.builder_new(
|
|
||||||
name: 'builder_heroweb_temp'
|
|
||||||
from: 'localhost/builder_go_rust'
|
|
||||||
delete: true
|
|
||||||
)!
|
|
||||||
builder0.hero_execute_cmd('installers -n heroweb')!
|
|
||||||
// builder0.hero_execute_cmd("installers -n heroweb")!
|
|
||||||
mpath := builder0.mount_to_path()!
|
|
||||||
|
|
||||||
// copy the built binary to host
|
|
||||||
osal.exec(
|
|
||||||
cmd: '
|
|
||||||
mkdir -p ${os.home_dir()}/hero/var/bin
|
|
||||||
cp ${mpath}/usr/local/bin/* ${os.home_dir()}/hero/var/bin/
|
|
||||||
'
|
|
||||||
)!
|
|
||||||
|
|
||||||
builder0.delete()!
|
|
||||||
mut builder2 := e.builder_new(name: name, from: 'localhost/builder_hero', delete: true)!
|
|
||||||
builder2.copy('${os.home_dir()}/hero/var/bin/', '/usr/local/bin/')!
|
|
||||||
builder2.commit('localhost/${name}')!
|
|
||||||
e.load()!
|
|
||||||
return builder2
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
module herocontainers
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.osal.core as osal
|
|
||||||
import freeflowuniverse.herolib.ui.console
|
|
||||||
import json
|
|
||||||
|
|
||||||
fn (mut e CEngine) builders_load() ! {
|
|
||||||
cmd := 'buildah containers --json'
|
|
||||||
out := osal.execute_silent(cmd)!
|
|
||||||
mut r := json.decode([]Builder, out) or { return error('Failed to decode JSON: ${err}') }
|
|
||||||
for mut item in r {
|
|
||||||
item.engine = &e
|
|
||||||
}
|
|
||||||
e.builders = r
|
|
||||||
}
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct BuilderNewArgs {
|
|
||||||
pub mut:
|
|
||||||
name string = 'default'
|
|
||||||
from string = 'docker.io/ubuntu:latest'
|
|
||||||
delete bool = true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_new(args_ BuilderNewArgs) !Builder {
|
|
||||||
mut args := args_
|
|
||||||
if args.delete {
|
|
||||||
e.builder_delete(args.name)!
|
|
||||||
}
|
|
||||||
osal.exec(cmd: 'buildah --name ${args.name} from ${args.from}')!
|
|
||||||
e.builders_load()!
|
|
||||||
return e.builder_get(args.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get buildah containers
|
|
||||||
pub fn (mut e CEngine) builders_get() ![]Builder {
|
|
||||||
if e.builders.len == 0 {
|
|
||||||
e.builders_load()!
|
|
||||||
}
|
|
||||||
return e.builders
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_exists(name string) !bool {
|
|
||||||
r := e.builders_get()!
|
|
||||||
res := r.filter(it.containername == name)
|
|
||||||
if res.len == 1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if res.len > 1 {
|
|
||||||
panic('bug')
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_get(name string) !Builder {
|
|
||||||
r := e.builders_get()!
|
|
||||||
res := r.filter(it.containername == name)
|
|
||||||
if res.len == 1 {
|
|
||||||
return res[0]
|
|
||||||
}
|
|
||||||
if res.len > 1 {
|
|
||||||
panic('bug')
|
|
||||||
}
|
|
||||||
return error('couldnt find builder with name ${name}')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builders_delete_all() ! {
|
|
||||||
console.print_debug('remove all')
|
|
||||||
osal.execute_stdout('buildah rm -a')!
|
|
||||||
e.builders_load()!
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_delete(name string) ! {
|
|
||||||
if e.builder_exists(name)! {
|
|
||||||
console.print_debug('remove ${name}')
|
|
||||||
osal.execute_stdout('buildah rm ${name}')!
|
|
||||||
e.builders_load()!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut e CEngine) builder_names() ![]string {
|
|
||||||
r := e.builders_get()!
|
|
||||||
return r.map(it.containername)
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
module herocontainers
|
|
||||||
|
|
||||||
import freeflowuniverse.herolib.installers.virt.podman as podman_installer
|
|
||||||
import freeflowuniverse.herolib.installers.lang.herolib
|
|
||||||
import freeflowuniverse.herolib.core
|
|
||||||
|
|
||||||
@[params]
|
|
||||||
pub struct NewArgs {
|
|
||||||
pub mut:
|
|
||||||
install bool = true
|
|
||||||
reset bool
|
|
||||||
herocompile bool
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(args_ NewArgs) !CEngine {
|
|
||||||
mut args := args_
|
|
||||||
|
|
||||||
if !core.is_linux()! {
|
|
||||||
return error('only linux supported as host for now')
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.install {
|
|
||||||
mut podman_installer0 := podman_installer.get()!
|
|
||||||
podman_installer0.install()!
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.herocompile {
|
|
||||||
herolib.check()! // will check if install, if not will do
|
|
||||||
herolib.hero_compile(reset: true)!
|
|
||||||
}
|
|
||||||
|
|
||||||
mut engine := CEngine{}
|
|
||||||
engine.init()!
|
|
||||||
if args.reset {
|
|
||||||
engine.reset_all()!
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@ pub mut:
|
|||||||
networks []string
|
networks []string
|
||||||
labels map[string]string @[str: skip]
|
labels map[string]string @[str: skip]
|
||||||
image &Image @[str: skip]
|
image &Image @[str: skip]
|
||||||
engine &CEngine @[skip; str: skip]
|
engine &PodmanFactory @[skip; str: skip]
|
||||||
status utils.ContainerStatus
|
status utils.ContainerStatus
|
||||||
memsize int // in MB
|
memsize int // in MB
|
||||||
command string
|
command string
|
||||||
@@ -54,7 +54,7 @@ pub mut:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a new container from an image
|
// create a new container from an image
|
||||||
pub fn (mut e CEngine) container_create(args_ ContainerCreateArgs) !&Container {
|
pub fn (mut e PodmanFactory) container_create(args_ ContainerCreateArgs) !&Container {
|
||||||
mut args := args_
|
mut args := args_
|
||||||
|
|
||||||
mut cmd := 'podman run --systemd=false'
|
mut cmd := 'podman run --systemd=false'
|
||||||
@@ -2,18 +2,17 @@ module herocontainers
|
|||||||
|
|
||||||
import freeflowuniverse.herolib.osal.core as osal { exec }
|
import freeflowuniverse.herolib.osal.core as osal { exec }
|
||||||
import freeflowuniverse.herolib.core
|
import freeflowuniverse.herolib.core
|
||||||
|
import freeflowuniverse.herolib.installers.virt.podman as podman_installer
|
||||||
|
|
||||||
@[heap]
|
@[heap]
|
||||||
pub struct CEngine {
|
pub struct PodmanFactory {
|
||||||
pub mut:
|
pub mut:
|
||||||
sshkeys_allowed []string // all keys here have access over ssh into the machine, when ssh enabled
|
// sshkeys_allowed []string // all keys here have access over ssh into the machine, when ssh enabled
|
||||||
images []Image
|
images []Image
|
||||||
containers []Container
|
containers []Container
|
||||||
builders []Builder
|
|
||||||
buildpath string
|
buildpath string
|
||||||
localonly bool
|
// cache bool = true
|
||||||
cache bool = true
|
// push bool
|
||||||
push bool
|
|
||||||
// platform []BuildPlatformType // used to build
|
// platform []BuildPlatformType // used to build
|
||||||
// registries []BAHRegistry // one or more supported BAHRegistries
|
// registries []BAHRegistry // one or more supported BAHRegistries
|
||||||
prefix string
|
prefix string
|
||||||
@@ -24,7 +23,22 @@ pub enum BuildPlatformType {
|
|||||||
linux_amd64
|
linux_amd64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut e CEngine) init() ! {
|
@[params]
|
||||||
|
pub struct NewArgs {
|
||||||
|
pub mut:
|
||||||
|
install bool = true
|
||||||
|
reset bool
|
||||||
|
herocompile bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if args.install {
|
||||||
|
mut podman_installer0 := podman_installer.get()!
|
||||||
|
podman_installer0.install()!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn (mut e PodmanFactory) init() ! {
|
||||||
if e.buildpath == '' {
|
if e.buildpath == '' {
|
||||||
e.buildpath = '/tmp/builder'
|
e.buildpath = '/tmp/builder'
|
||||||
exec(cmd: 'mkdir -p ${e.buildpath}', stdout: false)!
|
exec(cmd: 'mkdir -p ${e.buildpath}', stdout: false)!
|
||||||
@@ -33,14 +47,14 @@ fn (mut e CEngine) init() ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reload the state from system
|
// reload the state from system
|
||||||
pub fn (mut e CEngine) load() ! {
|
pub fn (mut e PodmanFactory) load() ! {
|
||||||
e.builders_load()!
|
e.builders_load()!
|
||||||
e.images_load()!
|
e.images_load()!
|
||||||
e.containers_load()!
|
e.containers_load()!
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset all images & containers, CAREFUL!
|
// reset all images & containers, CAREFUL!
|
||||||
pub fn (mut e CEngine) reset_all() ! {
|
pub fn (mut e PodmanFactory) reset_all() ! {
|
||||||
e.load()!
|
e.load()!
|
||||||
for mut container in e.containers.clone() {
|
for mut container in e.containers.clone() {
|
||||||
container.delete()!
|
container.delete()!
|
||||||
@@ -59,7 +73,7 @@ pub fn (mut e CEngine) reset_all() ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get free port
|
// Get free port
|
||||||
pub fn (mut e CEngine) get_free_port() ?int {
|
pub fn (mut e PodmanFactory) get_free_port() ?int {
|
||||||
mut used_ports := []int{}
|
mut used_ports := []int{}
|
||||||
mut range := []int{}
|
mut range := []int{}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ pub mut:
|
|||||||
digest string
|
digest string
|
||||||
size int // size in MB
|
size int // size in MB
|
||||||
created time.Time
|
created time.Time
|
||||||
engine &CEngine @[skip; str: skip]
|
engine &PodmanFactory @[skip; str: skip]
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete podman image
|
// delete podman image
|
||||||
@@ -6,10 +6,10 @@ import freeflowuniverse.herolib.core.texttools
|
|||||||
import freeflowuniverse.herolib.virt.utils
|
import freeflowuniverse.herolib.virt.utils
|
||||||
// import freeflowuniverse.herolib.ui.console
|
// import freeflowuniverse.herolib.ui.console
|
||||||
|
|
||||||
// load all containers, they can be consulted in e.containers
|
// load all containers, they can be consulted in self.containers
|
||||||
// see obj: Container as result in e.containers
|
// see obj: Container as result in self.containers
|
||||||
fn (mut e CEngine) containers_load() ! {
|
fn (mut self PodmanFactory) containers_load() ! {
|
||||||
e.containers = []Container{}
|
self.containers = []Container{}
|
||||||
mut ljob := exec(
|
mut ljob := exec(
|
||||||
// we used || because sometimes the command has | in it and this will ruin all subsequent columns
|
// 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}}'"
|
cmd: "podman container list -a --no-trunc --size --format '{{.ID}}||{{.Names}}||{{.ImageID}}||{{.Command}}||{{.CreatedAt}}||{{.Ports}}||{{.State}}||{{.Size}}||{{.Mounts}}||{{.Networks}}||{{.Labels}}'"
|
||||||
@@ -30,9 +30,9 @@ fn (mut e CEngine) containers_load() ! {
|
|||||||
if fields[2] == '' {
|
if fields[2] == '' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut image := e.image_get(id_full: fields[2])!
|
mut image := self.image_get(id_full: fields[2])!
|
||||||
mut container := Container{
|
mut container := Container{
|
||||||
engine: &e
|
engine: &self
|
||||||
image: &image
|
image: &image
|
||||||
}
|
}
|
||||||
container.id = id
|
container.id = id
|
||||||
@@ -47,7 +47,7 @@ fn (mut e CEngine) containers_load() ! {
|
|||||||
container.networks = utils.parse_networks(fields[9])!
|
container.networks = utils.parse_networks(fields[9])!
|
||||||
container.labels = utils.parse_labels(fields[10])!
|
container.labels = utils.parse_labels(fields[10])!
|
||||||
container.ssh_enabled = utils.contains_ssh_port(container.ports)
|
container.ssh_enabled = utils.contains_ssh_port(container.ports)
|
||||||
e.containers << container
|
self.containers << container
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,14 +63,14 @@ pub mut:
|
|||||||
|
|
||||||
// get containers from memory
|
// get containers from memory
|
||||||
// params:
|
// params:
|
||||||
// name string (can also be a glob e.g. use *,? and [])
|
// name string (can also be a glob self.g. use *,? and [])
|
||||||
// id string
|
// id string
|
||||||
// image_id string
|
// image_id string
|
||||||
pub fn (mut e CEngine) containers_get(args_ ContainerGetArgs) ![]&Container {
|
pub fn (mut self PodmanFactory) containers_get(args_ ContainerGetArgs) ![]&Container {
|
||||||
mut args := args_
|
mut args := args_
|
||||||
args.name = texttools.name_fix(args.name)
|
args.name = texttools.name_fix(args.name)
|
||||||
mut res := []&Container{}
|
mut res := []&Container{}
|
||||||
for _, c in e.containers {
|
for _, c in self.containers {
|
||||||
if args.name.contains('*') || args.name.contains('?') || args.name.contains('[') {
|
if args.name.contains('*') || args.name.contains('?') || args.name.contains('[') {
|
||||||
if c.name.match_glob(args.name) {
|
if c.name.match_glob(args.name) {
|
||||||
res << &c
|
res << &c
|
||||||
@@ -96,10 +96,10 @@ pub fn (mut e CEngine) containers_get(args_ ContainerGetArgs) ![]&Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get container from memory, can use match_glob see https://modules.vlang.io/index.html#string.match_glob
|
// 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 {
|
pub fn (mut self PodmanFactory) container_get(args_ ContainerGetArgs) !&Container {
|
||||||
mut args := args_
|
mut args := args_
|
||||||
args.name = texttools.name_fix(args.name)
|
args.name = texttools.name_fix(args.name)
|
||||||
mut res := e.containers_get(args)!
|
mut res := self.containers_get(args)!
|
||||||
if res.len > 1 {
|
if res.len > 1 {
|
||||||
return ContainerGetError{
|
return ContainerGetError{
|
||||||
args: args
|
args: args
|
||||||
@@ -109,8 +109,8 @@ pub fn (mut e CEngine) container_get(args_ ContainerGetArgs) !&Container {
|
|||||||
return res[0]
|
return res[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut e CEngine) container_exists(args ContainerGetArgs) !bool {
|
pub fn (mut self PodmanFactory) container_exists(args ContainerGetArgs) !bool {
|
||||||
e.container_get(args) or {
|
self.container_get(args) or {
|
||||||
if err.code() == 1 {
|
if err.code() == 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -119,19 +119,19 @@ pub fn (mut e CEngine) container_exists(args ContainerGetArgs) !bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut e CEngine) container_delete(args ContainerGetArgs) ! {
|
pub fn (mut self PodmanFactory) container_delete(args ContainerGetArgs) ! {
|
||||||
mut c := e.container_get(args)!
|
mut c := self.container_get(args)!
|
||||||
c.delete()!
|
c.delete()!
|
||||||
e.load()!
|
self.load()!
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove one or more container
|
// remove one or more container
|
||||||
pub fn (mut e CEngine) containers_delete(args ContainerGetArgs) ! {
|
pub fn (mut self PodmanFactory) containers_delete(args ContainerGetArgs) ! {
|
||||||
mut cs := e.containers_get(args)!
|
mut cs := self.containers_get(args)!
|
||||||
for mut c in cs {
|
for mut c in cs {
|
||||||
c.delete()!
|
c.delete()!
|
||||||
}
|
}
|
||||||
e.load()!
|
self.load()!
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContainerGetError {
|
pub struct ContainerGetError {
|
||||||
@@ -5,8 +5,8 @@ import freeflowuniverse.herolib.osal.core as osal { exec }
|
|||||||
import time
|
import time
|
||||||
import freeflowuniverse.herolib.ui.console
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
|
||||||
fn (mut e CEngine) images_load() ! {
|
fn (mut self PodmanFactory) images_load() ! {
|
||||||
e.images = []Image{}
|
self.images = []Image{}
|
||||||
mut lines := osal.execute_silent("podman images --format '{{.ID}}||{{.Id}}||{{.Repository}}||{{.Tag}}||{{.Digest}}||{{.Size}}||{{.CreatedAt}}'")!
|
mut lines := osal.execute_silent("podman images --format '{{.ID}}||{{.Id}}||{{.Repository}}||{{.Tag}}||{{.Digest}}||{{.Size}}||{{.CreatedAt}}'")!
|
||||||
for line in lines.split_into_lines() {
|
for line in lines.split_into_lines() {
|
||||||
fields := line.split('||').map(utils.clear_str)
|
fields := line.split('||').map(utils.clear_str)
|
||||||
@@ -14,7 +14,7 @@ fn (mut e CEngine) images_load() ! {
|
|||||||
panic('podman image needs to output 7 parts.\n${fields}')
|
panic('podman image needs to output 7 parts.\n${fields}')
|
||||||
}
|
}
|
||||||
mut image := Image{
|
mut image := Image{
|
||||||
engine: &e
|
engine: &self
|
||||||
}
|
}
|
||||||
image.id = fields[0]
|
image.id = fields[0]
|
||||||
image.id_full = fields[1]
|
image.id_full = fields[1]
|
||||||
@@ -23,12 +23,12 @@ fn (mut e CEngine) images_load() ! {
|
|||||||
image.digest = utils.parse_digest(fields[4]) or { '' }
|
image.digest = utils.parse_digest(fields[4]) or { '' }
|
||||||
image.size = utils.parse_size_mb(fields[5]) or { 0 }
|
image.size = utils.parse_size_mb(fields[5]) or { 0 }
|
||||||
image.created = utils.parse_time(fields[6]) or { time.now() }
|
image.created = utils.parse_time(fields[6]) or { time.now() }
|
||||||
e.images << image
|
self.images << image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// import herocontainers image back into the local env
|
// import herocontainers image back into the local env
|
||||||
pub fn (mut engine CEngine) image_load(path string) ! {
|
pub fn (mut engine PodmanFactory) image_load(path string) ! {
|
||||||
exec(cmd: 'podman load < ${path}', stdout: false)!
|
exec(cmd: 'podman load < ${path}', stdout: false)!
|
||||||
engine.images_load()!
|
engine.images_load()!
|
||||||
}
|
}
|
||||||
@@ -50,8 +50,8 @@ pub:
|
|||||||
// digest string
|
// digest string
|
||||||
// id string
|
// id string
|
||||||
// id_full
|
// id_full
|
||||||
pub fn (mut e CEngine) image_get(args ImageGetArgs) !Image {
|
pub fn (mut self PodmanFactory) image_get(args ImageGetArgs) !Image {
|
||||||
for i in e.images {
|
for i in self.images {
|
||||||
if args.digest != '' && i.digest == args.digest {
|
if args.digest != '' && i.digest == args.digest {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ pub fn (mut e CEngine) image_get(args ImageGetArgs) !Image {
|
|||||||
if args.repo != '' || args.tag != '' {
|
if args.repo != '' || args.tag != '' {
|
||||||
mut counter := 0
|
mut counter := 0
|
||||||
mut result_digest := ''
|
mut result_digest := ''
|
||||||
for i in e.images {
|
for i in self.images {
|
||||||
if args.repo != '' && i.repo != args.repo {
|
if args.repo != '' && i.repo != args.repo {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ pub fn (mut e CEngine) image_get(args ImageGetArgs) !Image {
|
|||||||
toomany: true
|
toomany: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e.image_get(digest: result_digest)!
|
return self.image_get(digest: result_digest)!
|
||||||
}
|
}
|
||||||
return ImageGetError{
|
return ImageGetError{
|
||||||
args: args
|
args: args
|
||||||
@@ -91,8 +91,8 @@ pub fn (mut e CEngine) image_get(args ImageGetArgs) !Image {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut e CEngine) image_exists(args ImageGetArgs) !bool {
|
pub fn (mut self PodmanFactory) image_exists(args ImageGetArgs) !bool {
|
||||||
e.image_get(args) or {
|
self.image_get(args) or {
|
||||||
if err.code() == 1 {
|
if err.code() == 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -102,11 +102,11 @@ pub fn (mut e CEngine) image_exists(args ImageGetArgs) !bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get buildah containers
|
// get buildah containers
|
||||||
pub fn (mut e CEngine) images_get() ![]Image {
|
pub fn (mut self PodmanFactory) images_get() ![]Image {
|
||||||
if e.builders.len == 0 {
|
if self.builders.len == 0 {
|
||||||
e.images_load()!
|
self.images_load()!
|
||||||
}
|
}
|
||||||
return e.images
|
return self.images
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (err ImageGetError) msg() string {
|
pub fn (err ImageGetError) msg() string {
|
||||||
117
lib/virt/podman/readme.md
Normal file
117
lib/virt/podman/readme.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
# Herocontainers
|
||||||
|
|
||||||
|
Tools to work with containers
|
||||||
|
|
||||||
|
```go
|
||||||
|
#!/usr/bin/env -S v -n -cg -w -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.virt.herocontainers
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.builder
|
||||||
|
|
||||||
|
//interative means will ask for login/passwd
|
||||||
|
|
||||||
|
console.print_header("BUILDAH Demo.")
|
||||||
|
|
||||||
|
//if herocompile on, then will forced compile hero, which might be needed in debug mode for hero
|
||||||
|
// to execute hero scripts inside build container
|
||||||
|
mut factory:=herocontainers.new(herocompile=true)!
|
||||||
|
//mut b:=factory.builder_new(name:"test")!
|
||||||
|
|
||||||
|
//create
|
||||||
|
factory.builderv_create()!
|
||||||
|
|
||||||
|
//get the container
|
||||||
|
//mut b2:=factory.builder_get("builderv")!
|
||||||
|
//b2.shell()!
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## buildah tricks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#find the containers as have been build, these are the active ones you can work with
|
||||||
|
buildah ls
|
||||||
|
#see the images
|
||||||
|
buildah images
|
||||||
|
```
|
||||||
|
|
||||||
|
result is something like
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
|
||||||
|
a9946633d4e7 * scratch base
|
||||||
|
86ff0deb00bf * 4feda76296d6 localhost/builder:latest base_go_rust
|
||||||
|
```
|
||||||
|
|
||||||
|
some tricks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#run interactive in one (here we chose the builderv one)
|
||||||
|
buildah run --terminal --env TERM=xterm base /bin/bash
|
||||||
|
#or
|
||||||
|
buildah run --terminal --env TERM=xterm default /bin/bash
|
||||||
|
#or
|
||||||
|
buildah run --terminal --env TERM=xterm base_go_rust /bin/bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
to check inside the container about diskusage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install ncdu
|
||||||
|
ncdu
|
||||||
|
```
|
||||||
|
|
||||||
|
## create container
|
||||||
|
|
||||||
|
|
||||||
|
```go
|
||||||
|
import freeflowuniverse.herolib.virt.herocontainers
|
||||||
|
import freeflowuniverse.herolib.ui.console
|
||||||
|
import freeflowuniverse.herolib.builder
|
||||||
|
|
||||||
|
//interative means will ask for login/passwd
|
||||||
|
|
||||||
|
console.print_header("Get a container.")
|
||||||
|
|
||||||
|
mut e:=herocontainers.new()!
|
||||||
|
|
||||||
|
//info see https://docs.podman.io/en/latest/markdown/podman-run.1.html
|
||||||
|
|
||||||
|
mut c:=e.container_create(
|
||||||
|
name: 'mycontainer'
|
||||||
|
image_repo: 'ubuntu'
|
||||||
|
// Resource limits
|
||||||
|
memory: '1g'
|
||||||
|
cpus: 0.5
|
||||||
|
// Network config
|
||||||
|
network: 'bridge'
|
||||||
|
network_aliases: ['myapp', 'api']
|
||||||
|
// DNS config
|
||||||
|
dns_servers: ['8.8.8.8', '8.8.4.4']
|
||||||
|
dns_search: ['example.com']
|
||||||
|
interactive: true // Keep STDIN open
|
||||||
|
mounts: [
|
||||||
|
'type=bind,src=/data,dst=/container/data,ro=true'
|
||||||
|
]
|
||||||
|
volumes: [
|
||||||
|
'/config:/etc/myapp:ro'
|
||||||
|
]
|
||||||
|
published_ports: [
|
||||||
|
'127.0.0.1:8080:80'
|
||||||
|
]
|
||||||
|
)!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## future
|
||||||
|
|
||||||
|
should make this module compatible with https://github.com/containerd/nerdctl
|
||||||
230
manual/playcmds/osal_core.md
Normal file
230
manual/playcmds/osal_core.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# OSAL Core Playbook Commands
|
||||||
|
|
||||||
|
This document describes the HeroScript commands available for interacting with the Operating System Abstraction Layer (OSAL) core functionalities. These commands allow for managing "done" keys, environment variables, executing commands, and handling package management within HeroScript playbooks.
|
||||||
|
|
||||||
|
## Done Management
|
||||||
|
The `osal.done` commands provide a mechanism to track the completion status of various tasks or conditions within a playbook.
|
||||||
|
|
||||||
|
- `!!osal.done_set`
|
||||||
|
- **Description**: Sets a key-value pair in the done system. This can be used to mark a task as completed or store a specific state.
|
||||||
|
- **Parameters**:
|
||||||
|
- `key` (string, required): The unique identifier for the done item.
|
||||||
|
- `value` (string, required): The value to associate with the key.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.done_set
|
||||||
|
key: 'installation_complete'
|
||||||
|
value: 'true'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.done_delete`
|
||||||
|
- **Description**: Deletes a specific done key and its associated value.
|
||||||
|
- **Parameters**:
|
||||||
|
- `key` (string, required): The key of the done item to delete.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.done_delete
|
||||||
|
key: 'temporary_flag'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.done_reset`
|
||||||
|
- **Description**: Resets (deletes) all currently set done keys. Use with caution.
|
||||||
|
- **Parameters**: None
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.done_reset
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.done_print`
|
||||||
|
- **Description**: Prints all currently set done keys and their values to the console.
|
||||||
|
- **Parameters**: None
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.done_print
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
The `osal.env` commands allow for manipulation of environment variables during playbook execution.
|
||||||
|
|
||||||
|
- `!!osal.env_set`
|
||||||
|
- **Description**: Sets a single environment variable.
|
||||||
|
- **Parameters**:
|
||||||
|
- `key` (string, required): The name of the environment variable.
|
||||||
|
- `value` (string, required): The value to set for the variable.
|
||||||
|
- `overwrite` (bool, optional, default: `true`): If `true`, overwrites the variable if it already exists.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.env_set
|
||||||
|
key: 'MY_APP_PATH'
|
||||||
|
value: '/opt/my_app'
|
||||||
|
overwrite: true
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.env_unset`
|
||||||
|
- **Description**: Unsets (removes) a single environment variable.
|
||||||
|
- **Parameters**:
|
||||||
|
- `key` (string, required): The name of the environment variable to unset.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.env_unset
|
||||||
|
key: 'OLD_VAR'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.env_unset_all`
|
||||||
|
- **Description**: Unsets all environment variables. Use with extreme caution as this can affect subsequent commands.
|
||||||
|
- **Parameters**: None
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.env_unset_all
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.env_set_all`
|
||||||
|
- **Description**: Sets multiple environment variables from a map of key-value pairs.
|
||||||
|
- **Parameters**:
|
||||||
|
- `clear_before_set` (bool, optional, default: `false`): If `true`, all existing environment variables are cleared before setting the new ones.
|
||||||
|
- `overwrite_if_exists` (bool, optional, default: `true`): If `true`, new variables will overwrite existing ones with the same name.
|
||||||
|
- Any other named parameter will be treated as an environment variable to set (e.g., `VAR1: 'value1'`).
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.env_set_all
|
||||||
|
clear_before_set: false
|
||||||
|
overwrite_if_exists: true
|
||||||
|
APP_ENV: 'production'
|
||||||
|
DEBUG_MODE: 'false'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.load_env_file`
|
||||||
|
- **Description**: Loads environment variables from a specified file (e.g., a `.env` file).
|
||||||
|
- **Parameters**:
|
||||||
|
- `file_path` (string, required): The path to the environment file.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.load_env_file
|
||||||
|
file_path: '/etc/my_app/.env'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Command Execution
|
||||||
|
The `osal.exec` commands provide various ways to execute shell commands, with options for output handling, error management, and interactivity.
|
||||||
|
|
||||||
|
- `!!osal.exec`
|
||||||
|
- **Description**: Executes a command with comprehensive options for control and output capture.
|
||||||
|
- **Parameters**:
|
||||||
|
- `cmd` (string, required): The command string to execute.
|
||||||
|
- `name` (string, optional): A name for the job.
|
||||||
|
- `description` (string, optional): A description for the job.
|
||||||
|
- `timeout` (int, optional, default: `3600`): Maximum execution time in seconds.
|
||||||
|
- `stdout` (bool, optional, default: `true`): If `true`, prints stdout to the console.
|
||||||
|
- `stdout_log` (bool, optional, default: `true`): If `true`, logs stdout.
|
||||||
|
- `raise_error` (bool, optional, default: `true`): If `true`, raises an error if the command fails.
|
||||||
|
- `ignore_error` (bool, optional, default: `false`): If `true`, ignores command execution errors.
|
||||||
|
- `work_folder` (string, optional): The working directory for the command.
|
||||||
|
- `scriptkeep` (bool, optional, default: `false`): If `true`, keeps the generated script file.
|
||||||
|
- `debug` (bool, optional, default: `false`): If `true`, enables debug output for the command.
|
||||||
|
- `shell` (bool, optional, default: `false`): If `true`, executes the command in a shell.
|
||||||
|
- `retry` (int, optional, default: `0`): Number of times to retry the command on failure.
|
||||||
|
- `interactive` (bool, optional, default: `true`): If `true`, allows interactive input/output.
|
||||||
|
- `async` (bool, optional, default: `false`): If `true`, executes the command asynchronously.
|
||||||
|
- `output_key` (string, optional): If provided, the command's output will be stored in the done system under this key.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.exec
|
||||||
|
cmd: 'ls -la /var/log'
|
||||||
|
output_key: 'log_directory_listing'
|
||||||
|
timeout: 60
|
||||||
|
raise_error: true
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.exec_silent`
|
||||||
|
- **Description**: Executes a command without printing any output to the console.
|
||||||
|
- **Parameters**:
|
||||||
|
- `cmd` (string, required): The command string to execute.
|
||||||
|
- `output_key` (string, optional): If provided, the command's output will be stored in the done system under this key.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.exec_silent
|
||||||
|
cmd: 'systemctl restart my_service'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.exec_debug`
|
||||||
|
- **Description**: Executes a command with debug output enabled.
|
||||||
|
- **Parameters**:
|
||||||
|
- `cmd` (string, required): The command string to execute.
|
||||||
|
- `output_key` (string, optional): If provided, the command's output will be stored in the done system under this key.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.exec_debug
|
||||||
|
cmd: 'my_script --verbose'
|
||||||
|
output_key: 'script_debug_output'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.exec_stdout`
|
||||||
|
- **Description**: Executes a command and prints its standard output directly to the console.
|
||||||
|
- **Parameters**:
|
||||||
|
- `cmd` (string, required): The command string to execute.
|
||||||
|
- `output_key` (string, optional): If provided, the command's output will be stored in the done system under this key.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.exec_stdout
|
||||||
|
cmd: 'cat /etc/os-release'
|
||||||
|
output_key: 'os_info'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.exec_interactive`
|
||||||
|
- **Description**: Executes a command in an interactive mode, allowing user input.
|
||||||
|
- **Parameters**:
|
||||||
|
- `cmd` (string, required): The command string to execute.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.exec_interactive
|
||||||
|
cmd: 'ssh user@remote_host'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Package Management
|
||||||
|
The `osal.package` commands provide basic functionalities for managing system packages.
|
||||||
|
|
||||||
|
- `!!osal.package_refresh`
|
||||||
|
- **Description**: Refreshes the local package lists from configured repositories.
|
||||||
|
- **Parameters**: None
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_refresh
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.package_install`
|
||||||
|
- **Description**: Installs one or more packages.
|
||||||
|
- **Parameters**:
|
||||||
|
- `name` (string, optional): A single package name to install.
|
||||||
|
- `names` (list of strings, optional): A comma-separated list of package names to install.
|
||||||
|
- Positional arguments can also be used for package names.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_install
|
||||||
|
name: 'git'
|
||||||
|
```
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_install
|
||||||
|
names: 'curl,vim,htop'
|
||||||
|
```
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_install
|
||||||
|
git curl vim
|
||||||
|
```
|
||||||
|
|
||||||
|
- `!!osal.package_remove`
|
||||||
|
- **Description**: Removes one or more packages.
|
||||||
|
- **Parameters**:
|
||||||
|
- `name` (string, optional): A single package name to remove.
|
||||||
|
- `names` (list of strings, optional): A comma-separated list of package names to remove.
|
||||||
|
- Positional arguments can also be used for package names.
|
||||||
|
- **Example**:
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_remove
|
||||||
|
name: 'unwanted_package'
|
||||||
|
```
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_remove
|
||||||
|
names: 'old_tool,unused_lib'
|
||||||
|
```
|
||||||
|
```heroscript
|
||||||
|
!!osal.package_remove
|
||||||
|
apache2 php7.4
|
||||||
Reference in New Issue
Block a user