WIP: Building hero

- The work is still in progress

Co-authored-by: supermario <mariobassem12@gmail.com>
This commit is contained in:
Mahmoud Emad
2025-01-02 19:01:37 +02:00
parent b29a57ea34
commit 4c01c88b85
103 changed files with 7064 additions and 506 deletions

View File

@@ -0,0 +1,210 @@
module generic
import freeflowuniverse.herolib.ui.console
import os
import freeflowuniverse.herolib.core.pathlib
// will ask questions when not in force mode
// & generate the module
pub fn generate(args_ GeneratorArgs) ! {
mut myconsole := console.new()
mut args := args_
console.print_header('Generate code for path: ${args.path} (reset:${args.force}, force:${args.force})')
console.print_debug(args)
if args.path == '' {
args.path = os.getwd()
}
if args.name == '' {
args.name = os.base(args.path)
}
if args.force {
mut config_path0 := pathlib.get_file(path: '${args.path}/.heroscript', create: false)!
if !config_path0.exists() {
return error("can't generate in force mode (non interactive) if ${config_path0.path} not found.")
}
generate_exec(args.path, args.reset)!
return
}
console.clear()
console.print_header('Configure generation of code for a module on path:')
console.print_green('Path: ${args.path}')
console.lf()
mut config_path := pathlib.get_file(path: '${args.path}/.heroscript', create: false)!
mut pathok := false
if config_path.exists() {
console.print_stdout(config_path.read()!)
console.lf()
myyes := myconsole.ask_yesno(
description: 'We found this heroscript, do you want to make a new one?'
)!
if myyes {
config_path.delete()!
pathok = true
} else {
myyes2 := myconsole.ask_yesno(description: 'Do you want to run it?')!
if myyes2 {
generate_exec(args.path, args.reset)!
} else {
console.print_stderr('Generation aborted.')
}
return
}
}
if pathok == false {
yesno := myconsole.ask_yesno(description: 'Is this path ok?')!
if !yesno {
return error("can't continue without a valid path")
}
}
mycat := myconsole.ask_dropdown(
description: 'Category of the generator'
question: 'What is the category of the generator?'
items: [
'installer',
'client',
]
warning: 'Please select a category'
)!
if mycat == 'installer' {
args.cat = .installer
} else {
args.cat = .client
}
// if args.name==""{
// yesno := myconsole.ask_yesno(description: 'Are you happy with name ${args.name}?')!
// if !yesno {
// return error("can't continue without a valid name, rename the directory you operate in.")
// }
// }
args.classname = myconsole.ask_question(
description: 'Class name of the ${mycat}'
question: 'What is the class name of the generator e.g. MyClass ?'
warning: 'Please provide a valid class name for the generator'
minlen: 4
)!
args.title = myconsole.ask_question(
description: 'Title of the ${mycat} (optional)'
)!
if args.cat == .installer {
args.hasconfig = myconsole.ask_yesno(
description: 'Does your installer have a config (normally yes)?'
)!
}
if args.hasconfig {
args.default = myconsole.ask_yesno(
description: 'Is it ok when doing new() that a default is created (normally yes)?'
)!
args.singleton = !myconsole.ask_yesno(
description: 'Can there be multiple instances (normally yes)?'
)!
}
// args.supported_platforms = myconsole.ask_dropdown_multiple(
// description: 'Supported platforms'
// question: 'Which platforms are supported?'
// items: [
// 'osx',
// 'ubuntu',
// 'arch',
// ]
// warning: 'Please select one or more platforms'
// )!
if args.cat == .installer {
args.templates = myconsole.ask_yesno(
description: 'Will there be templates available for your installer?'
)!
args.startupmanager = myconsole.ask_yesno(
description: 'Is this an installer which will be managed by a startup mananger?'
)!
args.build = myconsole.ask_yesno(
description: 'Are there builders for the installers (compilation)'
)!
}
// args.reset = myconsole.ask_yesno(
// description: 'Reset, overwrite code.'
// question: 'This will overwrite all files in your existing dir, be carefule?'
// )!
create_heroscript(args)!
generate_exec(args.path, true)!
}
pub fn create_heroscript(args GeneratorArgs) ! {
mut script := ''
if args.cat == .installer {
script = "
!!hero_code.generate_installer
name:'${args.name}'
classname:'${args.classname}'
singleton:${if args.singleton {
'1'
} else {
'0'
}}
templates:${if args.templates { '1' } else { '0' }}
default:${if args.default {
'1'
} else {
'0'
}}
title:'${args.title}'
supported_platforms:''
reset:${if args.reset {
'1'
} else {
'0'
}}
startupmanager:${if args.startupmanager { '1' } else { '0' }}
hasconfig:${if args.hasconfig {
'1'
} else {
'0'
}}
build:${if args.build {
'1'
} else {
'0'
}}"
} else {
script = "
!!hero_code.generate_client
name:'${args.name}'
classname:'${args.classname}'
singleton:${if args.singleton {
'1'
} else {
'0'
}}
default:${if args.default { '1' } else { '0' }}
hasconfig:${if args.hasconfig {
'1'
} else {
'0'
}}
reset:${if args.reset {
'1'
} else {
'0'
}}"
}
if !os.exists(args.path) {
os.mkdir(args.path)!
}
os.write_file('${args.path}/.heroscript', script)!
}

