diff --git a/examples/core/generate.vsh b/examples/core/generate.vsh index ef3bf223..0b2163ed 100755 --- a/examples/core/generate.vsh +++ b/examples/core/generate.vsh @@ -4,12 +4,18 @@ import freeflowuniverse.herolib.core.generator.generic as generator import freeflowuniverse.herolib.core.pathlib mut args := generator.GeneratorArgs{ - path: '~/code/github/freeflowuniverse/herolib/lib/clients' + path: '~/code/github/freeflowuniverse/herolib/lib/installers' force: true } +// mut args2 := generator.GeneratorArgs{ +// path: '~/code/github/freeflowuniverse/herolib/lib/installers/lang/rust' +// force: true +// } +// generator.scan(args2)! + // mut args := generator.GeneratorArgs{ -// path: '~/code/github/freeflowuniverse/herolib/lib' +// path: '~/code/github/freeflowuniverse/herolib/lib/installers' // force: true // } diff --git a/examples/installers/infra/zinit_installer.vsh b/examples/installers/infra/zinit_installer.vsh index ac3bce5f..2817969b 100755 --- a/examples/installers/infra/zinit_installer.vsh +++ b/examples/installers/infra/zinit_installer.vsh @@ -1,4 +1,4 @@ -#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run import freeflowuniverse.herolib.installers.infra.zinit_installer diff --git a/examples/installers/net/mycelium.vsh b/examples/installers/net/mycelium.vsh index bfa7e367..e6df3dd7 100755 --- a/examples/installers/net/mycelium.vsh +++ b/examples/installers/net/mycelium.vsh @@ -3,12 +3,18 @@ import freeflowuniverse.herolib.installers.net.mycelium_installer import freeflowuniverse.herolib.clients.mycelium -mut installer := mycelium_installer.get()! +mut installer := mycelium_installer.get(create:true)! +println(installer) + installer.start()! +$dbg; + mut r := mycelium.inspect()! println(r) +$dbg; + mut client := mycelium.get()! // Send a message to a node by public key diff --git a/lib/core/generator/generic/templates/objname_actions.vtemplate b/lib/core/generator/generic/templates/objname_actions.vtemplate index 45ee85ea..be9fb5b2 100644 --- a/lib/core/generator/generic/templates/objname_actions.vtemplate +++ b/lib/core/generator/generic/templates/objname_actions.vtemplate @@ -7,7 +7,7 @@ import freeflowuniverse.herolib.core.pathlib @if args.startupmanager import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager @end import freeflowuniverse.herolib.installers.ulist @@ -20,11 +20,11 @@ import freeflowuniverse.herolib.installers.lang.python import os @if args.startupmanager -fn startupcmd () ![]zinit.ZProcessNewArgs{ +fn startupcmd () ![]startupmanager.ZProcessNewArgs{ mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} //THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: '${args.name}' // cmd: '${args.name} server' // env: { diff --git a/lib/core/generator/generic/templates/objname_factory_.vtemplate b/lib/core/generator/generic/templates/objname_factory_.vtemplate index 4fbc9090..09156b94 100644 --- a/lib/core/generator/generic/templates/objname_factory_.vtemplate +++ b/lib/core/generator/generic/templates/objname_factory_.vtemplate @@ -9,19 +9,21 @@ import json @if args.cat == .installer import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit @if args.startupmanager import time @end @end +@if ! args.singleton __global ( ${args.name}_global map[string]&${args.classname} ${args.name}_default string ) +@end /////////FACTORY +@if args.hasconfig @@[params] pub struct ArgsGet { pub mut: @@ -29,6 +31,13 @@ pub mut: fromdb bool //will load from filesystem create bool //default will not create if not exist } +@else +@@[params] +pub struct ArgsGet { +pub mut: + name string = "default" +} +@end @if args.hasconfig pub fn new(args ArgsGet) !&${args.classname} { @@ -47,7 +56,7 @@ pub fn get(args ArgsGet) !&${args.classname} { if r.hexists('context:${args.name}', args.name)! { data := r.hget('context:${args.name}', args.name)! if data.len == 0 { - return error('${args.name} with name: ${args.name} does not exist, prob bug.') + return error('${args.classname} with name: ${args.name} does not exist, prob bug.') } mut obj := json.decode(${args.classname},data)! set_in_mem(obj)! @@ -127,19 +136,21 @@ fn set_in_mem(o ${args.classname}) ! { ${args.name}_default = o.name } -// switch instance to be used for ${args.name} -pub fn switch(name string) { - ${args.name}_default = name -} @else pub fn new(args ArgsGet) !&${args.classname} { return &${args.classname}{} } +pub fn get(args ArgsGet) !&${args.classname} { + return new(args)! +} @end pub fn play(mut plbook PlayBook) ! { + if ! plbook.exists(filter: '${args.name}.'){ + return + } mut install_actions := plbook.find(filter: '${args.name}.configure')! if install_actions.len > 0 { @if args.hasconfig @@ -149,7 +160,7 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } @else - panic("can't configure ??{${args.name}_obj}, because no config in this class.") + return error("can't configure ${args.name}, because no configuration allowed for this installer.") @end } @if args.cat == .installer @@ -200,23 +211,27 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////////////////////////////////////////////////////////////////////////////// @if args.startupmanager -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux - // systemd + // systemd match cat{ + .screen { + console.print_debug("startupmanager: zinit") + return startupmanager.get(.screen)! + } .zinit{ console.print_debug("startupmanager: zinit") - return startupmanager.get(cat:.zinit)! + return startupmanager.get(.zinit)! } .systemd{ console.print_debug("startupmanager: systemd") - return startupmanager.get(cat:.systemd)! + return startupmanager.get(.systemd)! }else{ console.print_debug("startupmanager: auto") - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -225,14 +240,18 @@ fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManag @if args.hasconfig //load from disk and make sure is properly intialized pub fn (mut self ${args.classname}) reload() ! { + @if ! args.singleton switch(self.name) + @end self=obj_init(self)! } @end @if args.startupmanager pub fn (mut self ${args.classname}) start() ! { + @if ! args.singleton switch(self.name) + @end if self.running()!{ return } @@ -296,10 +315,12 @@ pub fn (mut self ${args.classname}) running() !bool { //walk over the generic processes, if not running return for zprocess in startupcmd()!{ - mut sm:=startupmanager_get(zprocess.startuptype)! - r:=sm.running(zprocess.name)! - if r==false{ - return false + if zprocess.startuptype != .screen{ + mut sm:=startupmanager_get(zprocess.startuptype)! + r:=sm.running(zprocess.name)! + if r==false{ + return false + } } } return running()! @@ -337,3 +358,9 @@ pub fn (mut self ${args.classname}) destroy() ! { @end +// switch instance to be used for ${args.name} +pub fn switch(name string) { +@if ! args.singleton + ${args.name}_default = name +@end +} diff --git a/lib/core/pathlib/factory.v b/lib/core/pathlib/factory.v index 7784adb0..6afa8563 100644 --- a/lib/core/pathlib/factory.v +++ b/lib/core/pathlib/factory.v @@ -56,7 +56,10 @@ pub fn get_dir(args_ GetArgs) !Path { p2.absolute() if p2.exist == .no { if args.create { - os.mkdir_all(p2.absolute()) or { return error('cannot create path ${p2}, ${err}') } // Make sure that all the needed paths created + os.mkdir_all(p2.absolute()) or { + print_backtrace() + return error('cannot create path ${p2}, ${err}') + } // Make sure that all the needed paths created p2.check() } return p2 @@ -97,7 +100,10 @@ pub fn get_file(args_ GetArgs) !Path { mut parent_ := p2.parent()! parent_.check() if parent_.exist == .no { - os.mkdir_all(parent_.path) or { return error('cannot create path:${args.path}') } + os.mkdir_all(parent_.path) or { + print_backtrace() + return error('cannot create path:${args.path}') + } } if p2.exist == .no || args.empty { os.write_file(args.path, '') or { diff --git a/lib/installers/base/redis.v b/lib/installers/base/redis.v index 63b70089..adaf8942 100644 --- a/lib/installers/base/redis.v +++ b/lib/installers/base/redis.v @@ -90,7 +90,7 @@ pub fn start(args RedisInstallArgs) ! { // osal.exec(cmd:"redis-server ${configfilepath()} --daemonize yes")! // } } else { - mut sm := startupmanager.get()! + mut sm := startupmanager.get(.auto)! sm.new(name: 'redis', cmd: 'redis-server ${configfilepath()}', start: true)! } diff --git a/lib/installers/db/cometbft/cometbft_actions.v b/lib/installers/db/cometbft/cometbft_actions.v index 6cf1d112..c391931d 100644 --- a/lib/installers/db/cometbft/cometbft_actions.v +++ b/lib/installers/db/cometbft/cometbft_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'cometbft' // cmd: 'cometbft server' // env: { diff --git a/lib/installers/db/cometbft/cometbft_factory_.v b/lib/installers/db/cometbft/cometbft_factory_.v index 82fd5e02..e89832c9 100644 --- a/lib/installers/db/cometbft/cometbft_factory_.v +++ b/lib/installers/db/cometbft/cometbft_factory_.v @@ -3,8 +3,8 @@ module cometbft import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&CometBFT { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&CometBFT { mut obj := CometBFT{ name: args.name } - if args.name !in cometbft_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&CometBFT { + mut context := base.context()! + cometbft_default = args.name + if args.fromdb || args.name !in cometbft_global { + mut r := context.redis()! + if r.hexists('context:cometbft', args.name)! { + data := r.hget('context:cometbft', args.name)! + if data.len == 0 { + return error('CometBFT with name: cometbft does not exist, prob bug.') + } + mut obj := json.decode(CometBFT, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('cometbft', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("CometBFT with name 'cometbft' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return cometbft_global[args.name] or { - println(cometbft_global) - // bug if we get here because should be in globals - panic('could not get config for cometbft with name, is bug:${args.name}') + return error('could not get config for cometbft with name:cometbft') } } // register the config for the future pub fn set(o CometBFT) ! { set_in_mem(o)! + cometbft_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('cometbft', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:cometbft', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('cometbft', args.name) + mut r := context.redis()! + return r.hexists('context:cometbft', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('cometbft', args.name)! - if args.name in cometbft_global { - // del cometbft_global[args.name] + mut r := context.redis()! + r.hdel('context:cometbft', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&CometBFT { + mut res := []&CometBFT{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + cometbft_global = map[string]&CometBFT{} + cometbft_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:cometbft')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in cometbft_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o CometBFT) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'cometbft.') { + return + } mut install_actions := plbook.find(filter: 'cometbft.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'cometbft.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self CometBFT) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -260,10 +304,3 @@ pub fn (mut self CometBFT) destroy() ! { pub fn switch(name string) { cometbft_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/db/meilisearch_installer/meilisearch_installer_actions.v b/lib/installers/db/meilisearch_installer/meilisearch_installer_actions.v index 6bdb3ddc..e311be68 100644 --- a/lib/installers/db/meilisearch_installer/meilisearch_installer_actions.v +++ b/lib/installers/db/meilisearch_installer/meilisearch_installer_actions.v @@ -2,7 +2,7 @@ module meilisearch_installer import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.core.httpconnection import freeflowuniverse.herolib.core.texttools @@ -22,14 +22,15 @@ fn generate_master_key(length int) !string { return key.string() } -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} mut installer := get()! mut env := 'development' if installer.production { env = 'production' } - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'meilisearch' cmd: 'meilisearch --no-analytics --http-addr ${installer.host}:${installer.port} --env ${env} --db-path ${installer.path} --master-key ${installer.masterkey}' startuptype: .zinit diff --git a/lib/installers/db/meilisearch_installer/meilisearch_installer_factory_.v b/lib/installers/db/meilisearch_installer/meilisearch_installer_factory_.v index 79ed36c2..701b2284 100644 --- a/lib/installers/db/meilisearch_installer/meilisearch_installer_factory_.v +++ b/lib/installers/db/meilisearch_installer/meilisearch_installer_factory_.v @@ -3,8 +3,8 @@ module meilisearch_installer import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&MeilisearchInstaller { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&MeilisearchInstaller { mut obj := MeilisearchInstaller{ name: args.name } - if args.name !in meilisearch_installer_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&MeilisearchInstaller { + mut context := base.context()! + meilisearch_installer_default = args.name + if args.fromdb || args.name !in meilisearch_installer_global { + mut r := context.redis()! + if r.hexists('context:meilisearch_installer', args.name)! { + data := r.hget('context:meilisearch_installer', args.name)! + if data.len == 0 { + return error('MeilisearchInstaller with name: meilisearch_installer does not exist, prob bug.') + } + mut obj := json.decode(MeilisearchInstaller, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('meilisearch_installer', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("MeilisearchInstaller with name 'meilisearch_installer' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return meilisearch_installer_global[args.name] or { - println(meilisearch_installer_global) - // bug if we get here because should be in globals - panic('could not get config for meilisearch_installer with name, is bug:${args.name}') + return error('could not get config for meilisearch_installer with name:meilisearch_installer') } } // register the config for the future pub fn set(o MeilisearchInstaller) ! { set_in_mem(o)! + meilisearch_installer_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('meilisearch_installer', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:meilisearch_installer', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('meilisearch_installer', args.name) + mut r := context.redis()! + return r.hexists('context:meilisearch_installer', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('meilisearch_installer', args.name)! - if args.name in meilisearch_installer_global { - // del meilisearch_installer_global[args.name] + mut r := context.redis()! + r.hdel('context:meilisearch_installer', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&MeilisearchInstaller { + mut res := []&MeilisearchInstaller{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + meilisearch_installer_global = map[string]&MeilisearchInstaller{} + meilisearch_installer_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:meilisearch_installer')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in meilisearch_installer_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o MeilisearchInstaller) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'meilisearch_installer.') { + return + } mut install_actions := plbook.find(filter: 'meilisearch_installer.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'meilisearch_installer.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self MeilisearchInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -260,10 +304,3 @@ pub fn (mut self MeilisearchInstaller) destroy() ! { pub fn switch(name string) { meilisearch_installer_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/db/postgresql/postgresql_actions.v b/lib/installers/db/postgresql/postgresql_actions.v index c8102d1d..ca097664 100644 --- a/lib/installers/db/postgresql/postgresql_actions.v +++ b/lib/installers/db/postgresql/postgresql_actions.v @@ -3,23 +3,25 @@ module postgresql import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.installers.virt.podman as podman_installer -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut cfg := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} cmd := " mkdir -p ${cfg.volume_path} podman run --name ${cfg.container_name} -e POSTGRES_USER=${cfg.user} -e POSTGRES_PASSWORD=\"${cfg.password}\" -v ${cfg.volume_path}:/var/lib/postgresql/data -p ${cfg.port}:5432 --health-cmd=\"pg_isready -U ${cfg.user}\" postgres:latest " - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'postgresql' cmd: cmd startuptype: .zinit } + return res } diff --git a/lib/installers/db/postgresql/postgresql_factory_.v b/lib/installers/db/postgresql/postgresql_factory_.v index 54491266..70acf0eb 100644 --- a/lib/installers/db/postgresql/postgresql_factory_.v +++ b/lib/installers/db/postgresql/postgresql_factory_.v @@ -3,75 +3,106 @@ module postgresql import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - postgresql_global map[string]&Postgresql - postgresql_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&Postgresql { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&Postgresql { mut obj := Postgresql{ name: args.name } - if args.name !in postgresql_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&Postgresql { + mut context := base.context()! + postgresql_default = args.name + if args.fromdb || args.name !in postgresql_global { + mut r := context.redis()! + if r.hexists('context:postgresql', args.name)! { + data := r.hget('context:postgresql', args.name)! + if data.len == 0 { + return error('Postgresql with name: postgresql does not exist, prob bug.') + } + mut obj := json.decode(Postgresql, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('postgresql', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("Postgresql with name 'postgresql' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return postgresql_global[args.name] or { - println(postgresql_global) - // bug if we get here because should be in globals - panic('could not get config for postgresql with name, is bug:${args.name}') + return error('could not get config for postgresql with name:postgresql') } } // register the config for the future pub fn set(o Postgresql) ! { set_in_mem(o)! + postgresql_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('postgresql', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:postgresql', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('postgresql', args.name) + mut r := context.redis()! + return r.hexists('context:postgresql', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('postgresql', args.name)! - if args.name in postgresql_global { - // del postgresql_global[args.name] + mut r := context.redis()! + r.hdel('context:postgresql', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&Postgresql { + mut res := []&Postgresql{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + postgresql_global = map[string]&Postgresql{} + postgresql_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:postgresql')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in postgresql_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o Postgresql) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'postgresql.') { + return + } mut install_actions := plbook.find(filter: 'postgresql.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'postgresql.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self Postgresql) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self Postgresql) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self Postgresql) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -253,12 +290,4 @@ pub fn (mut self Postgresql) destroy() ! { // switch instance to be used for postgresql pub fn switch(name string) { - postgresql_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/db/qdrant_installer/qdrant_installer_actions.v b/lib/installers/db/qdrant_installer/qdrant_installer_actions.v index c2d767a8..209178fe 100644 --- a/lib/installers/db/qdrant_installer/qdrant_installer_actions.v +++ b/lib/installers/db/qdrant_installer/qdrant_installer_actions.v @@ -1,17 +1,19 @@ module qdrant_installer import freeflowuniverse.herolib.ui.console -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import os -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'qdrant' cmd: 'sleep 5 && qdrant --config-path ${os.home_dir()}/hero/var/qdrant/config.yaml' startuptype: .zinit } + return res } diff --git a/lib/installers/db/qdrant_installer/qdrant_installer_factory_.v b/lib/installers/db/qdrant_installer/qdrant_installer_factory_.v index bfda48a8..5113664e 100644 --- a/lib/installers/db/qdrant_installer/qdrant_installer_factory_.v +++ b/lib/installers/db/qdrant_installer/qdrant_installer_factory_.v @@ -3,8 +3,8 @@ module qdrant_installer import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&QDrant { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&QDrant { mut obj := QDrant{ name: args.name } - if args.name !in qdrant_installer_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&QDrant { + mut context := base.context()! + qdrant_installer_default = args.name + if args.fromdb || args.name !in qdrant_installer_global { + mut r := context.redis()! + if r.hexists('context:qdrant_installer', args.name)! { + data := r.hget('context:qdrant_installer', args.name)! + if data.len == 0 { + return error('QDrant with name: qdrant_installer does not exist, prob bug.') + } + mut obj := json.decode(QDrant, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('qdrant_installer', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("QDrant with name 'qdrant_installer' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return qdrant_installer_global[args.name] or { - println(qdrant_installer_global) - // bug if we get here because should be in globals - panic('could not get config for qdrant_installer with name, is bug:${args.name}') + return error('could not get config for qdrant_installer with name:qdrant_installer') } } // register the config for the future pub fn set(o QDrant) ! { set_in_mem(o)! + qdrant_installer_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('qdrant_installer', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:qdrant_installer', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('qdrant_installer', args.name) + mut r := context.redis()! + return r.hexists('context:qdrant_installer', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('qdrant_installer', args.name)! - if args.name in qdrant_installer_global { - // del qdrant_installer_global[args.name] + mut r := context.redis()! + r.hdel('context:qdrant_installer', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&QDrant { + mut res := []&QDrant{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + qdrant_installer_global = map[string]&QDrant{} + qdrant_installer_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:qdrant_installer')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in qdrant_installer_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o QDrant) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'qdrant_installer.') { + return + } mut install_actions := plbook.find(filter: 'qdrant_installer.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'qdrant_installer.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self QDrant) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -260,10 +304,3 @@ pub fn (mut self QDrant) destroy() ! { pub fn switch(name string) { qdrant_installer_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/db/zerodb/zerodb_actions.v b/lib/installers/db/zerodb/zerodb_actions.v index 226e9270..1564b0ba 100644 --- a/lib/installers/db/zerodb/zerodb_actions.v +++ b/lib/installers/db/zerodb/zerodb_actions.v @@ -3,7 +3,7 @@ module zerodb import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.develop.gittools import freeflowuniverse.herolib.installers.base @@ -14,19 +14,21 @@ import rand import os import time -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut cfg := get()! mut cmd := 'zdb --socket ${os.home_dir()}/var/zdb.sock --port ${cfg.port} --admin ${cfg.secret} --data ${cfg.datadir} --index ${cfg.indexdir} --dualnet --protect --rotate ${cfg.rotateperiod}' if cfg.sequential { cmd += ' --mode seq' } - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'zdb' cmd: cmd startuptype: .zinit } + return res } diff --git a/lib/installers/db/zerodb/zerodb_factory_.v b/lib/installers/db/zerodb/zerodb_factory_.v index a7f274d0..89e823fe 100644 --- a/lib/installers/db/zerodb/zerodb_factory_.v +++ b/lib/installers/db/zerodb/zerodb_factory_.v @@ -3,75 +3,106 @@ module zerodb import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - zerodb_global map[string]&ZeroDB - zerodb_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&ZeroDB { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&ZeroDB { mut obj := ZeroDB{ name: args.name } - if args.name !in zerodb_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&ZeroDB { + mut context := base.context()! + zerodb_default = args.name + if args.fromdb || args.name !in zerodb_global { + mut r := context.redis()! + if r.hexists('context:zerodb', args.name)! { + data := r.hget('context:zerodb', args.name)! + if data.len == 0 { + return error('ZeroDB with name: zerodb does not exist, prob bug.') + } + mut obj := json.decode(ZeroDB, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('zerodb', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("ZeroDB with name 'zerodb' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return zerodb_global[args.name] or { - println(zerodb_global) - // bug if we get here because should be in globals - panic('could not get config for zerodb with name, is bug:${args.name}') + return error('could not get config for zerodb with name:zerodb') } } // register the config for the future pub fn set(o ZeroDB) ! { set_in_mem(o)! + zerodb_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('zerodb', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:zerodb', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('zerodb', args.name) + mut r := context.redis()! + return r.hexists('context:zerodb', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('zerodb', args.name)! - if args.name in zerodb_global { - // del zerodb_global[args.name] + mut r := context.redis()! + r.hdel('context:zerodb', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&ZeroDB { + mut res := []&ZeroDB{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + zerodb_global = map[string]&ZeroDB{} + zerodb_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:zerodb')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in zerodb_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o ZeroDB) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'zerodb.') { + return + } mut install_actions := plbook.find(filter: 'zerodb.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'zerodb.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self ZeroDB) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self ZeroDB) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self ZeroDB) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -258,12 +295,4 @@ pub fn (mut self ZeroDB) destroy() ! { // switch instance to be used for zerodb pub fn switch(name string) { - zerodb_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/db/zerofs/zerofs_actions.v b/lib/installers/db/zerofs/zerofs_actions.v index c36514ef..8284594e 100644 --- a/lib/installers/db/zerofs/zerofs_actions.v +++ b/lib/installers/db/zerofs/zerofs_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'zerofs' // cmd: 'zerofs server' // env: { diff --git a/lib/installers/db/zerofs/zerofs_factory_.v b/lib/installers/db/zerofs/zerofs_factory_.v index 82b05801..7f5fd8e0 100644 --- a/lib/installers/db/zerofs/zerofs_factory_.v +++ b/lib/installers/db/zerofs/zerofs_factory_.v @@ -2,28 +2,34 @@ module zerofs import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - zerofs_global map[string]&ZeroFS - zerofs_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&ZeroFS { +pub fn new(args ArgsGet) !&ZeroFS { return &ZeroFS{} } +pub fn get(args ArgsGet) !&ZeroFS { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'zerofs.') { + return + } + mut install_actions := plbook.find(filter: 'zerofs.configure')! + if install_actions.len > 0 { + return error("can't configure zerofs, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'zerofs.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self ZeroFS) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self ZeroFS) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self ZeroFS) destroy() ! { // switch instance to be used for zerofs pub fn switch(name string) { - zerofs_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/infra/coredns/coredns_actions.v b/lib/installers/infra/coredns/coredns_actions.v index d77fc457..54442c6d 100644 --- a/lib/installers/infra/coredns/coredns_actions.v +++ b/lib/installers/infra/coredns/coredns_actions.v @@ -6,20 +6,22 @@ import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.core import freeflowuniverse.herolib.develop.gittools -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.core.httpconnection import freeflowuniverse.herolib.installers.lang.golang import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut args := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} cmd := "coredns -conf '${args.config_path}'" - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'coredns' cmd: cmd } + return res } diff --git a/lib/installers/infra/coredns/coredns_factory_.v b/lib/installers/infra/coredns/coredns_factory_.v index b3ebee54..f795ef2e 100644 --- a/lib/installers/infra/coredns/coredns_factory_.v +++ b/lib/installers/infra/coredns/coredns_factory_.v @@ -3,75 +3,106 @@ module coredns import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - coredns_global map[string]&CoreDNS - coredns_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&CoreDNS { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&CoreDNS { mut obj := CoreDNS{ name: args.name } - if args.name !in coredns_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&CoreDNS { + mut context := base.context()! + coredns_default = args.name + if args.fromdb || args.name !in coredns_global { + mut r := context.redis()! + if r.hexists('context:coredns', args.name)! { + data := r.hget('context:coredns', args.name)! + if data.len == 0 { + return error('CoreDNS with name: coredns does not exist, prob bug.') + } + mut obj := json.decode(CoreDNS, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('coredns', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("CoreDNS with name 'coredns' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return coredns_global[args.name] or { - println(coredns_global) - // bug if we get here because should be in globals - panic('could not get config for coredns with name, is bug:${args.name}') + return error('could not get config for coredns with name:coredns') } } // register the config for the future pub fn set(o CoreDNS) ! { set_in_mem(o)! + coredns_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('coredns', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:coredns', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('coredns', args.name) + mut r := context.redis()! + return r.hexists('context:coredns', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('coredns', args.name)! - if args.name in coredns_global { - // del coredns_global[args.name] + mut r := context.redis()! + r.hdel('context:coredns', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&CoreDNS { + mut res := []&CoreDNS{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + coredns_global = map[string]&CoreDNS{} + coredns_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:coredns')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in coredns_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o CoreDNS) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'coredns.') { + return + } mut install_actions := plbook.find(filter: 'coredns.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'coredns.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self CoreDNS) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self CoreDNS) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self CoreDNS) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -258,12 +295,4 @@ pub fn (mut self CoreDNS) destroy() ! { // switch instance to be used for coredns pub fn switch(name string) { - coredns_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/infra/gitea/gitea_actions.v b/lib/installers/infra/gitea/gitea_actions.v index ca9b4b7e..56202590 100644 --- a/lib/installers/infra/gitea/gitea_actions.v +++ b/lib/installers/infra/gitea/gitea_actions.v @@ -5,7 +5,7 @@ import freeflowuniverse.herolib.core import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.installers.ulist -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import os fn installed() !bool { @@ -30,16 +30,12 @@ fn install() ! { mut url := '' if core.is_linux_arm()! { - // https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-linux-arm64.xz url = '${baseurl}-linux-arm64.xz' } else if core.is_linux_intel()! { - // https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-linux-amd64.xz url = '${baseurl}-linux-amd64.xz' } else if core.is_osx_arm()! { - // https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-darwin-10.12-arm64.xz url = '${baseurl}-darwin-10.12-arm64.xz' } else if core.is_osx_intel()! { - // https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-darwin-10.12-amd64.xz url = '${baseurl}-darwin-10.12-amd64.xz' } else { return error('unsported platform') @@ -90,10 +86,11 @@ fn ulist_get() !ulist.UList { // uploads to S3 server if configured fn upload() ! {} -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut cfg := get()! - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'gitea' cmd: 'gitea server' env: { @@ -101,11 +98,12 @@ fn startupcmd() ![]zinit.ZProcessNewArgs { 'GITEA_CONFIG': cfg.config_path() } } + return res - // mut res := []zinit.ZProcessNewArgs{} + // mut res := []startupmanager.ZProcessNewArgs{} // cfg := get()! - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'gitea' // // cmd: 'GITEA_WORK_DIR=${cfg.path} sudo -u git /var/lib/git/gitea web -c /etc/gitea_app.ini' // cmd: ' @@ -151,7 +149,7 @@ fn startupcmd() ![]zinit.ZProcessNewArgs { // ' // workdir: cfg.path // } - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'restart_gitea' // cmd: 'sleep 30 && zinit restart gitea && exit 1' // after: ['gitea'] diff --git a/lib/installers/infra/gitea/gitea_factory_.v b/lib/installers/infra/gitea/gitea_factory_.v index 0c4846b7..b3a62150 100644 --- a/lib/installers/infra/gitea/gitea_factory_.v +++ b/lib/installers/infra/gitea/gitea_factory_.v @@ -3,75 +3,106 @@ module gitea import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - gitea_global map[string]&GiteaServer - gitea_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&GiteaServer { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&GiteaServer { mut obj := GiteaServer{ name: args.name } - if args.name !in gitea_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&GiteaServer { + mut context := base.context()! + gitea_default = args.name + if args.fromdb || args.name !in gitea_global { + mut r := context.redis()! + if r.hexists('context:gitea', args.name)! { + data := r.hget('context:gitea', args.name)! + if data.len == 0 { + return error('GiteaServer with name: gitea does not exist, prob bug.') + } + mut obj := json.decode(GiteaServer, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('gitea', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("GiteaServer with name 'gitea' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return gitea_global[args.name] or { - println(gitea_global) - // bug if we get here because should be in globals - panic('could not get config for gitea with name, is bug:${args.name}') + return error('could not get config for gitea with name:gitea') } } // register the config for the future pub fn set(o GiteaServer) ! { set_in_mem(o)! + gitea_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('gitea', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:gitea', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('gitea', args.name) + mut r := context.redis()! + return r.hexists('context:gitea', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('gitea', args.name)! - if args.name in gitea_global { - // del gitea_global[args.name] + mut r := context.redis()! + r.hdel('context:gitea', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&GiteaServer { + mut res := []&GiteaServer{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + gitea_global = map[string]&GiteaServer{} + gitea_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:gitea')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in gitea_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o GiteaServer) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'gitea.') { + return + } mut install_actions := plbook.find(filter: 'gitea.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'gitea.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self GiteaServer) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self GiteaServer) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self GiteaServer) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -258,12 +295,4 @@ pub fn (mut self GiteaServer) destroy() ! { // switch instance to be used for gitea pub fn switch(name string) { - gitea_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/infra/gitea/gitea_model.v b/lib/installers/infra/gitea/gitea_model.v index 1ad2b4bd..c30c8251 100644 --- a/lib/installers/infra/gitea/gitea_model.v +++ b/lib/installers/infra/gitea/gitea_model.v @@ -10,7 +10,7 @@ import freeflowuniverse.herolib.clients.mailclient import freeflowuniverse.herolib.clients.postgresql_client import rand -pub const version = '1.23.3' +pub const version = '1.24.5' const singleton = true const default = false diff --git a/lib/installers/infra/livekit/livekit_actions.v b/lib/installers/infra/livekit/livekit_actions.v index 408aab56..9ede5875 100644 --- a/lib/installers/infra/livekit/livekit_actions.v +++ b/lib/installers/infra/livekit/livekit_actions.v @@ -1,7 +1,7 @@ module livekit import freeflowuniverse.herolib.osal.core as osal -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.installers.ulist @@ -45,10 +45,11 @@ fn generate_keys() ! { obj.apisecret = api_secret } -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} mut installer := get()! - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'livekit' cmd: 'livekit-server --config ${installer.configpath} --bind 0.0.0.0' startuptype: .zinit diff --git a/lib/installers/infra/livekit/livekit_factory_.v b/lib/installers/infra/livekit/livekit_factory_.v index 906b3d88..d0c17d09 100644 --- a/lib/installers/infra/livekit/livekit_factory_.v +++ b/lib/installers/infra/livekit/livekit_factory_.v @@ -3,8 +3,8 @@ module livekit import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&LivekitServer { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&LivekitServer { mut obj := LivekitServer{ name: args.name } - if args.name !in livekit_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&LivekitServer { + mut context := base.context()! + livekit_default = args.name + if args.fromdb || args.name !in livekit_global { + mut r := context.redis()! + if r.hexists('context:livekit', args.name)! { + data := r.hget('context:livekit', args.name)! + if data.len == 0 { + return error('LivekitServer with name: livekit does not exist, prob bug.') + } + mut obj := json.decode(LivekitServer, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('livekit', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("LivekitServer with name 'livekit' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return livekit_global[args.name] or { - println(livekit_global) - // bug if we get here because should be in globals - panic('could not get config for livekit with name, is bug:${args.name}') + return error('could not get config for livekit with name:livekit') } } // register the config for the future pub fn set(o LivekitServer) ! { set_in_mem(o)! + livekit_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('livekit', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:livekit', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('livekit', args.name) + mut r := context.redis()! + return r.hexists('context:livekit', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('livekit', args.name)! - if args.name in livekit_global { - // del livekit_global[args.name] + mut r := context.redis()! + r.hdel('context:livekit', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&LivekitServer { + mut res := []&LivekitServer{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + livekit_global = map[string]&LivekitServer{} + livekit_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:livekit')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in livekit_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o LivekitServer) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'livekit.') { + return + } mut install_actions := plbook.find(filter: 'livekit.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'livekit.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self LivekitServer) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -255,10 +299,3 @@ pub fn (mut self LivekitServer) destroy() ! { pub fn switch(name string) { livekit_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/infra/screen/screen_factory_.v b/lib/installers/infra/screen/screen_factory_.v index 074f110f..97620f39 100644 --- a/lib/installers/infra/screen/screen_factory_.v +++ b/lib/installers/infra/screen/screen_factory_.v @@ -2,8 +2,8 @@ module screen import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( screen_global map[string]&Screen @@ -15,14 +15,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Screen { +pub fn new(args ArgsGet) !&Screen { return &Screen{} } +pub fn get(args ArgsGet) !&Screen { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'screen.') { + return + } + mut install_actions := plbook.find(filter: 'screen.configure')! + if install_actions.len > 0 { + return error("can't configure screen, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'screen.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +55,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -88,10 +77,3 @@ pub fn (mut self Screen) destroy() ! { pub fn switch(name string) { screen_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/infra/zinit_installer/zinit_installer_actions.v b/lib/installers/infra/zinit_installer/zinit_installer_actions.v index b349bbae..e54d8b0d 100644 --- a/lib/installers/infra/zinit_installer/zinit_installer_actions.v +++ b/lib/installers/infra/zinit_installer/zinit_installer_actions.v @@ -6,18 +6,28 @@ import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.develop.gittools import freeflowuniverse.herolib.core import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit as zinit_module import freeflowuniverse.herolib.installers.ulist +import freeflowuniverse.herolib.installers.lang.rust +import freeflowuniverse.herolib.osal.startupmanager import os -fn startupcmd() ![]zinit_module.ZProcessNewArgs { - mut res := []zinit_module.ZProcessNewArgs{} - res << zinit_module.ZProcessNewArgs{ - name: 'zinit' - cmd: '/usr/local/bin/zinit init' - startuptype: .systemd - start: true - restart: true +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} + if core.is_linux()! { + res << startupmanager.ZProcessNewArgs{ + name: 'zinit' + cmd: '/usr/local/bin/zinit init' + startuptype: .systemd + start: true + restart: true + } + } else { + res << startupmanager.ZProcessNewArgs{ + name: 'zinit' + cmd: '~/hero/bin/zinit init --config ~/hero/cfg/zinit' + startuptype: .screen + start: true + } } return res } @@ -70,25 +80,29 @@ fn upload() ! {} fn install() ! { console.print_header('install zinit') - if !core.is_linux()! { - return error('only support linux for now') + baseurl := 'https://github.com/threefoldtech/zinit/releases/download/v${version}/zinit-' + + mut url := '' + + if core.is_linux_intel()! { + url = '${baseurl}linux-x86_64' + } else if core.is_osx_arm()! { + url = '${baseurl}macos-aarch64' + } else if core.is_osx_intel()! { + url = '${baseurl}macos-x86_64' + } else { + return error('unsupported platform to install zinit') } - release_url := 'https://github.com/threefoldtech/zinit/releases/download/v0.2.25/zinit' - mut dest := osal.download( - url: release_url - minsize_kb: 2000 - reset: true + url: url + minsize_kb: 4000 )! osal.cmd_add( cmdname: 'zinit' source: dest.path )! - - osal.dir_ensure('/etc/zinit')! - console.print_header('install zinit done') } fn build() ! { @@ -96,7 +110,8 @@ fn build() ! { return error('only support linux for now') } - // rust.install() + mut i := rust.new()! + i.install()! // install zinit if it was already done will return true console.print_header('build zinit') @@ -125,8 +140,12 @@ fn build() ! { } fn destroy() ! { - mut systemdfactory := systemd.new()! - systemdfactory.destroy('zinit') or { return error('Could not destroy zinit due to: ${err}') } + if core.is_linux()! { + mut systemdfactory := systemd.new()! + systemdfactory.destroy('zinit') or { + return error('Could not destroy zinit due to: ${err}') + } + } osal.process_kill_recursive(name: 'zinit') or { return error('Could not kill zinit due to: ${err}') diff --git a/lib/installers/infra/zinit_installer/zinit_installer_factory_.v b/lib/installers/infra/zinit_installer/zinit_installer_factory_.v index dfb22f93..14b86a53 100644 --- a/lib/installers/infra/zinit_installer/zinit_installer_factory_.v +++ b/lib/installers/infra/zinit_installer/zinit_installer_factory_.v @@ -2,28 +2,34 @@ module zinit_installer import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - zinit_installer_global map[string]&ZinitInstaller - zinit_installer_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&ZinitInstaller { +pub fn new(args ArgsGet) !&ZinitInstaller { return &ZinitInstaller{} } +pub fn get(args ArgsGet) !&ZinitInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'zinit_installer.') { + return + } + mut install_actions := plbook.find(filter: 'zinit_installer.configure')! + if install_actions.len > 0 { + return error("can't configure zinit_installer, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'zinit_installer.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self ZinitInstaller) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self ZinitInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self ZinitInstaller) destroy() ! { // switch instance to be used for zinit_installer pub fn switch(name string) { - zinit_installer_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/infra/zinit_installer/zinit_installer_model.v b/lib/installers/infra/zinit_installer/zinit_installer_model.v index 458d0bc9..5e0f252b 100644 --- a/lib/installers/infra/zinit_installer/zinit_installer_model.v +++ b/lib/installers/infra/zinit_installer/zinit_installer_model.v @@ -2,7 +2,7 @@ module zinit_installer import freeflowuniverse.herolib.data.encoderhero -pub const version = '0.0.0' +pub const version = '0.2.25' const singleton = true const default = true @@ -23,14 +23,3 @@ fn obj_init(mycfg_ ZinitInstaller) !ZinitInstaller { fn configure() ! { // mut installer := get()! } - -/////////////NORMALLY NO NEED TO TOUCH - -pub fn heroscript_dumps(obj ZinitInstaller) !string { - return encoderhero.encode[ZinitInstaller](obj)! -} - -pub fn heroscript_loads(heroscript string) !ZinitInstaller { - mut obj := encoderhero.decode[ZinitInstaller](heroscript)! - return obj -} diff --git a/lib/installers/lang/golang/golang_factory_.v b/lib/installers/lang/golang/golang_factory_.v index 023a4b89..c2039dd4 100644 --- a/lib/installers/lang/golang/golang_factory_.v +++ b/lib/installers/lang/golang/golang_factory_.v @@ -2,27 +2,33 @@ module golang import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - golang_global map[string]&GolangInstaller - golang_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&GolangInstaller { +pub fn new(args ArgsGet) !&GolangInstaller { return &GolangInstaller{} } +pub fn get(args ArgsGet) !&GolangInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'golang.') { + return + } + mut install_actions := plbook.find(filter: 'golang.configure')! + if install_actions.len > 0 { + return error("can't configure golang, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'golang.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -91,12 +75,4 @@ pub fn (mut self GolangInstaller) destroy() ! { // switch instance to be used for golang pub fn switch(name string) { - golang_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/lang/nodejs/nodejs_factory_.v b/lib/installers/lang/nodejs/nodejs_factory_.v index 09f9508c..4227d85d 100644 --- a/lib/installers/lang/nodejs/nodejs_factory_.v +++ b/lib/installers/lang/nodejs/nodejs_factory_.v @@ -2,27 +2,33 @@ module nodejs import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - nodejs_global map[string]&NodeJS - nodejs_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&NodeJS { +pub fn new(args ArgsGet) !&NodeJS { return &NodeJS{} } +pub fn get(args ArgsGet) !&NodeJS { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'nodejs.') { + return + } + mut install_actions := plbook.find(filter: 'nodejs.configure')! + if install_actions.len > 0 { + return error("can't configure nodejs, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'nodejs.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self NodeJS) destroy() ! { // switch instance to be used for nodejs pub fn switch(name string) { - nodejs_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/lang/python/python_factory_.v b/lib/installers/lang/python/python_factory_.v index 24a37eab..c02f7dc8 100644 --- a/lib/installers/lang/python/python_factory_.v +++ b/lib/installers/lang/python/python_factory_.v @@ -2,27 +2,33 @@ module python import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - python_global map[string]&PythonInstaller - python_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&PythonInstaller { +pub fn new(args ArgsGet) !&PythonInstaller { return &PythonInstaller{} } +pub fn get(args ArgsGet) !&PythonInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'python.') { + return + } + mut install_actions := plbook.find(filter: 'python.configure')! + if install_actions.len > 0 { + return error("can't configure python, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'python.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self PythonInstaller) destroy() ! { // switch instance to be used for python pub fn switch(name string) { - python_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/lang/rust/rust_factory_.v b/lib/installers/lang/rust/rust_factory_.v index 6137693f..e0a80a7e 100644 --- a/lib/installers/lang/rust/rust_factory_.v +++ b/lib/installers/lang/rust/rust_factory_.v @@ -2,27 +2,33 @@ module rust import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - rust_global map[string]&RustInstaller - rust_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&RustInstaller { +pub fn new(args ArgsGet) !&RustInstaller { return &RustInstaller{} } +pub fn get(args ArgsGet) !&RustInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'rust.') { + return + } + mut install_actions := plbook.find(filter: 'rust.configure')! + if install_actions.len > 0 { + return error("can't configure rust, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'rust.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self RustInstaller) destroy() ! { // switch instance to be used for rust pub fn switch(name string) { - rust_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/net/mycelium_installer/mycelium_installer_actions.v b/lib/installers/net/mycelium_installer/mycelium_installer_actions.v index d6eef8cf..8ee88310 100644 --- a/lib/installers/net/mycelium_installer/mycelium_installer_actions.v +++ b/lib/installers/net/mycelium_installer/mycelium_installer_actions.v @@ -8,26 +8,26 @@ import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.installers.infra.zinit_installer import freeflowuniverse.herolib.clients.mycelium import freeflowuniverse.herolib.develop.gittools -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.rust import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} mut peers_str := installer.peers.join(' ') mut tun_name := 'tun${installer.tun_nr}' - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'mycelium' startuptype: .zinit cmd: 'mycelium --key-file ${osal.hero_path()!}/cfg/priv_key.bin --peers ${peers_str} --tun-name ${tun_name}' - env: { - 'HOME': '/root' + env: { + 'HOME': os.home_dir() } - } return res } diff --git a/lib/installers/net/mycelium_installer/mycelium_installer_factory_.v b/lib/installers/net/mycelium_installer/mycelium_installer_factory_.v index 7a3ba437..0f72cb9e 100644 --- a/lib/installers/net/mycelium_installer/mycelium_installer_factory_.v +++ b/lib/installers/net/mycelium_installer/mycelium_installer_factory_.v @@ -3,8 +3,8 @@ module mycelium_installer import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&MyceliumInstaller { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&MyceliumInstaller { mut obj := MyceliumInstaller{ name: args.name } - if args.name !in mycelium_installer_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&MyceliumInstaller { + mut context := base.context()! + mycelium_installer_default = args.name + if args.fromdb || args.name !in mycelium_installer_global { + mut r := context.redis()! + if r.hexists('context:mycelium_installer', args.name)! { + data := r.hget('context:mycelium_installer', args.name)! + if data.len == 0 { + return error('MyceliumInstaller with name: mycelium_installer does not exist, prob bug.') + } + mut obj := json.decode(MyceliumInstaller, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('mycelium_installer', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("MyceliumInstaller with name 'mycelium_installer' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return mycelium_installer_global[args.name] or { - println(mycelium_installer_global) - // bug if we get here because should be in globals - panic('could not get config for mycelium_installer with name, is bug:${args.name}') + return error('could not get config for mycelium_installer with name:mycelium_installer') } } // register the config for the future pub fn set(o MyceliumInstaller) ! { set_in_mem(o)! + mycelium_installer_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('mycelium_installer', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:mycelium_installer', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('mycelium_installer', args.name) + mut r := context.redis()! + return r.hexists('context:mycelium_installer', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('mycelium_installer', args.name)! - if args.name in mycelium_installer_global { - // del mycelium_installer_global[args.name] + mut r := context.redis()! + r.hdel('context:mycelium_installer', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&MyceliumInstaller { + mut res := []&MyceliumInstaller{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + mycelium_installer_global = map[string]&MyceliumInstaller{} + mycelium_installer_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:mycelium_installer')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in mycelium_installer_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o MyceliumInstaller) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'mycelium_installer.') { + return + } mut install_actions := plbook.find(filter: 'mycelium_installer.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'mycelium_installer.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self MyceliumInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -260,10 +304,3 @@ pub fn (mut self MyceliumInstaller) destroy() ! { pub fn switch(name string) { mycelium_installer_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/net/wireguard_installer/wireguard_installer_factory_.v b/lib/installers/net/wireguard_installer/wireguard_installer_factory_.v index a3e9cddb..90876b5b 100644 --- a/lib/installers/net/wireguard_installer/wireguard_installer_factory_.v +++ b/lib/installers/net/wireguard_installer/wireguard_installer_factory_.v @@ -2,8 +2,8 @@ module wireguard_installer import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( wireguard_installer_global map[string]&WireGuard @@ -15,14 +15,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&WireGuard { +pub fn new(args ArgsGet) !&WireGuard { return &WireGuard{} } +pub fn get(args ArgsGet) !&WireGuard { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'wireguard_installer.') { + return + } + mut install_actions := plbook.find(filter: 'wireguard_installer.configure')! + if install_actions.len > 0 { + return error("can't configure wireguard_installer, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'wireguard_installer.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +55,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -88,10 +77,3 @@ pub fn (mut self WireGuard) destroy() ! { pub fn switch(name string) { wireguard_installer_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/net/yggdrasil/yggdrasil_actions.v b/lib/installers/net/yggdrasil/yggdrasil_actions.v index 6a191e31..08f34df2 100644 --- a/lib/installers/net/yggdrasil/yggdrasil_actions.v +++ b/lib/installers/net/yggdrasil/yggdrasil_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'yggdrasil' // cmd: 'yggdrasil server' // env: { diff --git a/lib/installers/net/yggdrasil/yggdrasil_factory_.v b/lib/installers/net/yggdrasil/yggdrasil_factory_.v index f2ba112c..982f0f19 100644 --- a/lib/installers/net/yggdrasil/yggdrasil_factory_.v +++ b/lib/installers/net/yggdrasil/yggdrasil_factory_.v @@ -2,28 +2,34 @@ module yggdrasil import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - yggdrasil_global map[string]&YggdrasilInstaller - yggdrasil_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&YggdrasilInstaller { +pub fn new(args ArgsGet) !&YggdrasilInstaller { return &YggdrasilInstaller{} } +pub fn get(args ArgsGet) !&YggdrasilInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'yggdrasil.') { + return + } + mut install_actions := plbook.find(filter: 'yggdrasil.configure')! + if install_actions.len > 0 { + return error("can't configure yggdrasil, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'yggdrasil.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self YggdrasilInstaller) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self YggdrasilInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self YggdrasilInstaller) destroy() ! { // switch instance to be used for yggdrasil pub fn switch(name string) { - yggdrasil_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/actrunner/actrunner_actions.v b/lib/installers/sysadmintools/actrunner/actrunner_actions.v index 65f78458..16886a38 100644 --- a/lib/installers/sysadmintools/actrunner/actrunner_actions.v +++ b/lib/installers/sysadmintools/actrunner/actrunner_actions.v @@ -2,15 +2,16 @@ module actrunner import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.core import os -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'actrunner' cmd: 'actrunner daemon' startuptype: .zinit diff --git a/lib/installers/sysadmintools/actrunner/actrunner_factory_.v b/lib/installers/sysadmintools/actrunner/actrunner_factory_.v index be54d827..12b93b6b 100644 --- a/lib/installers/sysadmintools/actrunner/actrunner_factory_.v +++ b/lib/installers/sysadmintools/actrunner/actrunner_factory_.v @@ -2,28 +2,34 @@ module actrunner import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - actrunner_global map[string]&ActRunner - actrunner_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&ActRunner { +pub fn new(args ArgsGet) !&ActRunner { return &ActRunner{} } +pub fn get(args ArgsGet) !&ActRunner { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'actrunner.') { + return + } + mut install_actions := plbook.find(filter: 'actrunner.configure')! + if install_actions.len > 0 { + return error("can't configure actrunner, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'actrunner.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self ActRunner) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self ActRunner) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self ActRunner) destroy() ! { // switch instance to be used for actrunner pub fn switch(name string) { - actrunner_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/b2/b2_factory_.v b/lib/installers/sysadmintools/b2/b2_factory_.v index 27d828df..1500434b 100644 --- a/lib/installers/sysadmintools/b2/b2_factory_.v +++ b/lib/installers/sysadmintools/b2/b2_factory_.v @@ -2,27 +2,33 @@ module b2 import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - b2_global map[string]&BackBase - b2_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&BackBase { +pub fn new(args ArgsGet) !&BackBase { return &BackBase{} } +pub fn get(args ArgsGet) !&BackBase { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'b2.') { + return + } + mut install_actions := plbook.find(filter: 'b2.configure')! + if install_actions.len > 0 { + return error("can't configure b2, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'b2.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self BackBase) destroy() ! { // switch instance to be used for b2 pub fn switch(name string) { - b2_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/daguserver/daguserver_actions.v b/lib/installers/sysadmintools/daguserver/daguserver_actions.v index 1dcc0a92..e0985752 100644 --- a/lib/installers/sysadmintools/daguserver/daguserver_actions.v +++ b/lib/installers/sysadmintools/daguserver/daguserver_actions.v @@ -7,14 +7,15 @@ import freeflowuniverse.herolib.core import freeflowuniverse.herolib.core.httpconnection import freeflowuniverse.herolib.installers.ulist // import freeflowuniverse.herolib.develop.gittools -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import os -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} mut cfg := get()! - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'dagu' cmd: 'dagu server' env: { @@ -23,7 +24,8 @@ fn startupcmd() ![]zinit.ZProcessNewArgs { } } - res << zinit.ZProcessNewArgs{ + res << startupmanager.ZProcessNewArgs + { name: 'dagu_scheduler' cmd: 'dagu scheduler' env: { diff --git a/lib/installers/sysadmintools/daguserver/daguserver_factory_.v b/lib/installers/sysadmintools/daguserver/daguserver_factory_.v index 95b00690..1a1f81d2 100644 --- a/lib/installers/sysadmintools/daguserver/daguserver_factory_.v +++ b/lib/installers/sysadmintools/daguserver/daguserver_factory_.v @@ -3,75 +3,106 @@ module daguserver import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - daguserver_global map[string]&DaguInstaller - daguserver_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&DaguInstaller { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&DaguInstaller { mut obj := DaguInstaller{ name: args.name } - if args.name !in daguserver_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&DaguInstaller { + mut context := base.context()! + daguserver_default = args.name + if args.fromdb || args.name !in daguserver_global { + mut r := context.redis()! + if r.hexists('context:daguserver', args.name)! { + data := r.hget('context:daguserver', args.name)! + if data.len == 0 { + return error('DaguInstaller with name: daguserver does not exist, prob bug.') + } + mut obj := json.decode(DaguInstaller, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('daguserver', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("DaguInstaller with name 'daguserver' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return daguserver_global[args.name] or { - println(daguserver_global) - // bug if we get here because should be in globals - panic('could not get config for daguserver with name, is bug:${args.name}') + return error('could not get config for daguserver with name:daguserver') } } // register the config for the future pub fn set(o DaguInstaller) ! { set_in_mem(o)! + daguserver_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('daguserver', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:daguserver', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('daguserver', args.name) + mut r := context.redis()! + return r.hexists('context:daguserver', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('daguserver', args.name)! - if args.name in daguserver_global { - // del daguserver_global[args.name] + mut r := context.redis()! + r.hdel('context:daguserver', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&DaguInstaller { + mut res := []&DaguInstaller{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + daguserver_global = map[string]&DaguInstaller{} + daguserver_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:daguserver')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in daguserver_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o DaguInstaller) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'daguserver.') { + return + } mut install_actions := plbook.find(filter: 'daguserver.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'daguserver.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self DaguInstaller) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self DaguInstaller) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self DaguInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -253,12 +290,4 @@ pub fn (mut self DaguInstaller) destroy() ! { // switch instance to be used for daguserver pub fn switch(name string) { - daguserver_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/fungistor/fungistor_actions.v b/lib/installers/sysadmintools/fungistor/fungistor_actions.v index abea2acc..a983bef9 100644 --- a/lib/installers/sysadmintools/fungistor/fungistor_actions.v +++ b/lib/installers/sysadmintools/fungistor/fungistor_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'fungistor' // cmd: 'fungistor server' // env: { diff --git a/lib/installers/sysadmintools/fungistor/fungistor_factory_.v b/lib/installers/sysadmintools/fungistor/fungistor_factory_.v index d0981bd5..4f4ab3f3 100644 --- a/lib/installers/sysadmintools/fungistor/fungistor_factory_.v +++ b/lib/installers/sysadmintools/fungistor/fungistor_factory_.v @@ -2,28 +2,34 @@ module fungistor import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - fungistor_global map[string]&FungiStor - fungistor_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&FungiStor { +pub fn new(args ArgsGet) !&FungiStor { return &FungiStor{} } +pub fn get(args ArgsGet) !&FungiStor { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'fungistor.') { + return + } + mut install_actions := plbook.find(filter: 'fungistor.configure')! + if install_actions.len > 0 { + return error("can't configure fungistor, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'fungistor.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self FungiStor) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self FungiStor) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self FungiStor) destroy() ! { // switch instance to be used for fungistor pub fn switch(name string) { - fungistor_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/garage_s3/garage_s3_actions.v b/lib/installers/sysadmintools/garage_s3/garage_s3_actions.v index 45836fc1..8435482b 100644 --- a/lib/installers/sysadmintools/garage_s3/garage_s3_actions.v +++ b/lib/installers/sysadmintools/garage_s3/garage_s3_actions.v @@ -4,15 +4,16 @@ import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.core.httpconnection import os import json -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'garage_s3' cmd: 'garage_s3 -c /var/garage/config.toml server' startuptype: .zinit diff --git a/lib/installers/sysadmintools/garage_s3/garage_s3_factory_.v b/lib/installers/sysadmintools/garage_s3/garage_s3_factory_.v index 46ee9703..c25800e6 100644 --- a/lib/installers/sysadmintools/garage_s3/garage_s3_factory_.v +++ b/lib/installers/sysadmintools/garage_s3/garage_s3_factory_.v @@ -3,8 +3,8 @@ module garage_s3 import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -17,61 +17,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&GarageS3 { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&GarageS3 { mut obj := GarageS3{ name: args.name } - if args.name !in garage_s3_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&GarageS3 { + mut context := base.context()! + garage_s3_default = args.name + if args.fromdb || args.name !in garage_s3_global { + mut r := context.redis()! + if r.hexists('context:garage_s3', args.name)! { + data := r.hget('context:garage_s3', args.name)! + if data.len == 0 { + return error('GarageS3 with name: garage_s3 does not exist, prob bug.') + } + mut obj := json.decode(GarageS3, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('garage_s3', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("GarageS3 with name 'garage_s3' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return garage_s3_global[args.name] or { - println(garage_s3_global) - // bug if we get here because should be in globals - panic('could not get config for garage_s3 with name, is bug:${args.name}') + return error('could not get config for garage_s3 with name:garage_s3') } } // register the config for the future pub fn set(o GarageS3) ! { set_in_mem(o)! + garage_s3_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('garage_s3', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:garage_s3', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('garage_s3', args.name) + mut r := context.redis()! + return r.hexists('context:garage_s3', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('garage_s3', args.name)! - if args.name in garage_s3_global { - // del garage_s3_global[args.name] + mut r := context.redis()! + r.hdel('context:garage_s3', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&GarageS3 { + mut res := []&GarageS3{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + garage_s3_global = map[string]&GarageS3{} + garage_s3_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:garage_s3')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in garage_s3_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +118,9 @@ fn set_in_mem(o GarageS3) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'garage_s3.') { + return + } mut install_actions := plbook.find(filter: 'garage_s3.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +129,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'garage_s3.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,24 +169,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -223,10 +265,12 @@ pub fn (mut self GarageS3) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -255,10 +299,3 @@ pub fn (mut self GarageS3) destroy() ! { pub fn switch(name string) { garage_s3_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/sysadmintools/grafana/grafana_actions.v b/lib/installers/sysadmintools/grafana/grafana_actions.v index 759c0476..c2dc30c9 100644 --- a/lib/installers/sysadmintools/grafana/grafana_actions.v +++ b/lib/installers/sysadmintools/grafana/grafana_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'grafana' // cmd: 'grafana server' // env: { diff --git a/lib/installers/sysadmintools/grafana/grafana_factory_.v b/lib/installers/sysadmintools/grafana/grafana_factory_.v index b529bf6b..c15e9aac 100644 --- a/lib/installers/sysadmintools/grafana/grafana_factory_.v +++ b/lib/installers/sysadmintools/grafana/grafana_factory_.v @@ -2,28 +2,34 @@ module grafana import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - grafana_global map[string]&Grafana - grafana_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Grafana { +pub fn new(args ArgsGet) !&Grafana { return &Grafana{} } +pub fn get(args ArgsGet) !&Grafana { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'grafana.') { + return + } + mut install_actions := plbook.find(filter: 'grafana.configure')! + if install_actions.len > 0 { + return error("can't configure grafana, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'grafana.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self Grafana) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self Grafana) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self Grafana) destroy() ! { // switch instance to be used for grafana pub fn switch(name string) { - grafana_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/prometheus/prometheus_actions.v b/lib/installers/sysadmintools/prometheus/prometheus_actions.v index fa2c8350..242e3acd 100644 --- a/lib/installers/sysadmintools/prometheus/prometheus_actions.v +++ b/lib/installers/sysadmintools/prometheus/prometheus_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'prometheus' // cmd: 'prometheus server' // env: { diff --git a/lib/installers/sysadmintools/prometheus/prometheus_factory_.v b/lib/installers/sysadmintools/prometheus/prometheus_factory_.v index 3a948f60..509054d7 100644 --- a/lib/installers/sysadmintools/prometheus/prometheus_factory_.v +++ b/lib/installers/sysadmintools/prometheus/prometheus_factory_.v @@ -2,28 +2,34 @@ module prometheus import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - prometheus_global map[string]&Prometheus - prometheus_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Prometheus { +pub fn new(args ArgsGet) !&Prometheus { return &Prometheus{} } +pub fn get(args ArgsGet) !&Prometheus { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'prometheus.') { + return + } + mut install_actions := plbook.find(filter: 'prometheus.configure')! + if install_actions.len > 0 { + return error("can't configure prometheus, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'prometheus.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self Prometheus) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self Prometheus) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self Prometheus) destroy() ! { // switch instance to be used for prometheus pub fn switch(name string) { - prometheus_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/rclone/rclone_factory_.v b/lib/installers/sysadmintools/rclone/rclone_factory_.v index ebfc0b80..422d0c1a 100644 --- a/lib/installers/sysadmintools/rclone/rclone_factory_.v +++ b/lib/installers/sysadmintools/rclone/rclone_factory_.v @@ -3,8 +3,8 @@ module rclone import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( rclone_global map[string]&RClone @@ -16,61 +16,97 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&RClone { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&RClone { mut obj := RClone{ name: args.name } - if args.name !in rclone_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&RClone { + mut context := base.context()! + rclone_default = args.name + if args.fromdb || args.name !in rclone_global { + mut r := context.redis()! + if r.hexists('context:rclone', args.name)! { + data := r.hget('context:rclone', args.name)! + if data.len == 0 { + return error('RClone with name: rclone does not exist, prob bug.') + } + mut obj := json.decode(RClone, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('rclone', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("RClone with name 'rclone' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return rclone_global[args.name] or { - println(rclone_global) - // bug if we get here because should be in globals - panic('could not get config for rclone with name, is bug:${args.name}') + return error('could not get config for rclone with name:rclone') } } // register the config for the future pub fn set(o RClone) ! { set_in_mem(o)! + rclone_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('rclone', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:rclone', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('rclone', args.name) + mut r := context.redis()! + return r.hexists('context:rclone', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('rclone', args.name)! - if args.name in rclone_global { - // del rclone_global[args.name] + mut r := context.redis()! + r.hdel('context:rclone', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&RClone { + mut res := []&RClone{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + rclone_global = map[string]&RClone{} + rclone_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:rclone')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in rclone_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -81,6 +117,9 @@ fn set_in_mem(o RClone) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'rclone.') { + return + } mut install_actions := plbook.find(filter: 'rclone.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -89,7 +128,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'rclone.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -111,28 +149,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - // load from disk and make sure is properly intialized pub fn (mut self RClone) reload() ! { switch(self.name) @@ -161,10 +177,3 @@ pub fn (mut self RClone) destroy() ! { pub fn switch(name string) { rclone_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/sysadmintools/restic/restic_actions.v b/lib/installers/sysadmintools/restic/restic_actions.v index a5d7cb3a..1d3a5e47 100644 --- a/lib/installers/sysadmintools/restic/restic_actions.v +++ b/lib/installers/sysadmintools/restic/restic_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'restic' // cmd: 'restic server' // env: { diff --git a/lib/installers/sysadmintools/restic/restic_factory_.v b/lib/installers/sysadmintools/restic/restic_factory_.v index 892d109d..0a4ca10e 100644 --- a/lib/installers/sysadmintools/restic/restic_factory_.v +++ b/lib/installers/sysadmintools/restic/restic_factory_.v @@ -2,28 +2,34 @@ module restic import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - restic_global map[string]&Restic - restic_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Restic { +pub fn new(args ArgsGet) !&Restic { return &Restic{} } +pub fn get(args ArgsGet) !&Restic { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'restic.') { + return + } + mut install_actions := plbook.find(filter: 'restic.configure')! + if install_actions.len > 0 { + return error("can't configure restic, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'restic.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self Restic) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self Restic) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self Restic) destroy() ! { // switch instance to be used for restic pub fn switch(name string) { - restic_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/s3/s3_actions.v b/lib/installers/sysadmintools/s3/s3_actions.v index f5168020..d3868abd 100644 --- a/lib/installers/sysadmintools/s3/s3_actions.v +++ b/lib/installers/sysadmintools/s3/s3_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 's3' // cmd: 's3 server' // env: { diff --git a/lib/installers/sysadmintools/s3/s3_factory_.v b/lib/installers/sysadmintools/s3/s3_factory_.v index cb73988f..22c77c94 100644 --- a/lib/installers/sysadmintools/s3/s3_factory_.v +++ b/lib/installers/sysadmintools/s3/s3_factory_.v @@ -2,28 +2,34 @@ module s3 import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - s3_global map[string]&S3Installer - s3_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&S3Installer { +pub fn new(args ArgsGet) !&S3Installer { return &S3Installer{} } +pub fn get(args ArgsGet) !&S3Installer { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 's3.') { + return + } + mut install_actions := plbook.find(filter: 's3.configure')! + if install_actions.len > 0 { + return error("can't configure s3, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 's3.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self S3Installer) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self S3Installer) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self S3Installer) destroy() ! { // switch instance to be used for s3 pub fn switch(name string) { - s3_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/sysadmintools/s3/server.v b/lib/installers/sysadmintools/s3/server.v index 3235f9ea..0cf7c2dc 100644 --- a/lib/installers/sysadmintools/s3/server.v +++ b/lib/installers/sysadmintools/s3/server.v @@ -1,7 +1,7 @@ module s3 import freeflowuniverse.herolib.osal.core as osal -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.data.dbfs import freeflowuniverse.herolib.core.texttools import json diff --git a/lib/installers/threefold/griddriver/griddriver_factory_.v b/lib/installers/threefold/griddriver/griddriver_factory_.v index caa721c3..9108f8f0 100644 --- a/lib/installers/threefold/griddriver/griddriver_factory_.v +++ b/lib/installers/threefold/griddriver/griddriver_factory_.v @@ -2,27 +2,33 @@ module griddriver import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - griddriver_global map[string]&GridDriverInstaller - griddriver_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&GridDriverInstaller { +pub fn new(args ArgsGet) !&GridDriverInstaller { return &GridDriverInstaller{} } +pub fn get(args ArgsGet) !&GridDriverInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'griddriver.') { + return + } + mut install_actions := plbook.find(filter: 'griddriver.configure')! + if install_actions.len > 0 { + return error("can't configure griddriver, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'griddriver.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -91,12 +75,4 @@ pub fn (mut self GridDriverInstaller) destroy() ! { // switch instance to be used for griddriver pub fn switch(name string) { - griddriver_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/virt/cloudhypervisor/cloudhypervisor_factory_.v b/lib/installers/virt/cloudhypervisor/cloudhypervisor_factory_.v index 9cdac666..4567b29c 100644 --- a/lib/installers/virt/cloudhypervisor/cloudhypervisor_factory_.v +++ b/lib/installers/virt/cloudhypervisor/cloudhypervisor_factory_.v @@ -2,27 +2,33 @@ module cloudhypervisor import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - cloudhypervisor_global map[string]&CloudHypervisor - cloudhypervisor_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&CloudHypervisor { +pub fn new(args ArgsGet) !&CloudHypervisor { return &CloudHypervisor{} } +pub fn get(args ArgsGet) !&CloudHypervisor { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'cloudhypervisor.') { + return + } + mut install_actions := plbook.find(filter: 'cloudhypervisor.configure')! + if install_actions.len > 0 { + return error("can't configure cloudhypervisor, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'cloudhypervisor.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -91,12 +75,4 @@ pub fn (mut self CloudHypervisor) destroy() ! { // switch instance to be used for cloudhypervisor pub fn switch(name string) { - cloudhypervisor_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/virt/docker/docker_actions.v b/lib/installers/virt/docker/docker_actions.v index 99a359de..f6c35ccb 100644 --- a/lib/installers/virt/docker/docker_actions.v +++ b/lib/installers/virt/docker/docker_actions.v @@ -3,12 +3,13 @@ module docker import freeflowuniverse.herolib.core import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist -fn startupcmd() ![]zinit.ZProcessNewArgs { - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ +fn startupcmd() ![]startupmanager.ZProcessNewArgs { + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'docker' cmd: 'dockerd' } diff --git a/lib/installers/virt/docker/docker_factory_.v b/lib/installers/virt/docker/docker_factory_.v index e25e7205..14235f34 100644 --- a/lib/installers/virt/docker/docker_factory_.v +++ b/lib/installers/virt/docker/docker_factory_.v @@ -2,8 +2,8 @@ module docker import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time __global ( @@ -16,14 +16,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&DockerInstaller { +pub fn new(args ArgsGet) !&DockerInstaller { return &DockerInstaller{} } +pub fn get(args ArgsGet) !&DockerInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'docker.') { + return + } + mut install_actions := plbook.find(filter: 'docker.configure')! + if install_actions.len > 0 { + return error("can't configure docker, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'docker.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,24 +75,28 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } @@ -150,10 +165,12 @@ pub fn (mut self DockerInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -182,10 +199,3 @@ pub fn (mut self DockerInstaller) destroy() ! { pub fn switch(name string) { docker_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/virt/pacman/pacman_factory_.v b/lib/installers/virt/pacman/pacman_factory_.v index 6e333e9c..513826d3 100644 --- a/lib/installers/virt/pacman/pacman_factory_.v +++ b/lib/installers/virt/pacman/pacman_factory_.v @@ -2,27 +2,33 @@ module pacman import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - pacman_global map[string]&PacmanInstaller - pacman_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&PacmanInstaller { +pub fn new(args ArgsGet) !&PacmanInstaller { return &PacmanInstaller{} } +pub fn get(args ArgsGet) !&PacmanInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'pacman.') { + return + } + mut install_actions := plbook.find(filter: 'pacman.configure')! + if install_actions.len > 0 { + return error("can't configure pacman, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'pacman.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self PacmanInstaller) destroy() ! { // switch instance to be used for pacman pub fn switch(name string) { - pacman_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/virt/podman/podman_factory_.v b/lib/installers/virt/podman/podman_factory_.v index 2e859a2b..2cbc9633 100644 --- a/lib/installers/virt/podman/podman_factory_.v +++ b/lib/installers/virt/podman/podman_factory_.v @@ -2,27 +2,33 @@ module podman import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - podman_global map[string]&PodmanInstaller - podman_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&PodmanInstaller { +pub fn new(args ArgsGet) !&PodmanInstaller { return &PodmanInstaller{} } +pub fn get(args ArgsGet) !&PodmanInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'podman.') { + return + } + mut install_actions := plbook.find(filter: 'podman.configure')! + if install_actions.len > 0 { + return error("can't configure podman, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'podman.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self PodmanInstaller) destroy() ! { // switch instance to be used for podman pub fn switch(name string) { - podman_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/virt/youki/youki_factory_.v b/lib/installers/virt/youki/youki_factory_.v index f7494a09..5a5eaf33 100644 --- a/lib/installers/virt/youki/youki_factory_.v +++ b/lib/installers/virt/youki/youki_factory_.v @@ -2,27 +2,33 @@ module youki import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - youki_global map[string]&YoukiInstaller - youki_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&YoukiInstaller { +pub fn new(args ArgsGet) !&YoukiInstaller { return &YoukiInstaller{} } +pub fn get(args ArgsGet) !&YoukiInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'youki.') { + return + } + mut install_actions := plbook.find(filter: 'youki.configure')! + if install_actions.len > 0 { + return error("can't configure youki, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'youki.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -91,12 +75,4 @@ pub fn (mut self YoukiInstaller) destroy() ! { // switch instance to be used for youki pub fn switch(name string) { - youki_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/web/bun/bun_factory_.v b/lib/installers/web/bun/bun_factory_.v index 991f6147..4781595b 100644 --- a/lib/installers/web/bun/bun_factory_.v +++ b/lib/installers/web/bun/bun_factory_.v @@ -2,27 +2,33 @@ module bun import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit - -__global ( - bun_global map[string]&Bun - bun_default string -) /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Bun { +pub fn new(args ArgsGet) !&Bun { return &Bun{} } +pub fn get(args ArgsGet) !&Bun { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'bun.') { + return + } + mut install_actions := plbook.find(filter: 'bun.configure')! + if install_actions.len > 0 { + return error("can't configure bun, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'bun.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +50,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -86,12 +70,4 @@ pub fn (mut self Bun) destroy() ! { // switch instance to be used for bun pub fn switch(name string) { - bun_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/web/imagemagick/imagemagick_actions.v b/lib/installers/web/imagemagick/imagemagick_actions.v index 42030906..f1477b97 100644 --- a/lib/installers/web/imagemagick/imagemagick_actions.v +++ b/lib/installers/web/imagemagick/imagemagick_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'imagemagick' // cmd: 'imagemagick server' // env: { diff --git a/lib/installers/web/imagemagick/imagemagick_factory_.v b/lib/installers/web/imagemagick/imagemagick_factory_.v index f8e6efc0..7675a166 100644 --- a/lib/installers/web/imagemagick/imagemagick_factory_.v +++ b/lib/installers/web/imagemagick/imagemagick_factory_.v @@ -2,28 +2,34 @@ module imagemagick import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - imagemagick_global map[string]&ImageMagick - imagemagick_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&ImageMagick { +pub fn new(args ArgsGet) !&ImageMagick { return &ImageMagick{} } +pub fn get(args ArgsGet) !&ImageMagick { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'imagemagick.') { + return + } + mut install_actions := plbook.find(filter: 'imagemagick.configure')! + if install_actions.len > 0 { + return error("can't configure imagemagick, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'imagemagick.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self ImageMagick) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self ImageMagick) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self ImageMagick) destroy() ! { // switch instance to be used for imagemagick pub fn switch(name string) { - imagemagick_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/web/lighttpd/installer.v b/lib/installers/web/lighttpd/installer.v index 0eaefd35..09f84540 100644 --- a/lib/installers/web/lighttpd/installer.v +++ b/lib/installers/web/lighttpd/installer.v @@ -5,7 +5,7 @@ import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.installers.infra.zinit -import freeflowuniverse.herolib.osal.zinit as zinitmgmt +import freeflowuniverse.herolib.osal.startupmanager as zinitmgmt import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.osal.screen import os diff --git a/lib/installers/web/lighttpd/lighttpd_actions.v b/lib/installers/web/lighttpd/lighttpd_actions.v index d64a1684..6cba21e1 100644 --- a/lib/installers/web/lighttpd/lighttpd_actions.v +++ b/lib/installers/web/lighttpd/lighttpd_actions.v @@ -5,18 +5,18 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust import freeflowuniverse.herolib.installers.lang.python import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} + mut res := []startupmanager.ZProcessNewArgs{} // THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED - // res << zinit.ZProcessNewArgs{ + // res << startupmanager.ZProcessNewArgs{ // name: 'lighttpd' // cmd: 'lighttpd server' // env: { diff --git a/lib/installers/web/lighttpd/lighttpd_factory_.v b/lib/installers/web/lighttpd/lighttpd_factory_.v index 0d392640..b4a3ba88 100644 --- a/lib/installers/web/lighttpd/lighttpd_factory_.v +++ b/lib/installers/web/lighttpd/lighttpd_factory_.v @@ -2,28 +2,34 @@ module lighttpd import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - lighttpd_global map[string]&LightHttpdInstaller - lighttpd_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&LightHttpdInstaller { +pub fn new(args ArgsGet) !&LightHttpdInstaller { return &LightHttpdInstaller{} } +pub fn get(args ArgsGet) !&LightHttpdInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'lighttpd.') { + return + } + mut install_actions := plbook.find(filter: 'lighttpd.configure')! + if install_actions.len > 0 { + return error("can't configure lighttpd, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'lighttpd.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -64,30 +70,33 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } pub fn (mut self LightHttpdInstaller) start() ! { - switch(self.name) if self.running()! { return } @@ -150,10 +159,12 @@ pub fn (mut self LightHttpdInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -185,12 +196,4 @@ pub fn (mut self LightHttpdInstaller) destroy() ! { // switch instance to be used for lighttpd pub fn switch(name string) { - lighttpd_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/web/tailwind/tailwind_factory_.v b/lib/installers/web/tailwind/tailwind_factory_.v index a5a354f7..b08d4ce2 100644 --- a/lib/installers/web/tailwind/tailwind_factory_.v +++ b/lib/installers/web/tailwind/tailwind_factory_.v @@ -2,8 +2,8 @@ module tailwind import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( tailwind_global map[string]&Tailwind @@ -15,14 +15,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Tailwind { +pub fn new(args ArgsGet) !&Tailwind { return &Tailwind{} } +pub fn get(args ArgsGet) !&Tailwind { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'tailwind.') { + return + } + mut install_actions := plbook.find(filter: 'tailwind.configure')! + if install_actions.len > 0 { + return error("can't configure tailwind, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'tailwind.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +55,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -88,10 +77,3 @@ pub fn (mut self Tailwind) destroy() ! { pub fn switch(name string) { tailwind_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/web/tailwind4/tailwind4_factory_.v b/lib/installers/web/tailwind4/tailwind4_factory_.v index 75ae59e8..3ca1b96d 100644 --- a/lib/installers/web/tailwind4/tailwind4_factory_.v +++ b/lib/installers/web/tailwind4/tailwind4_factory_.v @@ -2,8 +2,8 @@ module tailwind4 import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( tailwind4_global map[string]&Tailwind @@ -15,14 +15,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&Tailwind { +pub fn new(args ArgsGet) !&Tailwind { return &Tailwind{} } +pub fn get(args ArgsGet) !&Tailwind { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'tailwind4.') { + return + } + mut install_actions := plbook.find(filter: 'tailwind4.configure')! + if install_actions.len > 0 { + return error("can't configure tailwind4, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'tailwind4.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +55,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -88,10 +77,3 @@ pub fn (mut self Tailwind) destroy() ! { pub fn switch(name string) { tailwind4_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/installers/web/traefik/traefik_actions.v b/lib/installers/web/traefik/traefik_actions.v index 90dd1c5b..b97976ef 100644 --- a/lib/installers/web/traefik/traefik_actions.v +++ b/lib/installers/web/traefik/traefik_actions.v @@ -4,14 +4,15 @@ import freeflowuniverse.herolib.osal.core as osal import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import os -fn startupcmd() ![]zinit.ZProcessNewArgs { +fn startupcmd() ![]startupmanager.ZProcessNewArgs { mut installer := get()! - mut res := []zinit.ZProcessNewArgs{} - res << zinit.ZProcessNewArgs{ + mut res := []startupmanager.ZProcessNewArgs{} + res << startupmanager.ZProcessNewArgs + { name: 'traefik' cmd: 'traefik' } diff --git a/lib/installers/web/traefik/traefik_factory_.v b/lib/installers/web/traefik/traefik_factory_.v index e9ba5510..e3d106d0 100644 --- a/lib/installers/web/traefik/traefik_factory_.v +++ b/lib/installers/web/traefik/traefik_factory_.v @@ -3,75 +3,106 @@ module traefik import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - traefik_global map[string]&TraefikServer - traefik_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&TraefikServer { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&TraefikServer { mut obj := TraefikServer{ name: args.name } - if args.name !in traefik_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&TraefikServer { + mut context := base.context()! + traefik_default = args.name + if args.fromdb || args.name !in traefik_global { + mut r := context.redis()! + if r.hexists('context:traefik', args.name)! { + data := r.hget('context:traefik', args.name)! + if data.len == 0 { + return error('TraefikServer with name: traefik does not exist, prob bug.') + } + mut obj := json.decode(TraefikServer, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('traefik', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("TraefikServer with name 'traefik' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return traefik_global[args.name] or { - println(traefik_global) - // bug if we get here because should be in globals - panic('could not get config for traefik with name, is bug:${args.name}') + return error('could not get config for traefik with name:traefik') } } // register the config for the future pub fn set(o TraefikServer) ! { set_in_mem(o)! + traefik_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('traefik', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:traefik', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('traefik', args.name) + mut r := context.redis()! + return r.hexists('context:traefik', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('traefik', args.name)! - if args.name in traefik_global { - // del traefik_global[args.name] + mut r := context.redis()! + r.hdel('context:traefik', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&TraefikServer { + mut res := []&TraefikServer{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + traefik_global = map[string]&TraefikServer{} + traefik_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:traefik')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in traefik_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o TraefikServer) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'traefik.') { + return + } mut install_actions := plbook.find(filter: 'traefik.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'traefik.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self TraefikServer) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self TraefikServer) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self TraefikServer) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -253,12 +290,4 @@ pub fn (mut self TraefikServer) destroy() ! { // switch instance to be used for traefik pub fn switch(name string) { - traefik_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/web/zola/zola_factory_.v b/lib/installers/web/zola/zola_factory_.v index 90637c52..6203cd38 100644 --- a/lib/installers/web/zola/zola_factory_.v +++ b/lib/installers/web/zola/zola_factory_.v @@ -2,8 +2,8 @@ module zola import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit __global ( zola_global map[string]&ZolaInstaller @@ -15,14 +15,25 @@ __global ( @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' } -pub fn get(args_ ArgsGet) !&ZolaInstaller { +pub fn new(args ArgsGet) !&ZolaInstaller { return &ZolaInstaller{} } +pub fn get(args ArgsGet) !&ZolaInstaller { + return new(args)! +} + pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'zola.') { + return + } + mut install_actions := plbook.find(filter: 'zola.configure')! + if install_actions.len > 0 { + return error("can't configure zola, because no configuration allowed for this installer.") + } mut other_actions := plbook.find(filter: 'zola.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -44,28 +55,6 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { - // unknown - // screen - // zinit - // tmux - // systemd - match cat { - .zinit { - console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! - } - .systemd { - console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! - } - else { - console.print_debug('startupmanager: auto') - return startupmanager.get()! - } - } -} - @[params] pub struct InstallArgs { pub mut: @@ -93,10 +82,3 @@ pub fn (mut self ZolaInstaller) destroy() ! { pub fn switch(name string) { zola_default = name } - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' -} diff --git a/lib/mycojobs/model/actor.v b/lib/mycojobs/model/actor.v new file mode 100644 index 00000000..368452a0 --- /dev/null +++ b/lib/mycojobs/model/actor.v @@ -0,0 +1,18 @@ +module model + +// a actor is a participant in the new internet, the one who can ask for work +// user can have more than one actor operating for them, an actor always operates in a context which is hosted by the hero of the user +// stored in the context db at actor: (actor is hset) +@[heap] +pub struct Actor { +pub mut: + id u32 + pubkey string + address []Address // address (is to reach the actor back), normally mycelium but doesn't have to be + created_at u32 // epoch + updated_at u32 // epoch +} + +pub fn (self Actor) redis_key() string { + return 'actor:${self.id}' +} diff --git a/lib/mycojobs/model/context.v b/lib/mycojobs/model/context.v new file mode 100644 index 00000000..69db32c7 --- /dev/null +++ b/lib/mycojobs/model/context.v @@ -0,0 +1,20 @@ +module model + +// each job is run in a context, this corresponds to a DB in redis and has specific rights to actors +// context is a redis db and also a locaction on a filesystem which can be used for e.g. logs, temporary files, etc. +// actors create contexts for others to work in +// stored in the context db at context: (context is hset) +@[heap] +pub struct Context { +pub mut: + id u32 // corresponds with the redis db (in our ourdb or other redis) + admins []u32 // actors which have admin rights on this context (means can do everything) + readers []u32 // actors which can read the context info + executors []u32 // actors which can execute jobs in this context + created_at u32 // epoch + updated_at u32 // epoch +} + +pub fn (self Context) redis_key() string { + return 'context:${self.id}' +} diff --git a/lib/mycojobs/model/flow.v b/lib/mycojobs/model/flow.v new file mode 100644 index 00000000..abc7c46d --- /dev/null +++ b/lib/mycojobs/model/flow.v @@ -0,0 +1,41 @@ +module model + +// what get's executed by an actor and needs to be tracked as a whole, can be represented as a DAG graph +// this is the high level representation of a workflow to execute on work, its fully decentralized and distributed +// only the actor who created the flow can modify it and holds it in DB +// stored in the context db at flow: (flow is hset) +@[heap] +pub struct Flow { +pub mut: + id u32 // this job id is given by the actor who called for it + caller_id u32 // is the actor which called for this job + context_id u32 // each job is executed in a context + jobs []u32 // links to all jobs which make up this flow, this can be dynamically modified + env_vars map[string]string // they are copied to every job done + result map[string]string // the result of the flow + created_at u32 // epoch + updated_at u32 // epoch + status FlowStatus +} + +pub fn (self Flow) redis_key() string { + return 'flow:${self.id}' +} + +// FlowStatus represents the status of a flow +pub enum FlowStatus { + dispatched + started + error + finished +} + +// str returns the string representation of FlowStatus +pub fn (self FlowStatus) str() string { + return match self { + .dispatched { 'dispatched' } + .started { 'started' } + .error { 'error' } + .finished { 'finished' } + } +} diff --git a/lib/mycojobs/model/message.v b/lib/mycojobs/model/message.v new file mode 100644 index 00000000..f0950769 --- /dev/null +++ b/lib/mycojobs/model/message.v @@ -0,0 +1,68 @@ +module model + +// Messages is what goes over mycelium (which is our messaging system), they can have a job inside +// stored in the context db at msg:: (msg is hset) +// there are 2 queues in the context db: queue: msg_out and msg_in these are generic queues which get all messages from mycelium (in) and the ones who need to be sent (out) are in the outqueue +@[heap] +pub struct Message { +pub mut: + id u32 // is unique id for the message, has been given by the caller + caller_id u32 // is the actor whos send this message + context_id u32 // each message is for a specific context + message string + message_type ScriptType + message_format_type MessageFormatType + timeout u32 // in sec, to arrive destination + timeout_ack u32 // in sec, to acknowledge receipt + timeout_result u32 // in sec, to process result and have it back + job []Job + logs []Log // e.g. for streaming logs back to originator + created_at u32 // epoch + updated_at u32 // epoch + status MessageStatus +} + +// MessageType represents the type of message +pub enum MessageType { + job + chat + mail +} + +// MessageFormatType represents the format of a message +pub enum MessageFormatType { + html + text + md +} + +pub fn (self Message) redis_key() string { + return 'message:${self.caller_id}:${self.id}' +} + +// queue_suffix returns the queue suffix for the message type +pub fn (mt MessageType) queue_suffix() string { + return match mt { + .job { 'job' } + .chat { 'chat' } + .mail { 'mail' } + } +} + +// MessageStatus represents the status of a message +pub enum MessageStatus { + dispatched + acknowledged + error + processed // e.g. can be something which comes back +} + +// str returns the string representation of MessageStatus +pub fn (ms MessageStatus) str() string { + return match ms { + .dispatched { 'dispatched' } + .acknowledged { 'acknowledged' } + .error { 'error' } + .processed { 'processed' } + } +} diff --git a/lib/mycojobs/model/runner.v b/lib/mycojobs/model/runner.v new file mode 100644 index 00000000..45cfe414 --- /dev/null +++ b/lib/mycojobs/model/runner.v @@ -0,0 +1,27 @@ +module model + +// a runner executes a job, this can be in VM, in a container or just some processes running somewhere +// the messages always come in over a topic +// stored in the context db at runner: (runner is hset) +@[heap] +pub struct Runner { +pub mut: + id u32 + pubkey string // from mycelium + address string // mycelium address + topic string // needs to be set by the runner but often runner e.g. runner20 + local bool // if local then goes on redis using the id + created_at u32 // epoch + updated_at u32 // epoch +} + +pub enum RunnerType { + v + python + osis + rust +} + +pub fn (self Runner) redis_key() string { + return 'runner:${self.id}' +} diff --git a/lib/mycojobs/model/runnerjob.v b/lib/mycojobs/model/runnerjob.v new file mode 100644 index 00000000..2ef789ed --- /dev/null +++ b/lib/mycojobs/model/runnerjob.v @@ -0,0 +1,64 @@ +module model + +// Job represents a job, a job is only usable in the context of a runner (which is part of a hero) +// stored in the context db at job:: (job is hset) +@[heap] +pub struct RunnerJob { +pub mut: + id u32 // this job id is given by the actor who called for it + caller_id u32 // is the actor which called for this job + context_id u32 // each job is executed in a context + script string + script_type ScriptType + timeout u32 // in sec + retries u8 + env_vars map[string]string + result map[string]string + prerequisites []string + dependends []u32 + created_at u32 // epoch + updated_at u32 // epoch + status JobStatus +} + +// ScriptType represents the type of script +pub enum ScriptType { + osis + sal + v + python +} + +pub fn (self RunnerJob) redis_key() string { + return 'job:${self.caller_id}:${self.id}' +} + +// queue_suffix returns the queue suffix for the script type +pub fn (st ScriptType) queue_suffix() string { + return match st { + .osis { 'osis' } + .sal { 'sal' } + .v { 'v' } + .python { 'python' } + } +} + +// JobStatus represents the status of a job +pub enum JobStatus { + dispatched + waiting_for_prerequisites + started + error + finished +} + +// str returns the string representation of JobStatus +pub fn (js JobStatus) str() string { + return match js { + .dispatched { 'dispatched' } + .waiting_for_prerequisites { 'waiting_for_prerequisites' } + .started { 'started' } + .error { 'error' } + .finished { 'finished' } + } +} diff --git a/lib/mycojobs/specs/models.md b/lib/mycojobs/specs/models.md new file mode 100644 index 00000000..4124ba1e --- /dev/null +++ b/lib/mycojobs/specs/models.md @@ -0,0 +1,314 @@ +# Models Specification +*Freeflow Universe – mycojobs* + +This document gathers **all data‑models** that exist in the `lib/mycojobs/model/` package, together with a concise purpose description, field semantics, Redis storage layout and the role each model plays in the overall *decentralised workflow* architecture. + + +## Table of Contents +1. [Actor](#actor) +2. [Context](#context) +3. [Flow](#flow) +4. [Message](#message) +5. [Runner](#runner) +6. [RunnerJob](#runnerjob) +7. [Enums & Shared Types](#enums-shared-types) +8. [Key‑generation helpers](#key-generation-helpers) + +--- + +## 1️⃣ `Actor` – Identity & entry‑point + +| Field | Type | Description | +|------|------|-------------| +| `id` | `u32` | Sequential identifier **unique per tenant**. Used as part of the Redis key `actor:`. | +| `pubkey` | `string` | Public key (Mycelium‑compatible) that authenticates the actor when it sends/receives messages. | +| `address` | `[]Address` | One or more reachable addresses (normally Mycelium topics) that other participants can use to contact the actor. | +| `created_at` | `u32` | Unix‑epoch time when the record was created. | +| `updated_at` | `u32` | Unix‑epoch time of the last mutation. | + +### Purpose +* An **Actor** is the *human‑or‑service* that **requests work**, receives results and can be an administrator of a **Context**. +* It is the *security principal* – every operation in a context is authorised against the actor’s ID and its public key signature. + +### Redis representation + +| Key | Example | Storage type | Fields | +|-----|---------|--------------|--------| +| `actor:${id}` | `actor:12` | **hash** (`HSET`) | `id`, `pubkey`, `address` (list), `created_at`, `updated_at` | + +--- + +## 2️⃣ `Context` – Tenant & permission container + +| Field | Type | Description | +|------|------|-------------| +| `id` | `u32` | Identifier that also selects the underlying **Redis DB** for this tenant. | +| `admins` | `[]u32` | Actor IDs that have **full control** (create/delete any object, manage permissions). | +| `readers` | `[]u32` | Actor IDs that may **read** any object in the context but cannot modify. | +| `executors` | `[]u32` | Actor IDs allowed to **run** `RunnerJob`s and update their status. | +| `created_at` | `u32` | Unix‑epoch of creation. | +| `updated_at` | `u32` | Unix‑epoch of last modification. | + +### Purpose +* A **Context** isolates a *tenant* – each tenant gets its own Redis database and a dedicated filesystem area (for logs, temporary files, …). +* It stores **permission lists** that the system consults before any operation (e.g., creating a `Flow`, enqueuing a `RunnerJob`). + +### Redis representation + +| Key | Example | Storage type | Fields | +|-----|---------|--------------|--------| +| `context:${id}` | `context:7` | **hash** | `id`, `admins`, `readers`, `executors`, `created_at`, `updated_at` | + +--- + +## 3️⃣ `Flow` – High‑level workflow (DAG) + +| Field | Type | Description | +|------|------|-------------| +| `id` | `u32` | Flow identifier – *unique inside the creator’s actor space*. | +| `caller_id` | `u32` | Actor that **created** the flow (owner). | +| `context_id` | `u32` | Context in which the flow lives. | +| `jobs` | `[]u32` | List of **RunnerJob** IDs that belong to this flow (the DAG edges are stored in each job’s `dependends`). | +| `env_vars` | `map[string]string` | Global environment variables injected into **every** job of the flow. | +| `result` | `map[string]string` | Aggregated output produced by the flow (filled by the orchestrator when the flow finishes). | +| `created_at` | `u32` | Creation timestamp. | +| `updated_at` | `u32` | Last update timestamp. | +| `status` | `FlowStatus` | Current lifecycle stage (`dispatched`, `started`, `error`, `finished`). | + +### Purpose +* A **Flow** is the *public‑facing* representation of a **workflow**. +* It groups many `RunnerJob`s, supplies common env‑vars, tracks overall status and collects the final result. +* Only the *creator* (the `caller_id`) may mutate the flow definition. + +### Redis representation + +| Key | Example | Storage type | Fields | +|-----|---------|--------------|--------| +| `flow:${id}` | `flow:33` | **hash** | `id`, `caller_id`, `context_id`, `jobs`, `env_vars`, `result`, `created_at`, `updated_at`, `status` | + +### `FlowStatus` enum + +| Value | Meaning | +|-------|---------| +| `dispatched` | Flow has been stored but not yet started. | +| `started` | At least one job is running. | +| `error` | One or more jobs failed; flow aborted. | +| `finished` | All jobs succeeded, `result` is final. | + +--- + +## 4️⃣ `Message` – Transport unit (Mycelium) + +| Field | Type | Description | +|------|------|-------------| +| `id` |u32 `_type` | `ScriptType` | *Kind* of the message – currently re‑used for job payloads (`osis`, `sal`, `v`, `python`). | +| `message_format_type` | `MessageFormatType` | Formatting of `message` (`html`, `text`, `md`). | +| `timeout` | `u32` | Seconds before the message is considered *lost* if not delivered. | +| `timeout_ack` | `u32` | Seconds allowed for the receiver to acknowledge. | +| `timeout_result` | `u32` | Seconds allowed for the receiver to send back a result. | +| `job` | `[]Job` | Embedded **RunnerJob** objects (normally a single job). | +| `logs` | `[]Log` | Optional streaming logs attached to the message. | +| `created_at` | `u32` | Timestamp of creation. | +| `updated_at` | `u32` | Timestamp of latest update. | +| `status` | `MessageStatus` | Current lifecycle (`dispatched`, `acknowledged`, `error`, `processed`). | + +### Purpose +* `Message` is the **payload carrier** that travels over **Mycelium** (the pub/sub system). +* It can be a **job request**, a **chat line**, an **email**, or any generic data that needs to be routed between actors, runners, or services. +* Every message is persisted as a Redis hash; the system also maintains two *generic* queues: + + * `msg_out` – outbound messages waiting to be handed to Mycelium. + * `msg_in` – inbound messages that have already arrived and are awaiting local processing. + +### Redis representation + +| Key | Example | Storage type | Fields | +|-----|---------|--------------|--------| +| `message:${caller_id}:${id}` | `message:12:101` | **hash** | All fields above (`id`, `caller_id`, `context_id`, …, `status`). | + +### `MessageType` enum (legacy – not used in current code but documented) + +| Value | Meaning | +|-------|---------| +| `job` | Payload carries a `RunnerJob`. | +| `chat` | Human‑to‑human communication. | +| `mail` | Email‑like message. | + +### `MessageFormatType` enum + +| Value | Meaning | +|-------|---------| +| `html` | HTML formatted body. | +| `text` | Plain‑text. | +| `md` | Markdown. | + +### `MessageStatus` enum + +| Value | Meaning | +|-------|---------| +| `dispatched` | Stored, not yet processed. | +| `acknowledged` | Receiver has confirmed receipt. | +| `error` | Delivery or processing failed. | +|` | Message handled (e.g., job result returned). | + +--- + +## 5️⃣ `Runner` – Worker that executes jobs + +| Field | Type | Description | +|------|------|-------------| +| `id` | `u32` | Unique runner identifier. | +| `pubkey` | `string` | Public key of the runner (used by Mycelium for auth). | +| `address` | `string` | Mycelium address (e.g., `mycelium://…`). | +| `topic` | `string` | Pub/Sub topic the runner subscribes to; defaults to `runner${id}`. | +| `local` | `bool` | If `true`, the runner also consumes jobs directly from **Redis queues** (e.g., `queue:v`). | +| `created_at` | `u32` | Creation timestamp. | +| `updated_at` | `u32` | Last modification timestamp. | + +### Purpose +* A **Runner** is the *execution engine* – it could be a VM, a container, or a process that knows how to run a specific script type (`v`, `python`, `osis`, `rust`). +* It **subscribes** to a Mycelium topic to receive job‑related messages, and, when `local==true`, it also **polls** a Redis list named after the script‑type (`queue:`). + +### Redis representation + +| Key | Example | Storage type | +|-----|---------|--------------| +| `runner:${id}` | `runner:20` | **hash** *(all fields above)* | + +### `RunnerType` enum + +| Value | Intended runtime | +|-------|------------------| +| `v` | V language VM | +| `python` | CPython / PyPy | +| `osis` | OSIS‑specific runtime | +| `rust` | Native Rust binary | + +--- + +## 6️⃣ `RunnerJob` – Executable unit + +| Field | Type | Description | +|------|------|-------------| +| `id` | `u32` | Job identifier **provided by the caller**. | +| `caller_id` | `u32` | Actor that created the job. | +| `context_id` | `u32` | Context in which the job will run. | +| `script` | `string` | Source code / command to be executed. | +| `script_type` | `ScriptType` | Language or runtime of the script (`osis`, `sal`, `v`, `python`). | +| `timeout` | `u32` | Maximum execution time (seconds). | +| `retries` | `u8` | Number of automatic retries on failure. | +| `env_vars` | `map[string]string` | Job‑specific environment variables (merged with `Flow.env_vars`). | +| `result` | `map[string]string` | Key‑value map that the job writes back upon completion. | +| `prerequisites` | `[]string` | Human‑readable IDs of **external** prerequisites (e.g., files, other services). | +| `dependends` | `[]u32` | IDs of **other RunnerJob** objects that must finish before this job can start. | +| `created_at` | `u32` | Creation timestamp. | +| `updated_at` | `u32` | Last update timestamp. | +| `status` | `JobStatus` | Lifecycle status (`dispatched`, `waiting_for_prerequisites`, `started`, `error`, `finished`). | + +### Purpose +* A **RunnerJob** is the *atomic piece of work* that a `Runner` executes. +* It lives inside a **Context**, is queued according to its `script_type`, and moves through a well‑defined **state machine**. +* The `dependends` field enables the *DAG* behaviour that the `Flow` model represents at a higher level. + +### Redis representation + +| Key | Example | Storage type | +|-----|---------|--------------| +| `job:${caller_id}:${id}` | `job:12:2001` | **hash** *(all fields above)* | + +### `ScriptType` enum + +| Value | Runtime | +|-------|---------| +| `osis` | OSIS interpreter | +| `sal` | SAL DSL (custom) | +| `v` | V language | +| `python`| CPython / PyPy | + +*The enum provides a **`queue_suffix()`** helper that maps a script type to the name of the Redis list used for local job dispatch (`queue:python`, `queue:v`, …).* + +### `JobStatus` enum + +| Value | Meaning | +|-------|---------| +| `dispatched` | Stored, waiting to be examined for prerequisites. | +| `waiting_for_prerequisites` | Has `dependends` that are not yet finished. | +| `started` | Currently executing on a runner. | +| `error` | Execution failed (or exceeded retries). | +| `finished` | Successfully completed, `result` populated. | + +--- + +## 7️⃣ Other Enums & Shared Types + +| Enum | Location | Values | Note | +|------|----------|--------|------| +| `MessageType` | `message.v` | `job`, `chat`, `mail` | Determines how a `Message` is interpreted. | +| `MessageFormatType` | `message.v` | `html`, `text`, `md` | UI‑layer rendering hint. | +| `MessageStatus` | `message.v` | `dispatched`, `acknowledged`, `error`, `processed` | Life‑cycle of a `Message`. | +| `FlowStatus` | `flow.v` | `dispatched`, `started`, `error`, `finished` | High‑level flow progress. | +| `RunnerType` | `runner.v` | `v`, `python`, `osis`, `rust` | Not currently stored; used by the orchestration layer to pick a runner implementation. | +| `ScriptType` | `runnerjob.v` | `osis`, `sal`, `v`, `python` | Determines queue suffix & runtime. | +| `JobStatus` | `runnerjob.v` | `dispatched`, `waiting_for_prerequisites`, `started`, `error`, `finished` | Per‑job state machine. | + +--- + +## 8️⃣ Key‑generation helpers (methods) + +| Model | Method | Returns | Example | +|-------|--------|---------|---------| +| `Actor` | `redis_key()` | `"actor:${self.id}"` | `actor:12` | +| `Context` | `redis_key()` | `"context:${self.id}"` | `context:7` | +| `Flow` | `redis_key()` | `"flow:${self.id}"` | `flow:33` | +| `Message` | `redis_key()` | `"message:${self.caller_id}:${self.id}"` | `message:12:101` | +| `Runner` | `redis_key()` | `"runner:${self.id}"` | `runner:20` | +| `RunnerJob` | `redis_key()` | `"job:${self.caller_id}:${self.id}"` | `job:12:2001` | +| `MessageType` | `queue_suffix()` | `"job"` / `"chat"` / `"mail"` | `MessageType.job.queue_suffix() → "job"` | +| `ScriptType` | `queue_suffix()` | `"osis"` / `"sal"` / `"v"` / `"python"` | `ScriptType.python.queue_suffix() → "python"` | + +These helpers guarantee **canonical key naming** throughout the code base and simplify Redis interactions. + +--- + +## 📌 Summary Diagram (quick reference) + +```mermaid +%%{init: {"theme":"dark"}}%% +graph TD + %% Actors and what they can create + A[Actor] -->|creates| Ctx[Context] + A -->|creates| Fl[Flow] + A -->|creates| Msg[Message] + A -->|creates| Rnr[Runner] + A -->|creates| Job[RunnerJob] + + %% All objects live inside one Redis DB that belongs to a Context + subgraph "Redis DB (per Context)" + Ctx + A + Fl + Msg + Rnr + Job + end + + %% Messaging queues (global, outside the Context DB) + Msg -->|pushes key onto| OutQ[msg_out] + OutQ -->|transport via Mycelium| InQ[msg_in] + InQ -->|pulled by| Rnr + + %% Local runner queues (only when runner.local == true) + Rnr -->|BRPOP from| QueueV["queue:v"] + Rnr -->|BRPOP from| QueuePy["queue:python"] + Rnr -->|BRPOP from| QueueOSIS["queue:osis"] + +``` + +## context based + +* Inside a Context, an **Actor** can create a **Flow** that references many **RunnerJob** IDs (the DAG). +* To *initiate* execution, the Actor packages a **RunnerJob** (or a full Flow) inside a **Message**, pushes it onto `msg_out`, and the system routes it via **Mycelium** to the target Context. +* The remote **Runner** receives the Message, materialises the **RunnerJob**, queues it on a script‑type list, executes it, writes back `result` and status, and optionally sends a *result Message* back to the originator. + +All state is persisted as **Redis hashes**, guaranteeing durability and enabling *idempotent* retries. The uniform naming conventions (`actor:`, `job::`, …) make it trivial to locate any object given its identifiers. + diff --git a/lib/mycojobs/specs/specs.md b/lib/mycojobs/specs/specs.md new file mode 100644 index 00000000..9e58f7d7 --- /dev/null +++ b/lib/mycojobs/specs/specs.md @@ -0,0 +1,263 @@ + +## Objects Used + +| Component | What it **stores** | Where it lives (Redis key) | Main responsibilities | +|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Actor** | Public key, reachable addresses, timestamps | `actor:` (hash) | An identity that can request work, receive results and act as an administrator of a *Context*. | +| **Context**| Permission lists (`admins`, `readers`, `executors`), timestamps | `context:` (hash) | An isolated “tenant” – a separate Redis DB and filesystem area. All objects (flows, messages, jobs, runners) belonging to a given workflow are stored under this context. The permission lists control who may read, execute or administer the context. | +| **Flow** | DAG of job IDs, env‑vars, result map, status, timestamps | `flow:` (hash) | A high‑level workflow created by a single **Actor**. It groups many **RunnerJob** objects, records their execution order, supplies common environment variables and aggregates the final result. | +| **Message**| Payload, type (`job\|chat\|mail`), format (`html\|text\|md`), time‑outs, embedded **Job** objects, log stream, status, timestamps | `message::` (hash) | The transport unit that travels over **Mycelium** (the pub/sub/message bus). A message can contain a **RunnerJob** (or a list of jobs) and is queued in two generic Redis lists: `msg_out` (to be sent) and `msg_in` (already received). | +| **Runner** | Public key, Mycelium address, topic name, type (`v\|python\|osis\|rust`), local flag, timestamps | `runner:` (hash) | The *worker* that actually executes **RunnerJob** scripts. It subscribes to a Mycelium topic (normally `runner`). If `local == true` the runner also consumes jobs directly from a Redis queue that is named after the script‑type suffix (`v`, `python`, …). | +| **RunnerJob**| Script source, type (`osis\|sal\|v\|python`), env‑vars, prerequisites, dependencies, status, timestamps, result map | `job::` (hash) | A single executable unit. It lives inside a **Context**, belongs to a **Runner**, and is queued according to its `script_type` (e.g. `queue:python`). Its status moves through the lifecycle `dispatched → waiting_for_prerequisites → started → finished|error`. | + +> **Key idea:** All objects are persisted as *hashes* in a **Redis** database that is dedicated to a *Context*. The system is completely **decentralised** – each actor owns its own context and can spin up as many runners as needed. Communication between actors, runners and the rest of the system happens over **Mycelium**, a message‑bus that uses Redis lists as queues. + +--- + +## Interaction diagram (who talks to who) + +### Sequence diagram – “Submit a flow and run it” + +```mermaid +%%{init: {"theme":"dark"}}%% +sequenceDiagram + participant A as Actor + participant L as Local‑Context (Redis) + participant M as Mycelium (msg_out / msg_in) + participant R as Remote‑Context (Redis) + participant W as Runner (worker) + + %% 1. Actor creates everything locally + A->>L: create Flow + RunnerJob (J) + A->>L: LPUSH msg_out Message{type=job, payload=J, target=Remote} + + %% 2. Mycelium transports the message + M->>R: LPUSH msg_in (Message key) + + %% 3. Remote context materialises the job + R->>R: HSET Message hash + R->>R: HSET RunnerJob (J') // copy of payload + R->>R: LPUSH queue:v (job key) + + %% 4. Runner consumes and executes + W->>R: BRPOP queue:v (job key) + W->>R: HSET job status = started + W->>W: execute script + W->>R: HSET job result + status = finished + + %% 5. Result is sent back + W->>M: LPUSH msg_out Message{type=result, payload=result, target=Local} + M->>L: LPUSH msg_in (result Message key) + + %% 6. Actor receives the result + A->>L: RPOP msg_in → read result +``` + +### 2.2 Component diagram – “Static view of objects & links” + +```mermaid +%%{init: {"theme":"dark"}}%% +graph LR + subgraph Redis["Redis (per Context)"] + A[Actor] -->|stores| Ctx[Context] + Ctx -->|stores| Fl[Flow] + Ctx -->|stores| Msg[Message] + Ctx -->|stores| Rnr[Runner] + Ctx -->|stores| Job[RunnerJob] + end + + subgraph Mycelium["Mycelium (Pub/Sub)"] + MsgOut["queue:msg_out"] -->|outgoing| Mcel[Mycelium Bus] + Mcel -->|incoming| MsgIn["queue:msg_in"] + RnrTopic["topic:runnerX"] -->|subscribed by| Rnr + queueV["queue:v"] -->|local jobs| Rnr + queuePython["queue:python"] -->|local jobs| Rnr + end + + A -->|creates / reads| Fl + A -->|creates / reads| Msg + A -->|creates / reads| Rnr + A -->|creates / reads| Job + Fl -->|references| Job + Msg -->|may embed| Job + Rnr -->|executes| Job + Job -->|updates| Fl + Msg -->|carries result back to| A +``` + +### 2.3 Flow‑status life‑cycle (state diagram) + +```mermaid +%%{init: {"theme":"dark"}}%% +stateDiagram-v2 + [*] --> dispatched + dispatched --> waiting_for_prerequisites : has prereqs + waiting_for_prerequisites --> started : prereqs met + dispatched --> started : no prereqs + started --> finished : success + started --> error : failure + waiting_for_prerequisites --> error : timeout / impossible + error --> [*] + finished --> [*] +``` + +--- + +## 3️⃣ Redis objects – concrete key & data layout + +All objects are stored as **hashes** (`HSET`). Below is a concise catalog that can be copied into a design doc. + +| Key pattern | Example | Fields (type) | Comments | +|-------------|---------|---------------|----------| +| `actor:${id}` | `actor:12` | `id` u32, `pubkey` str, `address` list\, `created_at` u32, `updated_at` u32 | One hash per actor. | +| `context:${id}` | `context:7` | `id` u32, `admins` list\, `readers` list\, `executors` list\, `created_at` u32, `updated_at` u32 | Holds permission lists for a tenant. | +| `flow:${id}` | `flow:33` | `id` u32, `caller_id` u32, `context_id` u32, `jobs` list\, `env_vars` map\, `result` map\, `created_at` u32, `updated_at` u32, `status` str (`dispatched|started|error|finished`) | +| `message:${caller_id}:${id}` | `message:12:101` | `id` u32, `caller_id` u32, `context_id` u32, `message` str, `message_type` str (`job|chat|mail`), `message_format_type` str (`html|text|md`), `timeout` u32, `timeout_ack` u32, `timeout_result` u32, `job` list\ (serialized), `logs` list\, `created_at` u32, `updated_at` u32, `status` str (`dispatched|acknowledged|error|processed`) | +| `runner:${id}` | `runner:20` | `id` u32, `pubkey` str, `address` str, `topic` str, `local` bool, `created_at` u32, `updated_at` u32 | +| `job:${caller_id}:${id}` | `job:12:2001` | `id` u32, `caller_id` u32, `context_id` u32, `script` str, `script_type` str (`osis|sal|v|python`), `timeout` u32, `retries` u8, `env_vars` map\, `result` map\, `prerequisites` list\, `dependends` list\, `created_at` u32, `updated_at` u32, `status` str (`dispatched|waiting_for_prerequisites|started|error|finished`) | + +#### Queue objects (lists) + +| Queue name | Purpose | +|------------|---------| +| `msg_out` | **Outbound** generic queue – every `Message` that an actor wants to send is pushed here. | +| `msg_in` | **Inbound** generic queue – every message received from Mycelium is placed here for the local consumer to process. | +| `queue:${suffix}` (e.g. `queue:v`, `queue:python`) | Local job queues used by a **Runner** when `local == true`. The suffix comes from `ScriptType.queue_suffix()`. | + +--- + +## 4️⃣ System specification (as a concise “specs” section) + +### 4.1 Naming conventions +* All Redis **hashes** are prefixed with the object name (`actor:`, `context:`, …). +* All **queues** are simple Redis lists (`LPUSH` / `RPOP`). +* **Message** keys embed both the *caller* and a locally unique *message id* – this guarantees global uniqueness across contexts. + +### 4.2 Permissions & security +* Only IDs present in `Context.admins` may **create** or **delete** any object inside that context. +* `Context.readers` can **GET** any hash but not modify it. +* `Context.executors` are allowed to **update** `RunnerJob.status`, `result` and to **pop** from local job queues. +* Every `Actor` must present a `pubkey` that can be verified by the receiving side (Mycelium uses asymmetric crypto). + + + +### 4.3 Message flow (publish / consume) + + + +Below is a **re‑written “Message flow (publish / consume)”** that reflects the real runtime components: + +* **Supervisor daemon** – runs on the node that owns the **Flow** (the *actor’s* side). + It is the only process that ever **RPOP**s from the global `msg_out` queue, adds the proper routing information and hands the message to **Mycelium**. + +* **Mycelium** – the pure pub/sub/message‑bus. It never touches Redis directly; it only receives a *payload key* from the coordinator and delivers that key to the remote tenant’s `msg_in` list. + +* **Remote‑side runner / service** – consumes from its own `msg_in`, materialises the job and executes it. + +The table now uses the exact component names and adds a short note about the permission check that the coordinator performs before it releases a message. + +| # | Action (what the system does) | Component that performs it | Redis interaction (exact commands) | +|---|-------------------------------|----------------------------|------------------------------------| +| **1️⃣ Publish** | Actor creates a `Message` hash and **LPUSH**es its key onto the *outbound* queue. | **Actor** (client code) | `HSET message:12:101 …`
`LPUSH msg_out message:12:101` | +| **2️⃣ Coordinate & route** | The **Supervisor daemon** (running at source) **RPOP**s the key, checks the actor’s permissions, adds the *target‑context* and *topic* fields, then forwards the key to Mycelium. | **Supervisor daemon** (per‑actor) | `RPOP msg_out` → (in‑process) → `LPUSH msg_out_coordinator ` (internal buffer) | +| **3️⃣ Transport** | Mycelium receives the key, looks at `Message.message_type` (or the explicit `topic`) and pushes the key onto the *inbound* queue of the **remote** tenant. | **Mycelium bus** (network layer) | `LPUSH msg_in: ` | +| **4️⃣ Consume** | The **Remote side** (runner or service) **RPOP**s from its `msg_in`, loads the full hash, verifies the actor’s signature and decides what to do based on `message_type`. | **Remote consumer** (runner / service | `RPOP msg_in:` → `HGETALL message:` | +| **5️⃣ Job materialisation** | If `message_type == "job"` the consumer creates a **RunnerJob** entry inside the **remote** context, adds the job **key** to the proper *script‑type* queue (`queue:v`, `queue:python`, …). | **Remote consumer** | `HSET job:: …`
`LPUSH queue: job::` | +| **6️⃣ Runner execution loop** | A **Runner** attached to that remote context **BRPOP**s from its script‑type queue, sets `status = started`, runs the script, writes `result` and final `status`. | **Runner** | `BRPOP queue:` → `HSET job:<…> status started` → … → `HSET job:<…> result … status finished` | +| **7️⃣ Result notification** | The runner builds a new `Message` (type `chat`, `result`, …) and pushes it onto **msg_out** again. The **Supervisor daemon** on the *originating* side will later pick it up and route it back to the original actor. | **Runner** → **Supervisor (remote side)** → **Mycelium** → **Supervisor (origin side)** → **Actor** | `HSET message: …`
`LPUSH msg_out message:` (steps 2‑3 repeat in reverse direction) | + +--- + +## Tiny end‑to‑end sequence (still simple enough to render) + +```mermaid +%%{init: {"theme":"dark"}}%% +sequenceDiagram + participant A as Actor + participant L as Local‑Redis (Flow ctx) + participant C as Supervisor daemon (local) + participant M as Mycelium bus + participant R as Remote‑Redis (target ctx) + participant W as Runner (remote) + + %% 1️⃣ publish + A->>L: HSET message:12:101 … + A->>L: LPUSH msg_out message:12:101 + + %% 2️⃣ coordinate + C->>L: RPOP msg_out + C->>C: check permissions / add routing info + C->>M: push key to Mycelium (msg_out_coordinator) + + %% 3️⃣ transport + M->>R: LPUSH msg_in message:12:101 + + %% 4️⃣ consume + R->>W: RPOP msg_in + R->>R: HGETALL message:12:101 + R->>R: verify signature + alt message_type == job + R->>R: HSET job:12:2001 … + R->>R: LPUSH queue:v job:12:2001 + end + + %% 5️⃣ runner loop + W->>R: BRPOP queue:v (job:12:2001) + W->>R: HSET job:12:2001 status started + W->>W: execute script + W->>R: HSET job:12:2001 result … status finished + + %% 6️⃣ result back + W->>R: HSET message:12:900 result … + W->>R: LPUSH msg_out message:12:900 + C->>M: (coordinator on remote side) routes back + M->>L: LPUSH msg_in message:12:900 + A->>L: RPOP msg_in → read result +``` + + +## 5️⃣ What the **system** is trying to achieve + +| Goal | How it is realized | +|------|--------------------| +| **Decentralised execution** | Every *actor* owns a **Context**; any number of **Runners** can be attached to that context, possibly on different machines, and they all talk over the same Mycelium/Redis backend. | +| **Fine‑grained permissions** | `Context.admins/readers/executors` enforce who can create, view or run jobs. | +| **Loose coupling via messages** | All actions (job submission, result propagation, chat, mail …) use the generic `Message` object; the same transport pipeline handles all of them. | +| **Workflow orchestration** | The **Flow** object models a DAG of jobs, tracks collective status and aggregates results, without needing a central scheduler. | +| **Pluggable runtimes** | `ScriptType` and `RunnerType` let a runner choose the proper execution environment (V, Python, OSIS, Rust, …) – adding a new language only means adding a new `ScriptType` and a corresponding worker. | +| **Observability** | `Log` arrays attached to a `Message` and the timestamps on every hash give a complete audit trail. | +| **Resilience** | Jobs are idempotent hash entries; queues are persisted in Redis, and status changes are atomic (`HSET`). Retries and time‑outs guarantee eventual consistency. | + +--- + +## 6️⃣ Diagram summary (quick visual cheat‑sheet) + +```mermaid +%%{init: {"theme":"dark"}}%% +graph TD + A[Actor] -->|creates| Ctx[Context] + A -->|creates| Flow + A -->|creates| Msg + A -->|creates| Rnr[Runner] + A -->|creates| Job[RunnerJob] + + subgraph Redis["Redis (per Context)"] + Ctx --> A + Ctx --> Flow + Ctx --> Msg + Ctx --> Rnr + Ctx --> Job + end + + Msg -->|push to| OutQ[msg_out] + OutQ --> Myc[Mycelium Bus] + Myc -->|deliver| InQ[msg_in] + InQ --> Rnr + Rnr -->|pop from| Qv["queue:v"] + Rnr -->|pop from| Qpy["queue:python"] + + Rnr -->|updates| Job + Job -->|updates| Flow + Flow -->|result Message| Msg +``` + diff --git a/lib/osal/screen/factory.v b/lib/osal/screen/factory.v index e8393e47..abcc1a85 100644 --- a/lib/osal/screen/factory.v +++ b/lib/osal/screen/factory.v @@ -5,7 +5,8 @@ import freeflowuniverse.herolib.core.texttools // import freeflowuniverse.herolib.screen import os import time -import freeflowuniverse.herolib.ui.console +// import freeflowuniverse.herolib.ui.console +import freeflowuniverse.herolib.osal.core as osal @[heap] pub struct ScreensFactory { @@ -54,11 +55,12 @@ pub fn (mut self ScreensFactory) scan() ! { return } // there is stuff to parses - + // println(res.output) res1 := texttools.remove_empty_lines(res.output) .split_into_lines() .filter(it.starts_with(' ') || it.starts_with('\t')) .join_lines() + // println(res1) mut res2 := texttools.to_list_map('pre,state', res1, '').map(init_screen_object(it)) for mut item in res2 { if self.exists(item.name) { @@ -105,7 +107,6 @@ pub fn (mut self ScreensFactory) add(args_ ScreenAddArgs) !Screen { mut myscreen := self.get(args.name) or { return error('couldnt start screen with name ${args.name}, was not found afterwards.\ncmd:${args.cmd}\nScreens found.\n${self.str()}') } - if args.attach { myscreen.attach()! } @@ -133,19 +134,23 @@ pub fn (mut self ScreensFactory) get(name string) !Screen { } pub fn (mut self ScreensFactory) start(name string) ! { + mut s := self.get(name) or { return error("can't start screen with name:${name}, couldn't find.\nScreens found.\n${self.str()}") } s.start_()! + + osal.sleep(1) + for { self.scan()! + mut s2 := self.get(name) or { return error('couldnt start screen with name ${name}, was not found in screen scan.\ncmd:\n${s.cmd}\nScreens found.\n${self.str()}') } if s2.pid > 0 { return } - console.print_debug(s2.str()) time.sleep(100000) } } diff --git a/lib/osal/startupmanager/model.v b/lib/osal/startupmanager/model.v new file mode 100644 index 00000000..9fef21ea --- /dev/null +++ b/lib/osal/startupmanager/model.v @@ -0,0 +1,39 @@ +module startupmanager + +pub enum StartupManagerType { + unknown + screen + zinit + tmux + systemd + auto +} + +@[params] +pub struct ZProcessNewArgs { +pub mut: + name string @[required] + cmd string @[required] + cmd_stop string // command to stop (optional) + cmd_test string // command line to test service is running + workdir string // where to execute the commands + after []string // list of service we depend on + env map[string]string + oneshot bool + start bool = true + restart bool = true // whether the process should be restarted on failure + description string // not used in zinit + startuptype StartupManagerType +} + +fn startup_manager_type_get(c string) StartupManagerType { + match c { + "unknown" { return .unknown } + "screen" { return .screen } + "zinit" { return .zinit } + "tmux" { return .tmux } + "systemd" { return .systemd } + "auto" { return .auto } + else { return .unknown } + } +} \ No newline at end of file diff --git a/lib/osal/startupmanager/readme.md b/lib/osal/startupmanager/readme.md index 29064ec5..3e94069e 100644 --- a/lib/osal/startupmanager/readme.md +++ b/lib/osal/startupmanager/readme.md @@ -1,16 +1,232 @@ -# startup manager +# Startup Manager -```go +The `startupmanager` module provides a unified interface for managing processes across different underlying startup systems like `screen`, `systemd`, and `zinit`. It abstracts away the complexities of each system, allowing you to start, stop, restart, delete, and query the status of processes using a consistent API. + +## How it Works + +The `StartupManager` struct acts as a facade, delegating calls to the appropriate underlying startup system based on the `StartupManagerType` configured or automatically detected. + +When you create a new `StartupManager` instance using `startupmanager.get()`, it attempts to detect if `zinit` is available on the system. If `zinit` is found, it will be used as the default startup manager. Otherwise, it falls back to `screen`. You can also explicitly specify the desired `StartupManagerType` during initialization. + +The `ZProcessNewArgs` struct defines the parameters for creating and managing a new process. + +## Usage + +### Initializing the Startup Manager + +You can initialize the `StartupManager` in a few ways: + +1. **Automatic Detection (Recommended):** + The manager will automatically detect if `zinit` is available and use it, otherwise it defaults to `screen`. + + ```v + import freeflowuniverse.herolib.osal.startupmanager + + fn main() { + mut sm := startupmanager.get(cat:.screen)! + // sm.cat will be .zinit or .screen + println("Using startup manager: ${sm.cat}") + } + ``` + +2. **Explicitly Specify Type:** + You can force the manager to use a specific type. + + ```v + import freeflowuniverse.herolib.osal.startupmanager + + fn main() { + mut sm_zinit := startupmanager.get(cat: .zinit)! + println("Using startup manager: ${sm_zinit.cat}") + + mut sm_screen := startupmanager.get(cat: .screen)! + println("Using startup manager: ${sm_screen.cat}") + + mut sm_systemd := startupmanager.get(cat: .systemd)! + println("Using startup manager: ${sm_systemd.cat}") + } + ``` + +### Managing Processes + +The following examples demonstrate how to use the `StartupManager` to interact with processes. The `new` method takes a `ZProcessNewArgs` struct to define the process. + +#### `new(args ZProcessNewArgs)`: Launch a new process + +This method creates and optionally starts a new process. + +```v import freeflowuniverse.herolib.osal.startupmanager -mut sm:=startupmanager.get()! +fn main() { + mut sm := startupmanager.get()! -sm.start( - name: 'myscreen' - cmd: 'htop' - description: '...' -)! + // Example: Starting a simple web server with zinit + sm.new( + name: "my_web_server" + cmd: "python3 -m http.server 8000" + start: true + restart: true + description: "A simple Python HTTP server" + startuptype: .zinit // Explicitly use zinit for this process + )! + println("Web server 'my_web_server' started with ${sm.cat}") + // Example: Starting a long-running script with screen + sm.new( + name: "my_background_script" + cmd: "bash -c 'while true; do echo Hello from script; sleep 5; done'" + start: true + restart: true + startuptype: .screen // Explicitly use screen for this process + )! + println("Background script 'my_background_script' started with ${sm.cat}") + + // Example: Starting a systemd service (requires root privileges and proper systemd setup) + // This assumes you have a systemd unit file configured for 'my_systemd_service' + // For example, a file like /etc/systemd/system/my_systemd_service.service + // [Unit] + // Description=My Systemd Service + // After=network.target + // + // [Service] + // ExecStart=/usr/bin/python3 -m http.server 8080 + // Restart=always + // + // [Install] + // WantedBy=multi-user.target + sm.new( + name: "my_systemd_service" + cmd: "python3 -m http.server 8080" // This command is used to generate the unit file if it doesn't exist + start: true + restart: true + startuptype: .systemd + )! + println("Systemd service 'my_systemd_service' created/started with ${sm.cat}") +} ``` +#### `start(name string)`: Start a process +Starts an existing process. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + sm.start("my_web_server")! + println("Process 'my_web_server' started.") +} +``` + +#### `stop(name string)`: Stop a process + +Stops a running process. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + sm.stop("my_web_server")! + println("Process 'my_web_server' stopped.") +} +``` + +#### `restart(name string)`: Restart a process + +Restarts a process. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + sm.restart("my_web_server")! + println("Process 'my_web_server' restarted.") +} +``` + +#### `delete(name string)`: Delete a process + +Removes a process from the startup manager. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + sm.delete("my_web_server")! + println("Process 'my_web_server' deleted.") +} +``` + +#### `status(name string) !ProcessStatus`: Get process status + +Returns the current status of a process. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + status := sm.status("my_web_server")! + println("Status of 'my_web_server': ${status}") +} +``` + +#### `running(name string) !bool`: Check if process is running + +Returns `true` if the process is active, `false` otherwise. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + is_running := sm.running("my_web_server")! + println("Is 'my_web_server' running? ${is_running}") +} +``` + +#### `output(name string) !string`: Get process output + +Retrieves the output (logs) of a process. Currently supported for `systemd`. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get(startupmanager.StartupManagerArgs{cat: .systemd})! + output := sm.output("my_systemd_service")! + println("Output of 'my_systemd_service':\n${output}") +} +``` + +#### `exists(name string) !bool`: Check if process exists + +Returns `true` if the process is known to the startup manager, `false` otherwise. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + does_exist := sm.exists("my_web_server")! + println("Does 'my_web_server' exist? ${does_exist}") +} +``` + +#### `list() ![]string`: List all managed services + +Returns a list of names of all services managed by the startup manager. + +```v +import freeflowuniverse.herolib.osal.startupmanager + +fn main() { + mut sm := startupmanager.get()! + services := sm.list()! + println("Managed services: ${services}") +} \ No newline at end of file diff --git a/lib/osal/startupmanager/startupmanager.v b/lib/osal/startupmanager/startupmanager.v index 2aaffae9..82e92578 100644 --- a/lib/osal/startupmanager/startupmanager.v +++ b/lib/osal/startupmanager/startupmanager.v @@ -7,7 +7,7 @@ import freeflowuniverse.herolib.osal.zinit // // TODO: check if using this interface would simplify things // pub interface StartupManagerI { -// new(args zinit.ZProcessNewArgs)! +// new(args startupmanager.ZProcessNewArgs)! // start(name string)! // stop(name string)! // restart(name string)! @@ -19,35 +19,32 @@ import freeflowuniverse.herolib.osal.zinit // list_services() ![]string // } -pub enum StartupManagerType { - unknown - screen - zinit - tmux - systemd -} - pub struct StartupManager { pub mut: cat StartupManagerType } -@[params] -pub struct StartupManagerArgs { -pub mut: - cat StartupManagerType -} +// @[params] +// pub struct StartupManagerArgs { +// pub mut: +// cat StartupManagerType +// } -pub fn get(args StartupManagerArgs) !StartupManager { +pub fn get(cat StartupManagerType) !StartupManager { + console.print_debug('startupmanager get ${cat}') mut sm := StartupManager{ - cat: args.cat + cat: cat } - if args.cat == .unknown { + if sm.cat == .auto { if zinit.check() { sm.cat = .zinit } else { sm.cat = .screen } + } + if sm.cat == .unknown { + print_backtrace() + return error("can't determine startup manager type, need to be a known one.") } return sm } @@ -67,12 +64,9 @@ pub fn get(args StartupManagerArgs) !StartupManager { // restart bool = true // whether the process should be restarted on failure // description string //not used in zinit //``` -pub fn (mut sm StartupManager) new(args zinit.ZProcessNewArgs) ! { +pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! { console.print_debug("startupmanager start:${args.name} cmd:'${args.cmd}' restart:${args.restart}") mut mycat := sm.cat - if args.startuptype == .systemd { - mycat = .systemd - } match mycat { .screen { mut scr := screen.new(reset: false)! @@ -83,40 +77,33 @@ pub fn (mut sm StartupManager) new(args zinit.ZProcessNewArgs) ! { // console.print_debug('systemd start ${args.name}') mut systemdfactory := systemd.new()! systemdfactory.new( - cmd: args.cmd - name: args.name - description: args.description - start: args.start - restart: args.restart - env: args.env + cmd: args.cmd + name: args.name + start: args.start + restart: args.restart + env: args.env )! } .zinit { console.print_debug('zinit start ${args.name}') mut zinitfactory := zinit.new()! - // pub struct ZProcessNewArgs { - // name string @[required] - // cmd string @[required] - // cmd_stop string - // cmd_test string - // cmd_file bool // if we wanna force to run it as a file which is given to bash -c (not just a cmd in zinit) - // test string - // test_file bool - // after []string - // env map[string]string - // oneshot bool - // } - zinitfactory.new(args)! + zinitfactory.new( + name: args.name + cmd: args.cmd + cmd_stop: args.cmd_stop + cmd_test: args.cmd_test + workdir: args.workdir + after: args.after + env: args.env + oneshot: args.oneshot + start: args.start + restart: args.restart + )! } else { panic('to implement, startup manager only support screen & systemd for now: ${mycat}') } } - // if args.start { - // sm.start(args.name)! - // } else if args.restart { - // sm.restart(args.name)! - // } } pub fn (mut sm StartupManager) start(name string) ! { @@ -309,7 +296,7 @@ pub fn (mut sm StartupManager) output(name string) !string { } pub fn (mut sm StartupManager) exists(name string) !bool { - println(sm.cat) + if sm.cat == .unknown { if zinit.check() { sm.cat = .zinit @@ -359,30 +346,3 @@ pub fn (mut sm StartupManager) list() ![]string { } } } - -// THIS IS PROBABLY PART OF OTHER MODULE NOW - -// pub struct SecretArgs { -// pub mut: -// name string @[required] -// cat SecretType -// } - -// pub enum SecretType { -// normal -// } - -// // creates a secret if it doesn exist yet -// pub fn (mut sm StartupManager) secret(args SecretArgs) !string { -// if !(sm.exists(args.name)) { -// return error("can't find screen with name ${args.name}, for secret") -// } -// key := 'secrets:startup:${args.name}' -// mut redis := redisclient.core_get()! -// mut secret := redis.get(key)! -// if secret.len == 0 { -// secret = rand.hex(16) -// redis.set(key, secret)! -// } -// return secret -// } diff --git a/lib/osal/zinit/implementation_plan.md b/lib/osal/zinit/implementation_plan.md deleted file mode 100644 index c540dac6..00000000 --- a/lib/osal/zinit/implementation_plan.md +++ /dev/null @@ -1,224 +0,0 @@ -# Implementation Plan: Zinit OpenRPC Client Refactoring - -## Current State Analysis -- Multiple implementations (zinit.v, zinit_stateless.v, rpc.v, zprocess.v) -- Inconsistent use of OpenRPC vs. direct filesystem operations -- Duplication of functionality across multiple files -- Lack of a unified approach - -## Implementation Plan - -### Phase 1: Create a New Unified OpenRPC Client -1. Create a new file `zinit_client.v` with a unified `ZinitClient` struct -2. Implement all methods using the OpenRPC protocol exclusively -3. Ensure the client handles all error cases properly -4. Add comprehensive documentation for all methods - -```mermaid -graph TD - A[Create New OpenRPC Client] --> B[Implement Core Client Methods] - B --> C[Implement Service Management Methods] - C --> D[Implement Configuration Management Methods] - D --> E[Implement System Operations Methods] - E --> F[Implement Logging Methods] -``` - -### Phase 2: Refactor Existing Implementations -1. Refactor `ZinitStateless` to use the new client for all operations -2. Refactor `Zinit` to use the new client for all operations -3. Refactor `ZProcess` to use the new client for all operations -4. Update factory methods to use the new client -5. Ensure backward compatibility by maintaining the same API/interface - -```mermaid -graph TD - A[Refactor ZinitStateless] --> B[Refactor Zinit] - B --> C[Refactor ZProcess] - C --> D[Update Factory Methods] - D --> E[Ensure Backward Compatibility] -``` - -### Phase 3: Update Tests and Examples -1. Update existing tests to use the new client -2. Add new tests to cover all OpenRPC methods -3. Update examples to demonstrate the new client -4. Create new examples to showcase best practices - -```mermaid -graph TD - A[Update Unit Tests] --> B[Update Integration Tests] - B --> C[Update Examples] - C --> D[Create New Examples] -``` - -### Phase 4: Documentation and Cleanup -1. Update the README with comprehensive documentation -2. Add detailed API documentation for all methods -3. Add usage examples for common scenarios -4. Mark old implementations as deprecated (with a migration guide) - -```mermaid -graph TD - A[Update README] --> B[Add API Documentation] - B --> C[Add Usage Examples] - C --> D[Mark Deprecated Code] -``` - -## Detailed Implementation Steps - -### 1. Create New OpenRPC Client (zinit_client.v) - -```v -module zinit - -import freeflowuniverse.herolib.schemas.jsonrpc -import json - -// ZinitClient is a unified client for interacting with Zinit using OpenRPC -pub struct ZinitClient { -pub mut: - rpc_client &jsonrpc.Client -} - -// new_client creates a new Zinit OpenRPC client -pub fn new_client(socket_path string) ZinitClient { - mut cl := jsonrpc.new_unix_socket_client(socket_path) - return ZinitClient{ - rpc_client: cl - } -} - -// Implement all OpenRPC methods... -``` - -### 2. Refactor ZinitStateless (zinit_stateless.v) - -```v -module zinit - -import freeflowuniverse.herolib.core.pathlib - -@[params] -pub struct ZinitConfig { - path string = '/etc/zinit' - pathcmds string = '/etc/zinit/cmds' - socket_path string = default_socket_path -} - -pub struct ZinitStateless { -pub mut: - client ZinitClient - path pathlib.Path - pathcmds pathlib.Path -} - -pub fn new_stateless(z ZinitConfig) !ZinitStateless { - return ZinitStateless{ - client: new_client(z.socket_path) - path: pathlib.get_dir(path: z.path, create: true)! - pathcmds: pathlib.get_dir(path: z.pathcmds, create: true)! - } -} - -// Refactor methods to use the OpenRPC client... -``` - -### 3. Refactor Zinit (zinit.v) - -```v -module zinit - -import freeflowuniverse.herolib.core.pathlib - -@[heap] -pub struct Zinit { -pub mut: - processes map[string]ZProcess - path pathlib.Path - pathcmds pathlib.Path - client ZinitClient -} - -// Refactor methods to use the OpenRPC client... -``` - -### 4. Refactor ZProcess (zprocess.v) - -```v -module zinit - -pub struct ZProcess { -pub: - name string = 'default' -pub mut: - cmd string - cmd_stop string - cmd_test string - workdir string - status ZProcessStatus - pid int - after []string - env map[string]string - oneshot bool - start bool = true - restart bool = true - description string - client &ZinitClient -} - -// Refactor methods to use the OpenRPC client... -``` - -## Key Changes Required - -1. **Replace Direct Filesystem Operations**: - - Replace file creation/modification with `service_create` OpenRPC calls - - Replace file deletion with `service_delete` OpenRPC calls - - Replace file reading with `service_get` OpenRPC calls - -2. **Replace Shell Commands**: - - Replace `zinit list` shell commands with `service_list` OpenRPC calls - - Replace `zinit status` shell commands with `service_status` OpenRPC calls - - Replace `zinit log` shell commands with `stream_currentLogs` OpenRPC calls - -3. **Unify Error Handling**: - - Implement consistent error handling across all methods - - Properly propagate OpenRPC error responses to the caller - -4. **Maintain Backward Compatibility**: - - Keep the same method signatures for public methods - - Ensure the same behavior for all methods - - Add deprecation notices for methods that will be removed in the future - -## Testing Strategy - -1. **Unit Tests**: - - Test each OpenRPC method individually - - Test error handling for each method - - Test with mock responses for predictable testing - -2. **Integration Tests**: - - Test with a real Zinit instance - - Test the full lifecycle of services (create, start, status, stop, delete) - - Test edge cases and error conditions - -3. **Backward Compatibility Tests**: - - Test existing code that uses the old implementations - - Ensure no regressions in functionality - -## Documentation Updates - -1. **README.md**: - - Update with comprehensive documentation - - Add examples for common use cases - - Add migration guide for users of the old implementations - -2. **API Documentation**: - - Document all public methods - - Document all structs and their fields - - Document error conditions and how to handle them - -3. **Examples**: - - Update existing examples - - Add new examples for common use cases - - Add examples for error handling \ No newline at end of file diff --git a/lib/osal/zinit/readme.md b/lib/osal/zinit/readme.md index eefe4c4a..679f4315 100644 --- a/lib/osal/zinit/readme.md +++ b/lib/osal/zinit/readme.md @@ -22,7 +22,7 @@ Zinit is a process manager that allows you to manage services on a system. This ### Basic Usage ```v -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager fn main() { // Create a new Zinit client with the default socket path @@ -47,7 +47,7 @@ fn main() { ### Creating a New Service ```v -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager fn main() { mut zinit_client := zinit.new_stateless()! @@ -77,7 +77,7 @@ fn main() { ### Getting Service Statistics ```v -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager fn main() { mut zinit_client := zinit.new_stateless()! @@ -98,7 +98,7 @@ fn main() { ### Retrieving Logs ```v -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager fn main() { mut zinit_client := zinit.new_stateless()! diff --git a/lib/osal/zinit/zinit.v b/lib/osal/zinit/zinit.v index 03d46bc4..5f8e7f69 100644 --- a/lib/osal/zinit/zinit.v +++ b/lib/osal/zinit/zinit.v @@ -15,6 +15,21 @@ pub mut: pathcmds pathlib.Path } +@[params] +pub struct ZProcessNewArgs { +pub mut: + name string @[required] + cmd string @[required] + cmd_stop string // command to stop (optional) + cmd_test string // command line to test service is running + workdir string // where to execute the commands + after []string // list of service we depend on + env map[string]string + oneshot bool + start bool = true + restart bool = true // whether the process should be restarted on failure +} + // will delete the process if it exists while starting pub fn (mut zinit Zinit) new(args_ ZProcessNewArgs) !ZProcess { console.print_header(' zinit process new') diff --git a/lib/osal/zinit/zprocess.v b/lib/osal/zinit/zprocess.v index f4760de0..2690e3dd 100644 --- a/lib/osal/zinit/zprocess.v +++ b/lib/osal/zinit/zprocess.v @@ -34,30 +34,6 @@ pub enum ZProcessStatus { spawned } -pub enum StartupManagerType { - unknown - zinit - systemd - screen -} - -@[params] -pub struct ZProcessNewArgs { -pub mut: - name string @[required] - cmd string @[required] - cmd_stop string // command to stop (optional) - cmd_test string // command line to test service is running - workdir string // where to execute the commands - after []string // list of service we depend on - env map[string]string - oneshot bool - start bool = true - restart bool = true // whether the process should be restarted on failure - description string // not used in zinit - startuptype StartupManagerType -} - pub fn (zp ZProcess) cmd() !string { mut zinitobj := new()! mut path := zinitobj.pathcmds.file_get_new('${zp.name}_start.sh')! diff --git a/lib/installers/infra/dify/.heroscript b/libarchive/dify/.heroscript similarity index 100% rename from lib/installers/infra/dify/.heroscript rename to libarchive/dify/.heroscript diff --git a/lib/installers/infra/dify/dify_actions.v b/libarchive/dify/dify_actions.v similarity index 96% rename from lib/installers/infra/dify/dify_actions.v rename to libarchive/dify/dify_actions.v index 5c39b825..62bb0d51 100644 --- a/lib/installers/infra/dify/dify_actions.v +++ b/libarchive/dify/dify_actions.v @@ -5,7 +5,7 @@ import freeflowuniverse.herolib.ui.console import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.osal.systemd -import freeflowuniverse.herolib.osal.zinit +import freeflowuniverse.herolib.osal.startupmanager import freeflowuniverse.herolib.installers.ulist import freeflowuniverse.herolib.installers.lang.golang import freeflowuniverse.herolib.installers.lang.rust @@ -17,7 +17,8 @@ fn startupcmd() ![]zinit.ZProcessNewArgs { mut installer := get()! mut res := []zinit.ZProcessNewArgs{} mut cfg := get()! - res << zinit.ZProcessNewArgs{ + res << zinit.ZProcessNewArgs + { name: 'docker' cmd: 'dockerd' startuptype: .systemd @@ -31,11 +32,13 @@ fn startupcmd() ![]zinit.ZProcessNewArgs { cd ${cfg.path}/docker/ docker compose --env-file ${cfg.path}/docker/.env up " - res << zinit.ZProcessNewArgs{ + res << zinit.ZProcessNewArgs + { name: 'dify' cmd: cmd startuptype: .systemd } + return res } diff --git a/lib/installers/infra/dify/dify_factory_.v b/libarchive/dify/dify_factory_.v similarity index 65% rename from lib/installers/infra/dify/dify_factory_.v rename to libarchive/dify/dify_factory_.v index 4379b5a8..14123845 100644 --- a/lib/installers/infra/dify/dify_factory_.v +++ b/libarchive/dify/dify_factory_.v @@ -3,75 +3,106 @@ module dify import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } import freeflowuniverse.herolib.ui.console +import json import freeflowuniverse.herolib.osal.startupmanager -import freeflowuniverse.herolib.osal.zinit import time -__global ( - dify_global map[string]&DifyInstaller - dify_default string -) - /////////FACTORY @[params] pub struct ArgsGet { pub mut: - name string + name string = 'default' + fromdb bool // will load from filesystem + create bool // default will not create if not exist } -fn args_get(args_ ArgsGet) ArgsGet { - mut args := args_ - if args.name == '' { - args.name = 'default' - } - return args -} - -pub fn get(args_ ArgsGet) !&DifyInstaller { - mut context := base.context()! - mut args := args_get(args_) +pub fn new(args ArgsGet) !&DifyInstaller { mut obj := DifyInstaller{ name: args.name } - if args.name !in dify_global { - if !exists(args)! { - set(obj)! + set(obj)! + return &obj +} + +pub fn get(args ArgsGet) !&DifyInstaller { + mut context := base.context()! + dify_default = args.name + if args.fromdb || args.name !in dify_global { + mut r := context.redis()! + if r.hexists('context:dify', args.name)! { + data := r.hget('context:dify', args.name)! + if data.len == 0 { + return error('DifyInstaller with name: dify does not exist, prob bug.') + } + mut obj := json.decode(DifyInstaller, data)! + set_in_mem(obj)! } else { - heroscript := context.hero_config_get('dify', args.name)! - mut obj_ := heroscript_loads(heroscript)! - set_in_mem(obj_)! + if args.create { + new(args)! + } else { + return error("DifyInstaller with name 'dify' does not exist") + } } + return get(name: args.name)! // no longer from db nor create } return dify_global[args.name] or { - println(dify_global) - // bug if we get here because should be in globals - panic('could not get config for dify with name, is bug:${args.name}') + return error('could not get config for dify with name:dify') } } // register the config for the future pub fn set(o DifyInstaller) ! { set_in_mem(o)! + dify_default = o.name mut context := base.context()! - heroscript := heroscript_dumps(o)! - context.hero_config_set('dify', o.name, heroscript)! + mut r := context.redis()! + r.hset('context:dify', o.name, json.encode(o))! } // does the config exists? -pub fn exists(args_ ArgsGet) !bool { +pub fn exists(args ArgsGet) !bool { mut context := base.context()! - mut args := args_get(args_) - return context.hero_config_exists('dify', args.name) + mut r := context.redis()! + return r.hexists('context:dify', args.name)! } -pub fn delete(args_ ArgsGet) ! { - mut args := args_get(args_) +pub fn delete(args ArgsGet) ! { mut context := base.context()! - context.hero_config_delete('dify', args.name)! - if args.name in dify_global { - // del dify_global[args.name] + mut r := context.redis()! + r.hdel('context:dify', args.name)! +} + +@[params] +pub struct ArgsList { +pub mut: + fromdb bool // will load from filesystem +} + +// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem +pub fn list(args ArgsList) ![]&DifyInstaller { + mut res := []&DifyInstaller{} + mut context := base.context()! + if args.fromdb { + // reset what is in mem + dify_global = map[string]&DifyInstaller{} + dify_default = '' } + if args.fromdb { + mut r := context.redis()! + mut l := r.hkeys('context:dify')! + + for name in l { + res << get(name: name, fromdb: true)! + } + return res + } else { + // load from memory + for _, client in dify_global { + res << client + } + } + return res } // only sets in mem, does not set as config @@ -82,6 +113,9 @@ fn set_in_mem(o DifyInstaller) ! { } pub fn play(mut plbook PlayBook) ! { + if !plbook.exists(filter: 'dify.') { + return + } mut install_actions := plbook.find(filter: 'dify.configure')! if install_actions.len > 0 { for install_action in install_actions { @@ -90,7 +124,6 @@ pub fn play(mut plbook PlayBook) ! { set(obj2)! } } - mut other_actions := plbook.find(filter: 'dify.')! for other_action in other_actions { if other_action.name in ['destroy', 'install', 'build'] { @@ -131,36 +164,38 @@ pub fn play(mut plbook PlayBook) ! { //////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager { +fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager { // unknown // screen // zinit // tmux // systemd match cat { + .screen { + console.print_debug('startupmanager: zinit') + return startupmanager.get(.screen)! + } .zinit { console.print_debug('startupmanager: zinit') - return startupmanager.get(cat: .zinit)! + return startupmanager.get(.zinit)! } .systemd { console.print_debug('startupmanager: systemd') - return startupmanager.get(cat: .systemd)! + return startupmanager.get(.systemd)! } else { console.print_debug('startupmanager: auto') - return startupmanager.get()! + return startupmanager.get(.auto)! } } } // load from disk and make sure is properly intialized pub fn (mut self DifyInstaller) reload() ! { - switch(self.name) self = obj_init(self)! } pub fn (mut self DifyInstaller) start() ! { - switch(self.name) if self.running()! { return } @@ -223,10 +258,12 @@ pub fn (mut self DifyInstaller) running() !bool { // walk over the generic processes, if not running return for zprocess in startupcmd()! { - mut sm := startupmanager_get(zprocess.startuptype)! - r := sm.running(zprocess.name)! - if r == false { - return false + if zprocess.startuptype != .screen { + mut sm := startupmanager_get(zprocess.startuptype)! + r := sm.running(zprocess.name)! + if r == false { + return false + } } } return running()! @@ -258,12 +295,4 @@ pub fn (mut self DifyInstaller) destroy() ! { // switch instance to be used for dify pub fn switch(name string) { - dify_default = name -} - -// helpers - -@[params] -pub struct DefaultConfigArgs { - instance string = 'default' } diff --git a/lib/installers/infra/dify/dify_model.v b/libarchive/dify/dify_model.v similarity index 100% rename from lib/installers/infra/dify/dify_model.v rename to libarchive/dify/dify_model.v diff --git a/lib/installers/infra/dify/readme.md b/libarchive/dify/readme.md similarity index 100% rename from lib/installers/infra/dify/readme.md rename to libarchive/dify/readme.md diff --git a/lib/installers/infra/dify/templates/atemplate.yaml b/libarchive/dify/templates/atemplate.yaml similarity index 100% rename from lib/installers/infra/dify/templates/atemplate.yaml rename to libarchive/dify/templates/atemplate.yaml