View File

@@ -0,0 +1,78 @@
module generic
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.pathlib
fn generate_exec(path string, reset bool) ! {
mut args := args_get(path)!
console.print_debug('generate code for path: ${path}')
if reset {
args.reset = true
}
mut path_actions := pathlib.get(args.path + '/${args.name}_actions.v')
if args.reset {
path_actions.delete()!
}
if !path_actions.exists() && args.cat == .installer {
console.print_debug('write installer actions')
mut templ_1 := $tmpl('templates/objname_actions.vtemplate')
pathlib.template_write(templ_1, '${args.path}/${args.name}_actions.v', true)!
}
mut templ_2 := $tmpl('templates/objname_factory_.vtemplate')
pathlib.template_write(templ_2, '${args.path}/${args.name}_factory_.v', true)!
mut path_model := pathlib.get(args.path + '/${args.name}_model.v')
if args.reset || !path_model.exists() {
console.print_debug('write model.')
mut templ_3 := $tmpl('templates/objname_model.vtemplate')
pathlib.template_write(templ_3, '${args.path}/${args.name}_model.v', true)!
}
// TODO: check case sensistivity for delete
mut path_readme := pathlib.get(args.path + '/readme.md')
if args.reset || !path_readme.exists() {
mut templ_readme := $tmpl('templates/readme.md')
pathlib.template_write(templ_readme, '${args.path}/readme.md', true)!
}
mut path_templ_dir := pathlib.get_dir(path: args.path + '/templates', create: false)!
if args.reset {
path_templ_dir.delete()!
}
if args.templates {
if !path_templ_dir.exists() {
mut templ_6 := $tmpl('templates/atemplate.yaml')
pathlib.template_write(templ_6, '${args.path}/templates/atemplate.yaml', true)!
}
}
}
fn platform_check(args GeneratorArgs) ! {
ok := 'osx,ubuntu,arch'
ok2 := ok.split(',')
for i in args.supported_platforms {
if i !in ok2 {
return error('cannot find ${i} in choices for supported_platforms. Valid ones are ${ok}')
}
}
}
pub fn (args GeneratorArgs) platform_check_str() string {
mut out := ''
if 'osx' in args.supported_platforms {
out += 'myplatform == .osx || '
}
if 'ubuntu' in args.supported_platforms {
out += 'myplatform == .ubuntu ||'
}
if 'arch' in args.supported_platforms {
out += 'myplatform == .arch ||'
}
out = out.trim_right('|')
return out
}

View File

@@ -0,0 +1,84 @@
module generic
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
pub struct GeneratorArgs {
pub mut:
name string
classname string
default bool = true // means user can just get the object and a default will be created
title string
supported_platforms []string // only relevant for installers for now
singleton bool // means there can only be one
templates bool // means we will use templates in the installer, client doesn't do this'
reset bool // regenerate all, dangerous !!!
startupmanager bool = true
build bool
cat Cat
path string
force bool
hasconfig bool = true
}
pub enum Cat {
installer
client
}
fn args_get(path string) !GeneratorArgs {
console.print_debug('play installer code for path: ${path}')
mut config_path := pathlib.get_file(path: '${path}/.heroscript', create: false)!
if !config_path.exists() {
return error("can't find path with .heroscript in ${path}")
}
mut plbook := playbook.new(text: config_path.read()!)!
mut install_actions := plbook.find(filter: 'hero_code.generate_installer')!
if install_actions.len > 0 {
for install_action in install_actions {
mut p := install_action.params
mut args := GeneratorArgs{
name: p.get('name')!
classname: p.get('classname')!
title: p.get_default('title', '')!
default: p.get_default_true('default')
supported_platforms: p.get_list('supported_platforms')!
singleton: p.get_default_false('singleton')
templates: p.get_default_false('templates')
reset: p.get_default_false('reset')
startupmanager: p.get_default_true('startupmanager')
hasconfig: p.get_default_true('hasconfig')
build: p.get_default_false('build')
force: p.get_default_false('force')
cat: .installer
path: path
}
return args
}
}
mut client_actions := plbook.find(filter: 'hero_code.generate_client')!
if client_actions.len > 0 {
for client_action in client_actions {
mut p := client_action.params
args := GeneratorArgs{
name: p.get('name')!
classname: p.get('classname')!
title: p.get_default('title', '')!
default: p.get_default_true('default')
singleton: p.get_default_false('singleton')
reset: p.get_default_false('reset')
cat: .client
path: path
}
return args
}
}
return error("can't find hero_code.generate_client or hero_code.generate_installer in ${path}")
// return GeneratorArgs{}
}

View File

@@ -0,0 +1,86 @@
# generation framework
```bash
#will ask questions if .heroscript is not there yet
hero generate -p thepath_is_optional
# to generate without questions
hero generate -p thepath_is_optional -t client
#if installer, default is a client
hero generate -p thepath_is_optional -t installer
#when you want to scan over multiple directories
hero generate -p thepath_is_optional -t installer -s
```
there will be a ```.heroscript``` in the director you want to generate for, the format is as follows:
```hero
//for a server
!!hero_code.generate_installer
name:'daguserver'
classname:'DaguServer'
singleton:1 //there can only be 1 object in the globals, is called 'default'
templates:1 //are there templates for the installer
default:1 //can we create a default when the factory is used
title:''
supported_platforms:'' //osx, ... (empty means all)
reset:0 // regenerate all, dangerous !!!
startupmanager:1 //managed by a startup manager, default true
build:1 //will we also build the component
//or for a client
!!hero_code.generate_client
name:'mail'
classname:'MailClient'
singleton:0 //default is 0
default:1 //can we create a default when the factory is used
reset:0 // regenerate all, dangerous !!!
//or for a play
!!hero_code.generate_play
path:'' //if not used then is path where this action is found
reset:0 //if set will overwrite the play_$actor_$action_.v
actor:'mail'
action:''
model:"""
"""
```
needs to be put as .heroscript in the directories which we want to generate
## templates remarks
in templates:
- ^^ or @@ > gets replaced to @
- ?? > gets replaced to $
this is to make distinction between processing at compile time (pre-compile) or at runtime.
## call by code
to call in code
```v
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.core.generator.generic
generic.scan(path:"~/code/github/freeflowuniverse/crystallib/crystallib/installers",force:true)!
```
to run from bash
```bash
~/code/github/freeflowuniverse/crystallib/scripts/fix_installers.vsh
```

View File

@@ -0,0 +1,30 @@
module generic
import os
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.ui.console
// scan over a set of directories call the play where
pub fn scan(args_ GeneratorArgs) ! {
mut args := args_
console.print_header('Scan for generation of code for path: ${args.path} (reset:${args.force}, force:${args.force})')
if args.path.len == 0 {
args.path = os.getwd()
}
// now walk over all directories, find .heroscript
mut pathroot := pathlib.get_dir(path: args.path, create: false)!
mut plist := pathroot.list(
recursive: true
ignoredefault: false
regex: ['.heroscript']
)!
for mut p in plist.paths {
pparent := p.parent()!
args.path = pparent.path
// println("-- ${pparent}")
generate(args)!
}
}

View File

@@ -0,0 +1,5 @@
name: ??{cfg.configpath}

View File

@@ -0,0 +1,13 @@
!!hero_code.generate_installer
name:'daguserver'
classname:'DaguServer'
singleton:1 //there can only be 1 object in the globals, is called 'default'
default:1 //can we create a default when the factory is used
title:''
supported_platforms:'' //osx, ... (empty means all)
reset:0 // regenerate all, dangerous !!!
//next only relevant for installer
startupmanager:1 //managed by a startup manager, default true
templates:1 //are there templates for the installer
build:1 //will we also build the component

View File

@@ -0,0 +1,212 @@
module ${args.name}
import freeflowuniverse.herolib.osal
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.pathlib
@if args.startupmanager
import freeflowuniverse.herolib.osal.systemd
import freeflowuniverse.herolib.osal.zinit
@end
@if args.build
import freeflowuniverse.herolib.installers.ulist
import freeflowuniverse.herolib.installers.lang.golang
import freeflowuniverse.herolib.installers.lang.rust
import freeflowuniverse.herolib.installers.lang.python
@end
import os
@if args.startupmanager
fn startupcmd () ![]zinit.ZProcessNewArgs{
mut installer := get()!
mut res := []zinit.ZProcessNewArgs{}
//THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// res << zinit.ZProcessNewArgs{
// name: '${args.name}'
// cmd: '${args.name} server'
// env: {
// 'HOME': '/root'
// }
// }
return res
}
fn running() !bool {
mut installer := get()!
//THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// this checks health of ${args.name}
// curl http://localhost:3333/api/v1/s --oauth2-bearer 1234 works
// url:='http://127.0.0.1:??{cfg.port}/api/v1'
// mut conn := httpconnection.new(name: '${args.name}', url: url)!
// if cfg.secret.len > 0 {
// conn.default_header.add(.authorization, 'Bearer ??{cfg.secret}')
// }
// conn.default_header.add(.content_type, 'application/json')
// console.print_debug("curl -X 'GET' '??{url}'/tags --oauth2-bearer ??{cfg.secret}")
// r := conn.get_json_dict(prefix: 'tags', debug: false) or {return false}
// println(r)
// if true{panic("ssss")}
// tags := r['Tags'] or { return false }
// console.print_debug(tags)
// console.print_debug('${args.name} is answering.')
return false
}
fn start_pre()!{
}
fn start_post()!{
}
fn stop_pre()!{
}
fn stop_post()!{
}
@end
//////////////////// following actions are not specific to instance of the object
@if args.cat == .installer
// checks if a certain version or above is installed
fn installed() !bool {
//THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// res := os.execute('??{osal.profile_path_source_and()} ${args.name} version')
// if res.exit_code != 0 {
// return false
// }
// r := res.output.split_into_lines().filter(it.trim_space().len > 0)
// if r.len != 1 {
// return error("couldn't parse ${args.name} version.\n??{res.output}")
// }
// if texttools.version(version) == texttools.version(r[0]) {
// return true
// }
return false
}
//get the Upload List of the files
fn ulist_get() !ulist.UList {
//optionally build a UList which is all paths which are result of building, is then used e.g. in upload
return ulist.UList{}
}
//uploads to S3 server if configured
fn upload() ! {
// installers.upload(
// cmdname: '${args.name}'
// source: '??{gitpath}/target/x86_64-unknown-linux-musl/release/${args.name}'
// )!
}
fn install() ! {
console.print_header('install ${args.name}')
//THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// mut url := ''
// if osal.is_linux_arm() {
// url = 'https://github.com/${args.name}-dev/${args.name}/releases/download/v??{version}/${args.name}_??{version}_linux_arm64.tar.gz'
// } else if osal.is_linux_intel() {
// url = 'https://github.com/${args.name}-dev/${args.name}/releases/download/v??{version}/${args.name}_??{version}_linux_amd64.tar.gz'
// } else if osal.is_osx_arm() {
// url = 'https://github.com/${args.name}-dev/${args.name}/releases/download/v??{version}/${args.name}_??{version}_darwin_arm64.tar.gz'
// } else if osal.is_osx_intel() {
// url = 'https://github.com/${args.name}-dev/${args.name}/releases/download/v??{version}/${args.name}_??{version}_darwin_amd64.tar.gz'
// } else {
// return error('unsported platform')
// }
// mut dest := osal.download(
// url: url
// minsize_kb: 9000
// expand_dir: '/tmp/${args.name}'
// )!
// //dest.moveup_single_subdir()!
// mut binpath := dest.file_get('${args.name}')!
// osal.cmd_add(
// cmdname: '${args.name}'
// source: binpath.path
// )!
}
@if args.build
fn build() ! {
//url := 'https://github.com/threefoldtech/${args.name}'
// make sure we install base on the node
// if osal.platform() != .ubuntu {
// return error('only support ubuntu for now')
// }
// golang.install()!
// console.print_header('build ${args.name}')
// gitpath := gittools.get_repo(coderoot: '/tmp/builder', url: url, reset: true, pull: true)!
// cmd := '
// cd ??{gitpath}
// source ~/.cargo/env
// exit 1 #todo
// '
// osal.execute_stdout(cmd)!
//
// //now copy to the default bin path
// mut binpath := dest.file_get('...')!
// adds it to path
// osal.cmd_add(
// cmdname: 'griddriver2'
// source: binpath.path
// )!
}
@end
fn destroy() ! {
// mut systemdfactory := systemd.new()!
// systemdfactory.destroy("zinit")!
// osal.process_kill_recursive(name:'zinit')!
// osal.cmd_delete('zinit')!
// osal.package_remove('
// podman
// conmon
// buildah
// skopeo
// runc
// ')!
// //will remove all paths where go/bin is found
// osal.profile_path_add_remove(paths2delete:"go/bin")!
// osal.rm("
// podman
// conmon
// buildah
// skopeo
// runc
// /var/lib/containers
// /var/lib/podman
// /var/lib/buildah
// /tmp/podman
// /tmp/conmon
// ")!
}
@end

View File

@@ -0,0 +1,313 @@
module ${args.name}
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
@if args.cat == .installer
import freeflowuniverse.herolib.sysadmin.startupmanager
import freeflowuniverse.herolib.osal.zinit
import time
@end
__global (
${args.name}_global map[string]&${args.classname}
${args.name}_default string
)
/////////FACTORY
^^[params]
pub struct ArgsGet{
pub mut:
name string
}
@if args.hasconfig
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = ${args.name}_default
}
if args.name == ""{
args.name = "default"
}
return args
}
pub fn get(args_ ArgsGet) !&${args.classname} {
mut args := args_get(args_)
if !(args.name in ${args.name}_global) {
if args.name=="default"{
if ! config_exists(args){
if default{
config_save(args)!
}
}
config_load(args)!
}
}
return ${args.name}_global[args.name] or {
println(${args.name}_global)
panic("could not get config for ${args.name} with name:??{args.name}")
}
}
@else
pub fn get(args_ ArgsGet) !&${args.classname} {
return &${args.classname}{}
}
@end
@if args.hasconfig
fn config_exists(args_ ArgsGet) bool {
mut args := args_get(args_)
mut context:=base.context() or { panic("bug") }
return context.hero_config_exists("${args.name}",args.name)
}
fn config_load(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
mut heroscript := context.hero_config_get("${args.name}",args.name)!
play(heroscript:heroscript)!
}
fn config_save(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_set("${args.name}",args.name,heroscript_default()!)!
}
fn set(o ${args.classname})! {
mut o2:=obj_init(o)!
${args.name}_global[o.name] = &o2
${args.name}_default = o.name
}
^^[params]
pub struct PlayArgs {
pub mut:
heroscript string //if filled in then plbook will be made out of it
plbook ?playbook.PlayBook
reset bool
}
pub fn play(args_ PlayArgs) ! {
mut args:=args_
@if args.hasconfig
if args.heroscript == "" {
args.heroscript = heroscript_default()!
}
@end
mut plbook := args.plbook or {
playbook.new(text: args.heroscript)!
}
@if args.hasconfig
mut install_actions := plbook.find(filter: '${args.name}.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
mut p := install_action.params
mycfg:=cfg_play(p)!
console.print_debug("install action ${args.name}.configure\n??{mycfg}")
set(mycfg)!
}
}
@end
@if args.cat == .installer
mut other_actions := plbook.find(filter: '${args.name}.')!
for other_action in other_actions {
if other_action.name in ["destroy","install","build"]{
mut p := other_action.params
reset:=p.get_default_false("reset")
if other_action.name == "destroy" || reset{
console.print_debug("install action ${args.name}.destroy")
destroy()!
}
if other_action.name == "install"{
console.print_debug("install action ${args.name}.install")
install()!
}
}
@if args.startupmanager
if other_action.name in ["start","stop","restart"]{
mut p := other_action.params
name := p.get('name')!
mut ${args.name}_obj:=get(name:name)!
console.print_debug("action object:\n??{${args.name}_obj}")
if other_action.name == "start"{
console.print_debug("install action ${args.name}.??{other_action.name}")
${args.name}_obj.start()!
}
if other_action.name == "stop"{
console.print_debug("install action ${args.name}.??{other_action.name}")
${args.name}_obj.stop()!
}
if other_action.name == "restart"{
console.print_debug("install action ${args.name}.??{other_action.name}")
${args.name}_obj.restart()!
}
}
@end
}
@end
}
@end
@if args.cat == .installer
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# 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()!
}
}
}
@if args.hasconfig
//load from disk and make sure is properly intialized
pub fn (mut self ${args.classname}) reload() ! {
switch(self.name)
self=obj_init(self)!
}
@end
@if args.startupmanager
pub fn (mut self ${args.classname}) start() ! {
switch(self.name)
if self.running()!{
return
}
console.print_header('${args.name} start')
if ! installed()!{
install()!
}
configure()!
start_pre()!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
console.print_debug('starting ${args.name} with ??{zprocess.startuptype}...')
sm.new(zprocess)!
sm.start(zprocess.name)!
}
start_post()!
for _ in 0 .. 50 {
if self.running()! {
return
}
time.sleep(100 * time.millisecond)
}
return error('${args.name} did not install properly.')
}
pub fn (mut self ${args.classname}) install_start(args InstallArgs) ! {
switch(self.name)
self.install(args)!
self.start()!
}
pub fn (mut self ${args.classname}) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
}
pub fn (mut self ${args.classname}) restart() ! {
switch(self.name)
self.stop()!
self.start()!
}
pub fn (mut self ${args.classname}) running() !bool {
switch(self.name)
//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
}
}
return running()!
}
@end
@@[params]
pub struct InstallArgs{
pub mut:
reset bool
}
pub fn (mut self ${args.classname}) install(args InstallArgs) ! {
switch(self.name)
if args.reset || (!installed()!) {
install()!
}
}
@if args.build
pub fn (mut self ${args.classname}) build() ! {
switch(self.name)
build()!
}
@end
pub fn (mut self ${args.classname}) destroy() ! {
switch(self.name)
@if args.startupmanager
self.stop() or {}
@end
destroy()!
}
@end
//switch instance to be used for ${args.name}
pub fn switch(name string) {
${args.name}_default = name
}

View File

@@ -0,0 +1,137 @@
module ${args.name}
import freeflowuniverse.herolib.data.paramsparser
import os
pub const version = '1.14.3'
const singleton = ${args.singleton}
const default = ${args.default}
@if args.hasconfig
//TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
pub fn heroscript_default() !string {
@if args.cat == .installer
heroscript:="
!!${args.name}.configure
name:'${args.name}'
homedir: '{HOME}/hero/var/${args.name}'
configpath: '{HOME}/.config/${args.name}/admin.yaml'
username: 'admin'
password: 'secretpassword'
secret: ''
title: 'My Hero DAG'
host: 'localhost'
port: 8888
"
@else
heroscript:="
!!${args.name}.configure
name:'${args.name}'
mail_from: 'info@@example.com'
mail_password: 'secretpassword'
mail_port: 587
mail_server: 'smtp-relay.brevo.com'
mail_username: 'kristof@@incubaid.com'
"
@end
return heroscript
}
@end
//THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
@if args.cat == .installer
@[heap]
pub struct ${args.classname} {
pub mut:
name string = 'default'
@if args.hasconfig
homedir string
configpath string
username string
password string @@[secret]
secret string @@[secret]
title string
host string
port int
@end
}
@if args.hasconfig
fn cfg_play(p paramsparser.Params) !${args.classname} {
//THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
mut mycfg := ${args.classname}{
name: p.get_default('name', 'default')!
homedir: p.get_default('homedir', '{HOME}/hero/var/${args.name}')!
configpath: p.get_default('configpath', '{HOME}/hero/var/${args.name}/admin.yaml')!
username: p.get_default('username', 'admin')!
password: p.get_default('password', '')!
secret: p.get_default('secret', '')!
title: p.get_default('title', 'HERO DAG')!
host: p.get_default('host', 'localhost')!
port: p.get_int_default('port', 8888)!
}
if mycfg.password == '' && mycfg.secret == '' {
return error('password or secret needs to be filled in for ${args.name}')
}
return mycfg
}
@end
@else
@[heap]
pub struct ${args.classname} {
pub mut:
name string = 'default'
mail_from string
mail_password string @@[secret]
mail_port int
mail_server string
mail_username string
}
@if args.hasconfig
fn cfg_play(p paramsparser.Params) ! {
//THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
mut mycfg := ${args.classname}{
name: p.get_default('name', 'default')!
mail_from: p.get('mail_from')!
mail_password: p.get('mail_password')!
mail_port: p.get_int_default('mail_port', 8888)!
mail_server: p.get('mail_server')!
mail_username: p.get('mail_username')!
}
set(mycfg)!
}
@end
@end
fn obj_init(obj_ ${args.classname})!${args.classname}{
//never call get here, only thing we can do here is work on object itself
mut obj:=obj_
return obj
}
@if args.cat == .installer
//called before start if done
fn configure() ! {
@if args.cat == .installer
//mut installer := get()!
@else
//mut client := get()!
@end
@if args.templates
// mut mycode := ??tmpl('templates/atemplate.yaml')
// mut path := pathlib.get_file(path: cfg.configpath, create: true)!
// path.write(mycode)!
// console.print_debug(mycode)
@end
}
@end

View File

@@ -0,0 +1,63 @@
# ${args.name}
${args.title}
To get started
```vlang
@if args.cat == .installer
import freeflowuniverse.herolib.installers.something.${args.name} as ${args.name}_installer
heroscript:="
!!${args.name}.configure name:'test'
password: '1234'
port: 7701
!!${args.name}.start name:'test' reset:1
"
${args.name}_installer.play(heroscript=heroscript)!
//or we can call the default and do a start with reset
//mut installer:= ${args.name}_installer.get()!
//installer.start(reset:true)!
@else
import freeflowuniverse.herolib.clients. ${args.name}
mut client:= ${args.name}.get()!
client...
@end
```
## example heroscript
@if args.cat == .installer
```hero
!!${args.name}.configure
homedir: '/home/user/${args.name}'
username: 'admin'
password: 'secretpassword'
title: 'Some Title'
host: 'localhost'
port: 8888
```
@else
```hero
!!${args.name}.configure
secret: '...'
host: 'localhost'
port: 8888
```
@end