WIP: Building hero
- The work is still in progress Co-authored-by: supermario <mariobassem12@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import freeflowuniverse.herolib.installers.base
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.ui
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
|
||||
@@ -48,7 +49,7 @@ fn do() ! {
|
||||
toinstall = true
|
||||
}
|
||||
|
||||
if osal.is_osx() {
|
||||
if core.is_osx()! {
|
||||
if !osal.cmd_exists('brew') {
|
||||
console.clear()
|
||||
mut myui := ui.new()!
|
||||
|
||||
210
lib/core/generator/generic/factory.v
Normal file
210
lib/core/generator/generic/factory.v
Normal 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)!
|
||||
}
|
||||
78
lib/core/generator/generic/generator.v
Normal file
78
lib/core/generator/generic/generator.v
Normal 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
|
||||
}
|
||||
84
lib/core/generator/generic/model.v
Normal file
84
lib/core/generator/generic/model.v
Normal 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{}
|
||||
}
|
||||
86
lib/core/generator/generic/readme.md
Normal file
86
lib/core/generator/generic/readme.md
Normal 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
|
||||
```
|
||||
|
||||
30
lib/core/generator/generic/scanner.v
Normal file
30
lib/core/generator/generic/scanner.v
Normal 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)!
|
||||
}
|
||||
}
|
||||
5
lib/core/generator/generic/templates/atemplate.yaml
Normal file
5
lib/core/generator/generic/templates/atemplate.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
name: ??{cfg.configpath}
|
||||
|
||||
|
||||
13
lib/core/generator/generic/templates/heroscript_example
Normal file
13
lib/core/generator/generic/templates/heroscript_example
Normal 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
|
||||
212
lib/core/generator/generic/templates/objname_actions.vtemplate
Normal file
212
lib/core/generator/generic/templates/objname_actions.vtemplate
Normal 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
|
||||
313
lib/core/generator/generic/templates/objname_factory_.vtemplate
Normal file
313
lib/core/generator/generic/templates/objname_factory_.vtemplate
Normal 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
|
||||
}
|
||||
137
lib/core/generator/generic/templates/objname_model.vtemplate
Normal file
137
lib/core/generator/generic/templates/objname_model.vtemplate
Normal 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
|
||||
|
||||
|
||||
63
lib/core/generator/generic/templates/readme.md
Normal file
63
lib/core/generator/generic/templates/readme.md
Normal 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
|
||||
|
||||
|
||||
119
lib/core/herocmds/bootstrap.v
Normal file
119
lib/core/herocmds/bootstrap.v
Normal file
@@ -0,0 +1,119 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.installers.base
|
||||
import freeflowuniverse.herolib.installers.lang.herolib
|
||||
import freeflowuniverse.herolib.builder
|
||||
import cli { Command, Flag }
|
||||
|
||||
pub fn cmd_bootstrap(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'bootstrap'
|
||||
description: 'bootstrap hero'
|
||||
required_args: 0
|
||||
execute: cmd_bootstrap_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'will reset.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'develop'
|
||||
abbrev: 'd'
|
||||
description: 'will put system in development mode.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'compileupload'
|
||||
abbrev: 'c'
|
||||
description: 'Compile and upload hero.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'update'
|
||||
abbrev: 'u'
|
||||
description: 'Update/install hero.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'hero'
|
||||
abbrev: 'u'
|
||||
description: 'Update hero.'
|
||||
})
|
||||
|
||||
// cmd_run.add_flag(Flag{
|
||||
// flag: .bool
|
||||
// required: false
|
||||
// name: 'crystal'
|
||||
// abbrev: 'cr'
|
||||
// description: 'install crystal lib + vlang.'
|
||||
// })
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
name: 'address'
|
||||
abbrev: 'a'
|
||||
description: 'address in form root@212.3.4.5:2222 or root@212.3.4.5 or root@info.three.com'
|
||||
})
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_bootstrap_execute(cmd Command) ! {
|
||||
mut develop := cmd.flags.get_bool('develop') or { false }
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
|
||||
mut compileupload := cmd.flags.get_bool('compileupload') or { false }
|
||||
mut update := cmd.flags.get_bool('update') or { false }
|
||||
|
||||
// mut hero := cmd.flags.get_bool('hero') or { false }
|
||||
mut address := cmd.flags.get_string('address') or { '' }
|
||||
if address == '' {
|
||||
osal.profile_path_add_hero()!
|
||||
if develop {
|
||||
herolib.install(reset: reset)!
|
||||
} else {
|
||||
base.install(reset: reset)!
|
||||
}
|
||||
base.bash_installers_package()!
|
||||
} else {
|
||||
mut b := builder.new()!
|
||||
mut n := b.node_new(ipaddr: address)!
|
||||
if develop {
|
||||
n.crystal_install(reset: reset)!
|
||||
n.hero_install()!
|
||||
n.dagu_install()!
|
||||
} else {
|
||||
panic('implement, need to download here and install')
|
||||
}
|
||||
// return error(cmd.help_message())
|
||||
}
|
||||
if compileupload {
|
||||
// mycmd:='
|
||||
// \${HOME}/code/github/freeflowuniverse/crystallib/scripts/package.vsh
|
||||
// '
|
||||
// osal.exec(cmd: mycmd)!
|
||||
println('please execute:\n~/code/github/freeflowuniverse/crystallib/scripts/githubactions.sh')
|
||||
}
|
||||
|
||||
if update {
|
||||
// mycmd:='
|
||||
// \${HOME}/code/github/freeflowuniverse/crystallib/scripts/package.vsh
|
||||
// '
|
||||
// osal.exec(cmd: mycmd)!
|
||||
println('please execute:\n~/code/github/freeflowuniverse/crystallib/scripts/install_hero.sh')
|
||||
}
|
||||
}
|
||||
83
lib/core/herocmds/docsorter.v
Normal file
83
lib/core/herocmds/docsorter.v
Normal file
@@ -0,0 +1,83 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.conversiontools.docsorter
|
||||
import cli { Command, Flag }
|
||||
import os
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
// const wikipath = os.dir(@FILE) + '/wiki'
|
||||
|
||||
pub fn cmd_docsorter(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'docsorter'
|
||||
description: 'can sort, export, ... pdfs and other docs.'
|
||||
required_args: 0
|
||||
execute: cmd_docsorter_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'path'
|
||||
abbrev: 'p'
|
||||
description: 'If not in current directory.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'instructions'
|
||||
abbrev: 'i'
|
||||
description: 'Location to the instructions file, format is text file with per line:\naaa:ourworld:kristof_bio\naab:phoenix:phoenix_digital_nation_litepaper:Litepaper of how a Digital nation can use the Hero Phone'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'dest'
|
||||
abbrev: 'd'
|
||||
description: 'if not given will bet /tmp/export.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'reset the export dir.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'slides'
|
||||
abbrev: 's'
|
||||
description: 'extract slides out of the pdfs.'
|
||||
})
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_docsorter_execute(cmd Command) ! {
|
||||
mut dest := cmd.flags.get_string('dest') or { '' }
|
||||
if dest == '' {
|
||||
dest = '/tmp/export'
|
||||
}
|
||||
mut path := cmd.flags.get_string('path') or { '' }
|
||||
if path == '' {
|
||||
path = os.getwd()
|
||||
}
|
||||
mut instructions := cmd.flags.get_string('instructions') or { '' }
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
mut slides := cmd.flags.get_bool('slides') or { false }
|
||||
|
||||
docsorter.sort(
|
||||
path: path
|
||||
export_path: dest
|
||||
instructions: instructions
|
||||
reset: reset
|
||||
slides: slides
|
||||
) or {
|
||||
print_backtrace()
|
||||
console.print_stderr(err.str())
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
81
lib/core/herocmds/generator.v
Normal file
81
lib/core/herocmds/generator.v
Normal file
@@ -0,0 +1,81 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.core.generator.generic
|
||||
import os
|
||||
import cli { Command, Flag }
|
||||
|
||||
pub fn cmd_generator(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'generate'
|
||||
description: 'generator for vlang code in hero context.'
|
||||
required_args: 0
|
||||
execute: cmd_generator_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'will reset.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'path'
|
||||
abbrev: 'p'
|
||||
description: 'path where to generate the code or scan over multiple directories.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'force'
|
||||
abbrev: 'f'
|
||||
description: 'will work non interactive if possible.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'scan'
|
||||
abbrev: 's'
|
||||
description: 'force scanning operation.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'installer'
|
||||
abbrev: 'i'
|
||||
description: 'Make sure its installer.'
|
||||
})
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_generator_execute(cmd Command) ! {
|
||||
mut force := cmd.flags.get_bool('force') or { false }
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
mut scan := cmd.flags.get_bool('scan') or { false }
|
||||
mut installer := cmd.flags.get_bool('installer') or { false }
|
||||
mut path := cmd.flags.get_string('path') or { '' }
|
||||
|
||||
if path == '' {
|
||||
path = os.getwd()
|
||||
}
|
||||
|
||||
path = path.replace('~', os.home_dir())
|
||||
|
||||
mut cat := generic.Cat.client
|
||||
if installer {
|
||||
cat = generic.Cat.installer
|
||||
}
|
||||
|
||||
if scan {
|
||||
generic.scan(path: path, reset: reset, force: force, cat: cat)!
|
||||
} else {
|
||||
generic.generate(path: path, reset: reset, force: force, cat: cat)!
|
||||
}
|
||||
}
|
||||
284
lib/core/herocmds/git.v
Normal file
284
lib/core/herocmds/git.v
Normal file
@@ -0,0 +1,284 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import cli { Command, Flag }
|
||||
import os
|
||||
|
||||
pub fn cmd_git(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'git'
|
||||
description: 'Work with your repos, list, commit, pull, reload, ...'
|
||||
// required_args: 1
|
||||
usage: 'sub commands of git are '
|
||||
execute: cmd_git_execute
|
||||
sort_commands: true
|
||||
}
|
||||
|
||||
mut clone_command := Command{
|
||||
sort_flags: true
|
||||
name: 'clone'
|
||||
execute: cmd_git_execute
|
||||
description: 'will clone the repo based on a given url, e.g. https://github.com/freeflowuniverse/webcomponents/tree/main'
|
||||
}
|
||||
|
||||
mut pull_command := Command{
|
||||
sort_flags: true
|
||||
name: 'pull'
|
||||
execute: cmd_git_execute
|
||||
description: 'will pull the content, if it exists for each found repo.'
|
||||
}
|
||||
|
||||
mut push_command := Command{
|
||||
sort_flags: true
|
||||
name: 'push'
|
||||
execute: cmd_git_execute
|
||||
description: 'will push the content, if it exists for each found repo.'
|
||||
}
|
||||
|
||||
mut commit_command := Command{
|
||||
sort_flags: true
|
||||
name: 'commit'
|
||||
execute: cmd_git_execute
|
||||
description: 'will commit newly found content, specify the message.'
|
||||
}
|
||||
|
||||
mut reload_command := Command{
|
||||
sort_flags: true
|
||||
name: 'reload'
|
||||
execute: cmd_git_execute
|
||||
description: 'reset the cache of the repos, they are kept for 24h in local redis, this will reload all info.'
|
||||
}
|
||||
|
||||
mut delete_command := Command{
|
||||
sort_flags: true
|
||||
name: 'delete'
|
||||
execute: cmd_git_execute
|
||||
description: 'delete the repo.'
|
||||
}
|
||||
|
||||
mut list_command := Command{
|
||||
sort_flags: true
|
||||
name: 'list'
|
||||
execute: cmd_git_execute
|
||||
description: 'list all repos.'
|
||||
}
|
||||
|
||||
mut sourcetree_command := Command{
|
||||
sort_flags: true
|
||||
name: 'sourcetree'
|
||||
execute: cmd_git_execute
|
||||
description: 'Open sourcetree on found repos, will do for max 5.'
|
||||
}
|
||||
|
||||
mut editor_command := Command{
|
||||
sort_flags: true
|
||||
name: 'edit'
|
||||
execute: cmd_git_execute
|
||||
description: 'Open visual studio code on found repos, will do for max 5.'
|
||||
}
|
||||
|
||||
mut cmd_cd := Command{
|
||||
sort_flags: true
|
||||
name: 'cd'
|
||||
execute: cmd_git_execute
|
||||
description: 'cd to a git repo, use e.g. eval $(git cd -u https://github.com/threefoldfoundation/www_threefold_io)'
|
||||
}
|
||||
|
||||
cmd_cd.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'url'
|
||||
abbrev: 'u'
|
||||
description: 'url for git cd operation, so we know where to cd to'
|
||||
})
|
||||
|
||||
mut allcmdsref := [&list_command, &clone_command, &push_command, &pull_command, &commit_command,
|
||||
&reload_command, &delete_command, &sourcetree_command, &editor_command]
|
||||
|
||||
for mut c in allcmdsref {
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'silent'
|
||||
abbrev: 's'
|
||||
description: 'be silent.'
|
||||
})
|
||||
}
|
||||
|
||||
mut allcmdscommit := [&push_command, &pull_command, &commit_command]
|
||||
|
||||
for mut c in allcmdscommit {
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'message'
|
||||
abbrev: 'm'
|
||||
description: 'which message to use for commit.'
|
||||
})
|
||||
}
|
||||
|
||||
mut urlcmds := [&clone_command, &pull_command, &push_command, &editor_command, &sourcetree_command]
|
||||
for mut c in urlcmds {
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'url'
|
||||
abbrev: 'u'
|
||||
description: 'url for clone operation.'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'reset'
|
||||
description: 'force a pull and reset changes.'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'pull'
|
||||
description: 'force a pull.'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'pullreset'
|
||||
abbrev: 'pr'
|
||||
description: 'force a pull and do a reset.'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'recursive'
|
||||
description: 'if we do a clone or a pull we also get the git submodules.'
|
||||
})
|
||||
}
|
||||
|
||||
for mut c in allcmdsref {
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'filter'
|
||||
abbrev: 'f'
|
||||
description: 'Filter is part of path of repo e.g. threefoldtech/info_'
|
||||
})
|
||||
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'repo'
|
||||
abbrev: 'r'
|
||||
description: 'name of repo'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'branch'
|
||||
abbrev: 'b'
|
||||
description: 'branch of repo (optional)'
|
||||
})
|
||||
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'account'
|
||||
abbrev: 'a'
|
||||
description: 'name of account e.g. threefoldtech'
|
||||
})
|
||||
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'provider'
|
||||
abbrev: 'p'
|
||||
description: 'name of provider e.g. github'
|
||||
})
|
||||
}
|
||||
for mut c_ in allcmdsref {
|
||||
mut c := *c_
|
||||
c.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'coderoot'
|
||||
abbrev: 'cr'
|
||||
description: 'If you want to use another directory for your code root.'
|
||||
})
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'script'
|
||||
abbrev: 'z'
|
||||
description: 'to use in scripts, will not run interative and ask questions.'
|
||||
})
|
||||
cmd_run.add_command(c)
|
||||
}
|
||||
cmd_run.add_command(cmd_cd)
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_git_execute(cmd Command) ! {
|
||||
mut silent := cmd.flags.get_bool('silent') or { false }
|
||||
if silent || cmd.name == 'cd' {
|
||||
console.silent_set()
|
||||
}
|
||||
mut coderoot := cmd.flags.get_string('coderoot') or { '' }
|
||||
|
||||
if 'CODEROOT' in os.environ() && coderoot == '' {
|
||||
coderoot = os.environ()['CODEROOT']
|
||||
}
|
||||
|
||||
mut gs := gittools.get()!
|
||||
if coderoot.len > 0 {
|
||||
// is a hack for now
|
||||
gs = gittools.new(coderoot: coderoot)!
|
||||
}
|
||||
|
||||
// create the filter for doing group actions, or action on 1 repo
|
||||
mut filter := cmd.flags.get_string('filter') or { '' }
|
||||
mut branch := cmd.flags.get_string('branch') or { '' }
|
||||
mut repo := cmd.flags.get_string('repo') or { '' }
|
||||
mut account := cmd.flags.get_string('account') or { '' }
|
||||
mut provider := cmd.flags.get_string('provider') or { '' }
|
||||
|
||||
if cmd.name != 'cd' {
|
||||
// check if we are in a git repo
|
||||
if repo == '' && account == '' && provider == '' && filter == '' {
|
||||
if r0 := gs.get_working_repo() {
|
||||
repo = r0.name
|
||||
account = r0.account
|
||||
provider = r0.provider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.name in gittools.gitcmds.split(',') {
|
||||
mut pull := cmd.flags.get_bool('pull') or { false }
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
mut recursive := cmd.flags.get_bool('recursive') or { false }
|
||||
if cmd.flags.get_bool('pullreset') or { false } {
|
||||
pull = true
|
||||
reset = true
|
||||
}
|
||||
mypath := gs.do(
|
||||
filter: filter
|
||||
repo: repo
|
||||
account: account
|
||||
provider: provider
|
||||
branch: branch
|
||||
recursive: recursive
|
||||
cmd: cmd.name
|
||||
script: cmd.flags.get_bool('script') or { false }
|
||||
pull: pull
|
||||
reset: reset
|
||||
msg: cmd.flags.get_string('message') or { '' }
|
||||
url: cmd.flags.get_string('url') or { '' }
|
||||
)!
|
||||
if cmd.name == 'cd' {
|
||||
print('cd ${mypath}\n')
|
||||
}
|
||||
return
|
||||
} else {
|
||||
// console.print_debug(" Supported commands are: ${gittools.gitcmds}")
|
||||
return error(cmd.help_message())
|
||||
}
|
||||
}
|
||||
68
lib/core/herocmds/imagedownsize.v
Normal file
68
lib/core/herocmds/imagedownsize.v
Normal file
@@ -0,0 +1,68 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.conversiontools.imagemagick
|
||||
import cli { Command, Flag }
|
||||
import os
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
// const wikipath = os.dir(@FILE) + '/wiki'
|
||||
|
||||
pub fn cmd_imagedownsize(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'image_downsize'
|
||||
description: 'walk over current director or specified one and downsize all images'
|
||||
required_args: 0
|
||||
execute: cmd_imagedownsize_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'path'
|
||||
abbrev: 'p'
|
||||
description: 'If not in current directory.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'backupdir'
|
||||
abbrev: 'b'
|
||||
description: 'What is the backup dir if any.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'convertpng'
|
||||
description: 'will convert png to jpg.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'redo'
|
||||
abbrev: 'r'
|
||||
description: 'will do the checks again.'
|
||||
})
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_imagedownsize_execute(cmd Command) ! {
|
||||
mut backupdir := cmd.flags.get_string('backupdir') or { '' }
|
||||
mut path := cmd.flags.get_string('path') or { '' }
|
||||
if path == '' {
|
||||
path = os.getwd()
|
||||
}
|
||||
imagemagick.downsize(
|
||||
path: path
|
||||
backupdir: backupdir
|
||||
redo: cmd.flags.get_bool('redo') or { false }
|
||||
convertpng: cmd.flags.get_bool('convertpng') or { false }
|
||||
) or {
|
||||
print_backtrace()
|
||||
console.print_stderr(err.str())
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
103
lib/core/herocmds/init.v
Normal file
103
lib/core/herocmds/init.v
Normal file
@@ -0,0 +1,103 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.installers.base
|
||||
import freeflowuniverse.herolib.installers.lang.herolib
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import cli { Command, Flag }
|
||||
|
||||
pub fn cmd_init(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'init'
|
||||
usage: '
|
||||
Initialization Helpers for Hero
|
||||
|
||||
-r will reset everything e.g. done states (when installing something)
|
||||
-d will put the platform in development mode, get V, crystallib, hero...
|
||||
-c will compile hero on local platform (requires local crystallib)
|
||||
|
||||
'
|
||||
description: 'initialize hero environment (reset, development mode, )'
|
||||
required_args: 0
|
||||
execute: cmd_init_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'will reset.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'develop'
|
||||
abbrev: 'd'
|
||||
description: 'will put system in development mode.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'compile'
|
||||
abbrev: 'c'
|
||||
description: 'will compile hero.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'redis'
|
||||
description: 'will make sure redis is in system and is running.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitpull'
|
||||
abbrev: 'gp'
|
||||
description: 'will try to pull git repos for crystallib.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitreset'
|
||||
abbrev: 'gr'
|
||||
description: 'will reset the git repo if there are changes inside, will also pull, CAREFUL.'
|
||||
})
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_init_execute(cmd Command) ! {
|
||||
mut develop := cmd.flags.get_bool('develop') or { false }
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
mut hero := cmd.flags.get_bool('compile') or { false }
|
||||
mut redis := cmd.flags.get_bool('redis') or { false }
|
||||
mut git_reset := cmd.flags.get_bool('gitreset') or { false }
|
||||
mut git_pull := cmd.flags.get_bool('gitpull') or { false }
|
||||
|
||||
if redis {
|
||||
base.redis_install(reset: true)!
|
||||
}
|
||||
|
||||
if develop {
|
||||
console.print_header('init in development mode: reset:${reset}')
|
||||
base.install(reset: reset, develop: true)!
|
||||
return
|
||||
}
|
||||
if hero {
|
||||
base.install(reset: reset, develop: true)!
|
||||
herolib.install(reset: reset, git_pull: git_pull, git_reset: git_reset)!
|
||||
base.redis_install()!
|
||||
herolib.hero_compile(reset: reset)!
|
||||
r := osal.profile_path_add_hero()!
|
||||
console.print_header(' add path ${r} to profile.')
|
||||
return
|
||||
}
|
||||
|
||||
return error(cmd.help_message())
|
||||
}
|
||||
83
lib/core/herocmds/installers.v
Normal file
83
lib/core/herocmds/installers.v
Normal file
@@ -0,0 +1,83 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.installers
|
||||
import cli { Command, Flag }
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
pub fn cmd_installers(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'installers'
|
||||
description: 'a set of installers'
|
||||
required_args: 0
|
||||
execute: cmd_installers_execute
|
||||
}
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'names'
|
||||
abbrev: 'n'
|
||||
description: 'Comma separated list of installers to call.'
|
||||
})
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'will reset.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'uninstall'
|
||||
abbrev: 'u'
|
||||
description: 'will uninstall in stead of install.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitpull'
|
||||
abbrev: 'gp'
|
||||
description: 'e.g. in crystallib or other git repo pull changes.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitreset'
|
||||
abbrev: 'gr'
|
||||
description: 'e.g. in crystallib or other git repo pull & reset changes.'
|
||||
})
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_installers_execute(cmd Command) ! {
|
||||
mut reset := cmd.flags.get_bool('reset') or { false }
|
||||
mut uninstall := cmd.flags.get_bool('uninstall') or { false }
|
||||
mut gitpull := cmd.flags.get_bool('gitpull') or { false }
|
||||
mut gitreset := cmd.flags.get_bool('gitreset') or { false }
|
||||
mut names := cmd.flags.get_string('names') or { '' }
|
||||
|
||||
if names == '' {
|
||||
console.clear()
|
||||
console.print_header('the following installers are known:')
|
||||
console.print_lf(2)
|
||||
for x in installers.names() {
|
||||
console.print_item(x)
|
||||
}
|
||||
console.print_lf(1)
|
||||
console.print_stdout(cmd.help_message())
|
||||
console.print_lf(5)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
installers.install_multi(
|
||||
reset: reset
|
||||
names: names
|
||||
uninstall: uninstall
|
||||
gitpull: gitpull
|
||||
gitreset: gitreset
|
||||
)!
|
||||
}
|
||||
92
lib/core/herocmds/luadns.v
Normal file
92
lib/core/herocmds/luadns.v
Normal file
@@ -0,0 +1,92 @@
|
||||
module herocmds
|
||||
|
||||
import cli { Command, Flag }
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.develop.luadns
|
||||
|
||||
// Main function to set up CLI commands
|
||||
pub fn cmd_luadns(mut cmdroot Command) {
|
||||
mut cmd_luadns := Command{
|
||||
name: 'luadns'
|
||||
usage: '
|
||||
## Manage your LuaDNS
|
||||
|
||||
example:
|
||||
|
||||
hero luadns load -u https://github.com/example/dns-repo
|
||||
hero luadns set-domain -d example.com -i 51.129.54.234
|
||||
|
||||
'
|
||||
description: 'Manage LuaDNS configurations'
|
||||
required_args: 0
|
||||
execute: cmd_luadns_execute
|
||||
}
|
||||
|
||||
cmd_luadns.add_command(cmd_luadns_set_domain())
|
||||
cmdroot.add_command(cmd_luadns)
|
||||
}
|
||||
|
||||
fn cmd_luadns_set_domain() Command {
|
||||
mut cmd := Command{
|
||||
name: 'set-domain'
|
||||
usage: 'Set a domain in the DNS configurations'
|
||||
required_args: 0
|
||||
execute: cmd_luadns_set_domain_execute
|
||||
}
|
||||
|
||||
cmd.add_flag(Flag{
|
||||
flag: .string
|
||||
required: true
|
||||
name: 'domain'
|
||||
abbrev: 'd'
|
||||
description: 'Domain to set in the DNS configurations'
|
||||
})
|
||||
|
||||
cmd.add_flag(Flag{
|
||||
flag: .string
|
||||
required: true
|
||||
name: 'ip'
|
||||
abbrev: 'i'
|
||||
description: 'IP address for the domain'
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
fn cmd_luadns_execute(cmd Command) ! {
|
||||
console.print_stdout(cmd.help_message())
|
||||
}
|
||||
|
||||
fn cmd_luadns_set_domain_execute(cmd Command) ! {
|
||||
url := cmd.flags.get_string('url') or {
|
||||
console.print_debug('URL flag is required')
|
||||
cmd_luadns_help(cmd)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
domain := cmd.flags.get_string('domain') or {
|
||||
console.print_debug('Domain flag is required')
|
||||
cmd_luadns_help(cmd)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
ip := cmd.flags.get_string('ip') or {
|
||||
console.print_debug('IP flag is required')
|
||||
cmd_luadns_help(cmd)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
mut lua_dns := luadns.load(url)!
|
||||
lua_dns.set_domain(domain, ip) or {
|
||||
eprintln('Failed to set domain: ${err}')
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fn cmd_luadns_help(cmd Command) {
|
||||
console.clear()
|
||||
console.print_header('Instructions for LuaDNS:')
|
||||
console.print_lf(1)
|
||||
console.print_stdout(cmd.help_message())
|
||||
console.print_lf(5)
|
||||
}
|
||||
121
lib/core/herocmds/mdbook.v
Normal file
121
lib/core/herocmds/mdbook.v
Normal file
@@ -0,0 +1,121 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.web.mdbook
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import cli { Command, Flag }
|
||||
import os
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
// path string //if location on filessytem, if exists, this has prio on git_url
|
||||
// git_url string // location of where the hero scripts are
|
||||
// git_pull bool // means when getting new repo will pull even when repo is already there
|
||||
// git_pullreset bool // means we will force a pull and reset old content
|
||||
// coderoot string //the location of coderoot if its another one
|
||||
pub fn cmd_mdbook(mut cmdroot Command) {
|
||||
mut cmd_mdbook := Command{
|
||||
name: 'mdbook'
|
||||
usage: '
|
||||
## Manage your MDBooks
|
||||
|
||||
example:
|
||||
|
||||
hero mdbook -u https://git.ourworld.tf/tfgrid/info_tfgrid/src/branch/main/heroscript
|
||||
|
||||
If you do -gp it will pull newest book content from git and give error if there are local changes.
|
||||
If you do -gr it will pull newest book content from git and overwrite local changes (careful).
|
||||
|
||||
'
|
||||
description: 'create, edit, show mdbooks'
|
||||
required_args: 0
|
||||
execute: cmd_mdbook_execute
|
||||
}
|
||||
|
||||
cmd_run_add_flags(mut cmd_mdbook)
|
||||
|
||||
cmd_mdbook.add_flag(Flag{
|
||||
flag: .string
|
||||
name: 'name'
|
||||
abbrev: 'n'
|
||||
description: 'name of the mdbook.'
|
||||
})
|
||||
|
||||
// cmd_mdbook.add_flag(Flag{
|
||||
// flag: .bool
|
||||
// required: false
|
||||
// name: 'edit'
|
||||
// description: 'will open vscode for collections & summary.'
|
||||
// })
|
||||
|
||||
cmd_mdbook.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'open'
|
||||
abbrev: 'o'
|
||||
description: 'will open the generated book.'
|
||||
})
|
||||
|
||||
mut cmd_list := Command{
|
||||
sort_flags: true
|
||||
name: 'list'
|
||||
execute: cmd_mdbook_list
|
||||
description: 'will list existing mdbooks'
|
||||
}
|
||||
|
||||
cmd_mdbook.add_command(cmd_list)
|
||||
cmdroot.add_command(cmd_mdbook)
|
||||
}
|
||||
|
||||
fn cmd_mdbook_list(cmd Command) ! {
|
||||
console.print_header('MDBooks:')
|
||||
build_path := os.join_path(os.home_dir(), 'hero/var/mdbuild')
|
||||
mut build_dir := pathlib.get_dir(path: build_path)!
|
||||
list := build_dir.list(
|
||||
recursive: false
|
||||
dirs_only: true
|
||||
)!
|
||||
for path in list.paths {
|
||||
console.print_stdout(path.name())
|
||||
}
|
||||
}
|
||||
|
||||
fn cmd_mdbook_execute(cmd Command) ! {
|
||||
mut name := cmd.flags.get_string('name') or { '' }
|
||||
|
||||
mut url := cmd.flags.get_string('url') or { '' }
|
||||
mut path := cmd.flags.get_string('path') or { '' }
|
||||
if path.len > 0 || url.len > 0 {
|
||||
// execute the attached playbook
|
||||
mut plbook, _ := plbook_run(cmd)!
|
||||
// get name from the book.generate action
|
||||
if name == '' {
|
||||
mut a := plbook.action_get(actor: 'mdbook', name: 'define')!
|
||||
name = a.params.get('name') or { '' }
|
||||
}
|
||||
} else {
|
||||
mdbook_help(cmd)
|
||||
}
|
||||
|
||||
if name == '' {
|
||||
console.print_debug('did not find name of book to generate, check in heroscript or specify with --name')
|
||||
mdbook_help(cmd)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
edit := cmd.flags.get_bool('edit') or { false }
|
||||
open := cmd.flags.get_bool('open') or { false }
|
||||
if edit || open {
|
||||
mdbook.book_open(name)!
|
||||
}
|
||||
|
||||
if edit {
|
||||
mdbook.book_edit(name)!
|
||||
}
|
||||
}
|
||||
|
||||
fn mdbook_help(cmd Command) {
|
||||
console.clear()
|
||||
console.print_header('Instructions for mdbook:')
|
||||
console.print_lf(1)
|
||||
console.print_stdout(cmd.help_message())
|
||||
console.print_lf(5)
|
||||
}
|
||||
183
lib/core/herocmds/playbook_lib.v
Normal file
183
lib/core/herocmds/playbook_lib.v
Normal file
@@ -0,0 +1,183 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.develop.vscode
|
||||
import freeflowuniverse.herolib.develop.sourcetree
|
||||
import cli { Command, Flag }
|
||||
import os
|
||||
|
||||
pub fn cmd_run_add_flags(mut cmd_run Command) {
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'path'
|
||||
abbrev: 'p'
|
||||
description: 'path where heroscripts can be found.'
|
||||
})
|
||||
|
||||
// cmd_run.add_flag(Flag{
|
||||
// flag: .string
|
||||
// required: false
|
||||
// name: 'sessionname'
|
||||
// abbrev: 'sn'
|
||||
// description: 'name for the session (optional).'
|
||||
// })
|
||||
// cmd_run.add_flag(Flag{
|
||||
// flag: .string
|
||||
// required: false
|
||||
// name: 'contextname'
|
||||
// abbrev: 'cn'
|
||||
// description: 'name for the context (optional).'
|
||||
// })
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'url'
|
||||
abbrev: 'u'
|
||||
description: 'url where heroscript can be found.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitpull'
|
||||
abbrev: 'gp'
|
||||
description: 'will try to pull.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'gitreset'
|
||||
abbrev: 'gr'
|
||||
description: 'will reset the git repo if there are changes inside, will also pull, CAREFUL.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .string
|
||||
required: false
|
||||
name: 'coderoot'
|
||||
abbrev: 'cr'
|
||||
description: 'Set code root for gittools.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'script'
|
||||
abbrev: 's'
|
||||
description: 'runs non interactive!'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'reset'
|
||||
abbrev: 'r'
|
||||
description: 'reset, means lose changes of your repos, BE CAREFUL.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'edit'
|
||||
abbrev: 'e'
|
||||
description: 'Open visual studio code for where we found the content.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'sourcetree'
|
||||
abbrev: 'st'
|
||||
description: 'Open sourcetree (git mgmt) for the repo where we found the content.'
|
||||
})
|
||||
|
||||
cmd_run.add_flag(Flag{
|
||||
flag: .bool
|
||||
required: false
|
||||
name: 'dagu'
|
||||
abbrev: 'da'
|
||||
description: 'Schedule the heroscripts through DAGU.'
|
||||
})
|
||||
}
|
||||
|
||||
// returns the path of the fetched repo url
|
||||
pub fn plbook_code_get(cmd Command) !string {
|
||||
mut path := cmd.flags.get_string('path') or { '' }
|
||||
mut url := cmd.flags.get_string('url') or { '' }
|
||||
|
||||
// mut sessionname := cmd.flags.get_string('sessionname') or { '' }
|
||||
// mut contextname := cmd.flags.get_string('contextname') or { '' }
|
||||
|
||||
mut coderoot := cmd.flags.get_string('coderoot') or { '' }
|
||||
if 'CODEROOT' in os.environ() && coderoot == '' {
|
||||
coderoot = os.environ()['CODEROOT']
|
||||
}
|
||||
|
||||
if coderoot.len > 0 {
|
||||
base.context_new(coderoot: coderoot)!
|
||||
}
|
||||
|
||||
reset := cmd.flags.get_bool('gitreset') or { false }
|
||||
pull := cmd.flags.get_bool('gitpull') or { false }
|
||||
// interactive := !cmd.flags.get_bool('script') or { false }
|
||||
|
||||
mut gs := gittools.get(coderoot: coderoot)!
|
||||
if url.len > 0 {
|
||||
mut repo := gs.get_repo(
|
||||
pull: pull
|
||||
reset: reset
|
||||
url: url
|
||||
// QUESTION: why should reload be default true?
|
||||
// reload: true
|
||||
)!
|
||||
|
||||
path = repo.get_path_of_url(url)!
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// same as session_run_get but will also run the playbook
|
||||
pub fn plbook_run(cmd Command) !(&playbook.PlayBook, string) {
|
||||
path := plbook_code_get(cmd)!
|
||||
if path.len == 0 {
|
||||
return error(cmd.help_message())
|
||||
}
|
||||
|
||||
// add all actions inside to the playbook
|
||||
mut plbook := playbook.new(path: path)!
|
||||
|
||||
dagu := cmd.flags.get_bool('dagu') or { false }
|
||||
|
||||
playcmds.run(mut plbook, dagu)!
|
||||
|
||||
// TODO: below gives Segmentation fault (core dumped)
|
||||
// console.print_stdout(plbook.str())
|
||||
return &plbook, path
|
||||
}
|
||||
|
||||
fn plbook_edit_sourcetree(cmd Command) !(&playbook.PlayBook, string) {
|
||||
edit := cmd.flags.get_bool('edit') or { false }
|
||||
treedo := cmd.flags.get_bool('sourcetree') or { false }
|
||||
|
||||
mut plbook, path := plbook_run(cmd)!
|
||||
|
||||
if path.len == 0 {
|
||||
return error('path or url needs to be specified')
|
||||
}
|
||||
|
||||
if treedo {
|
||||
// mut repo := gittools.git_repo_get(coderoot: coderoot, path: path)!
|
||||
// repo.sourcetree()!
|
||||
sourcetree.open(path: path)!
|
||||
} else if edit {
|
||||
mut vscode_ := vscode.new(path)
|
||||
vscode_.open()!
|
||||
}
|
||||
|
||||
return plbook, path
|
||||
}
|
||||
40
lib/core/herocmds/run.v
Normal file
40
lib/core/herocmds/run.v
Normal file
@@ -0,0 +1,40 @@
|
||||
module herocmds
|
||||
|
||||
import cli { Command }
|
||||
|
||||
// path string //if location on filessytem, if exists, this has prio on git_url
|
||||
// git_url string // location of where the hero scripts are
|
||||
// git_pull bool // means when getting new repo will pull even when repo is already there
|
||||
// git_pullreset bool // means we will force a pull and reset old content
|
||||
// coderoot string //the location of coderoot if its another one
|
||||
pub fn cmd_run(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'run'
|
||||
usage: '
|
||||
## Powerfull command to run heroscript
|
||||
|
||||
heroscript has numerous ways to execute actions using your hero tool.
|
||||
|
||||
example:
|
||||
|
||||
hero run -u https://git.ourworld.tf/threefold_coop/info_asimov/src/branch/main/heroscript
|
||||
|
||||
Can also do -e or -st to see sourcetree
|
||||
|
||||
If you do -gp it will pull newest heroscripts from git and give error if there are local changes.
|
||||
If you do -gr it will pull newest heroscripts from git and overwrite local changes (careful).
|
||||
|
||||
|
||||
'
|
||||
required_args: 0
|
||||
description: 'run heroscript commands'
|
||||
execute: cmd_heroscript_execute
|
||||
}
|
||||
cmd_run_add_flags(mut cmd_run)
|
||||
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_heroscript_execute(cmd Command) ! {
|
||||
plbook_edit_sourcetree(cmd)!
|
||||
}
|
||||
138
lib/core/herocmds/sshagent.v
Normal file
138
lib/core/herocmds/sshagent.v
Normal file
@@ -0,0 +1,138 @@
|
||||
module herocmds
|
||||
|
||||
import freeflowuniverse.herolib.osal.sshagent
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.ui
|
||||
import cli { Command, Flag }
|
||||
|
||||
pub fn cmd_sshagent(mut cmdroot Command) {
|
||||
mut cmd_run := Command{
|
||||
name: 'sshagent'
|
||||
description: 'Work with SSHAgent'
|
||||
// required_args: 1
|
||||
usage: 'sub commands of generate are list, generate, unload, load'
|
||||
execute: cmd_sshagent_execute
|
||||
sort_commands: true
|
||||
}
|
||||
|
||||
mut sshagent_command_list := Command{
|
||||
sort_flags: true
|
||||
name: 'list'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'list ssh-keys.'
|
||||
}
|
||||
|
||||
mut sshagent_command_generate := Command{
|
||||
sort_flags: true
|
||||
name: 'generate'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'generate ssh-key.'
|
||||
}
|
||||
|
||||
mut sshagent_command_add := Command{
|
||||
sort_flags: true
|
||||
name: 'add'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'add a key starting from private key, only works interactive for nows.'
|
||||
}
|
||||
|
||||
sshagent_command_generate.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'load'
|
||||
abbrev: 'l'
|
||||
description: 'should key be loaded'
|
||||
})
|
||||
|
||||
mut sshagent_command_load := Command{
|
||||
sort_flags: true
|
||||
name: 'load'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'load ssh-key in agent.'
|
||||
}
|
||||
|
||||
mut sshagent_command_unload := Command{
|
||||
sort_flags: true
|
||||
name: 'forget'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'Unload ssh-key from agent.'
|
||||
}
|
||||
|
||||
mut sshagent_command_reset := Command{
|
||||
sort_flags: true
|
||||
name: 'reset'
|
||||
execute: cmd_sshagent_execute
|
||||
description: 'Reset all keys, means unload them all.'
|
||||
}
|
||||
|
||||
mut allcmdsref_gen0 := [&sshagent_command_generate, &sshagent_command_load, &sshagent_command_unload,
|
||||
&sshagent_command_reset, &sshagent_command_add]
|
||||
for mut d in allcmdsref_gen0 {
|
||||
d.add_flag(Flag{
|
||||
flag: .string
|
||||
name: 'name'
|
||||
abbrev: 'n'
|
||||
required: true
|
||||
description: 'name of the key'
|
||||
})
|
||||
}
|
||||
|
||||
mut allcmdsref_gen := [&sshagent_command_list, &sshagent_command_generate, &sshagent_command_load,
|
||||
&sshagent_command_unload, &sshagent_command_reset]
|
||||
|
||||
for mut c in allcmdsref_gen {
|
||||
// c.add_flag(Flag{
|
||||
// flag: .bool
|
||||
// name: 'reset'
|
||||
// abbrev: 'r'
|
||||
// description: 'do you want to reset all? Dangerous!'
|
||||
// })
|
||||
c.add_flag(Flag{
|
||||
flag: .bool
|
||||
name: 'script'
|
||||
abbrev: 's'
|
||||
description: 'runs non interactive!'
|
||||
})
|
||||
|
||||
cmd_run.add_command(*c)
|
||||
}
|
||||
cmdroot.add_command(cmd_run)
|
||||
}
|
||||
|
||||
fn cmd_sshagent_execute(cmd Command) ! {
|
||||
// mut reset := cmd.flags.get_bool('reset') or {false }
|
||||
mut isscript := cmd.flags.get_bool('script') or { false }
|
||||
mut load := cmd.flags.get_bool('load') or { false }
|
||||
mut name := cmd.flags.get_string('name') or { '' }
|
||||
|
||||
mut agent := sshagent.new()!
|
||||
|
||||
if cmd.name == 'list' {
|
||||
if !isscript {
|
||||
console.clear()
|
||||
}
|
||||
console.print_debug(agent.str())
|
||||
} else if cmd.name == 'generate' {
|
||||
agent.generate(name, '')!
|
||||
if load {
|
||||
agent.load(name)!
|
||||
}
|
||||
} else if cmd.name == 'load' {
|
||||
agent.load(name)!
|
||||
} else if cmd.name == 'forget' {
|
||||
agent.forget(name)!
|
||||
} else if cmd.name == 'reset' {
|
||||
agent.reset()!
|
||||
} else if cmd.name == 'add' {
|
||||
panic("can't work, no support for multiline yet")
|
||||
mut myui := ui.new()!
|
||||
privkey := myui.ask_question(
|
||||
question: 'private key of your ssh key'
|
||||
)!
|
||||
agent.add(name, privkey)!
|
||||
} else {
|
||||
// console.print_debug(1)
|
||||
return error(cmd.help_message())
|
||||
// console.print_debug(" Supported commands are: ${gentools.gencmds}")
|
||||
// return error('unknown subcmd')
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ module playcmds
|
||||
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.virt.hetzner
|
||||
// import freeflowuniverse.herolib.virt.hetzner
|
||||
// import freeflowuniverse.herolib.clients.b2
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.hero.publishing
|
||||
// import freeflowuniverse.herolib.hero.publishing
|
||||
import freeflowuniverse.herolib.threefold.grid4.gridsimulator
|
||||
// import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
import freeflowuniverse.herolib.threefold.grid4.farmingsimulator
|
||||
@@ -26,7 +26,7 @@ pub fn run(mut plbook playbook.PlayBook, dagu bool) ! {
|
||||
// play_caddy(mut plbook)!
|
||||
// play_juggler(mut plbook)!
|
||||
// play_luadns(mut plbook)!
|
||||
hetzner.heroplay(mut plbook)!
|
||||
// hetzner.heroplay(mut plbook)!
|
||||
// b2.heroplay(mut plbook)!
|
||||
|
||||
farmingsimulator.play(mut plbook)!
|
||||
@@ -36,7 +36,7 @@ pub fn run(mut plbook playbook.PlayBook, dagu bool) ! {
|
||||
// base_install(play(mut plbook)!
|
||||
// coredns.play(mut plbook)!
|
||||
|
||||
publishing.play(mut plbook)!
|
||||
// publishing.play(mut plbook)!
|
||||
|
||||
// plbook.empty_check()!
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module playcmds
|
||||
|
||||
// import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
|
||||
// pub fn scheduler(heroscript string) ! {
|
||||
// daguserver.play(
|
||||
// heroscript: heroscript
|
||||
// )!
|
||||
// }
|
||||
pub fn scheduler(heroscript string) ! {
|
||||
daguserver.play(
|
||||
heroscript: heroscript
|
||||
)!
|
||||
}
|
||||
|
||||
31
lib/develop/luadns/README.md
Normal file
31
lib/develop/luadns/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# LuaDNS Vlang Module
|
||||
|
||||
## Overview
|
||||
This module provides functionality to parse and manage DNS configurations from Lua scripts. It supports creating, updating, and validating DNS records for multiple domains.
|
||||
|
||||
## Features
|
||||
- Parse Lua DNS configuration files.
|
||||
- Manage DNS records for multiple domains.
|
||||
- Validate IP addresses and domain names.
|
||||
- Automatically add default CNAME and CAA records.
|
||||
|
||||
## Usage
|
||||
|
||||
### Load DNS Configurations
|
||||
Load DNS configurations from a git repository.
|
||||
```v
|
||||
import luadns
|
||||
|
||||
// Load configurations from a git URL
|
||||
dns := luadns.load('https://git.example.com/repo.git')!
|
||||
```
|
||||
|
||||
### Set Domain
|
||||
Add or update an A record for a domain or subdomain.
|
||||
```v
|
||||
dns.set_domain('example.com', '51.129.54.234')!
|
||||
dns.set_domain('auth.example.com', '231.29.54.234')!
|
||||
```
|
||||
|
||||
### Validate Inputs
|
||||
The module ensures that only valid IP addresses and domain names are accepted.
|
||||
25
lib/develop/luadns/factory.v
Normal file
25
lib/develop/luadns/factory.v
Normal file
@@ -0,0 +1,25 @@
|
||||
module luadns
|
||||
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
|
||||
struct LuaDNS {
|
||||
pub mut:
|
||||
url string
|
||||
configs []DNSConfig
|
||||
}
|
||||
|
||||
// returns the path of the fetched repo
|
||||
pub fn load(url string) !LuaDNS {
|
||||
mut gs := gittools.new()!
|
||||
mut repo := gs.get_repo(
|
||||
url: url
|
||||
pull: true
|
||||
)!
|
||||
|
||||
repo_path := repo.get_path()!
|
||||
|
||||
return LuaDNS{
|
||||
url: url
|
||||
configs: parse_dns_configs(repo_path)!
|
||||
}
|
||||
}
|
||||
114
lib/develop/luadns/luadns.v
Normal file
114
lib/develop/luadns/luadns.v
Normal file
@@ -0,0 +1,114 @@
|
||||
module luadns
|
||||
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
|
||||
// returns the directory of the git repository for the dns
|
||||
pub fn (dns LuaDNS) directory() !pathlib.Path {
|
||||
mut gs := gittools.new()!
|
||||
mut repo := gs.get_repo(url: dns.url, pull: true)!
|
||||
repo_path := repo.get_path()!
|
||||
return pathlib.get_dir(path: repo_path)!
|
||||
}
|
||||
|
||||
pub fn (dns LuaDNS) domain_file(domain string) !pathlib.Path {
|
||||
return pathlib.get_file(path: '${dns.directory()!.path}/${domain}.lua')!
|
||||
}
|
||||
|
||||
// returns the git repository for the dns
|
||||
pub fn (dns LuaDNS) repository() !&gittools.GitRepo {
|
||||
mut gs := gittools.new()!
|
||||
repo := gs.get_repo(url: dns.url, pull: true)!
|
||||
return repo
|
||||
}
|
||||
|
||||
pub fn (mut dns LuaDNS) set_domain(domain string, ip string) ! {
|
||||
// Validate the IP address
|
||||
if !is_valid_ip(ip) {
|
||||
return error('Invalid IP address: ${ip}')
|
||||
}
|
||||
|
||||
// Validate the domain
|
||||
if !is_valid_domain(domain) {
|
||||
return error('Invalid domain: ${domain}')
|
||||
}
|
||||
|
||||
subdomain := if domain.contains('.') { domain.all_before('.') } else { domain }
|
||||
root_domain := if domain.contains('.') { domain.all_after('.') } else { domain }
|
||||
|
||||
mut config := dns.find_or_create_config(root_domain)
|
||||
|
||||
mut updated := false
|
||||
for mut record in config.a_records {
|
||||
if record.name == subdomain {
|
||||
record.ip = ip
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !updated {
|
||||
if subdomain == root_domain {
|
||||
config.a_records << ARecord{'', ip}
|
||||
} else {
|
||||
config.a_records << ARecord{subdomain, ip}
|
||||
}
|
||||
}
|
||||
|
||||
// Add default CNAME and CAA records if they do not exist
|
||||
if config.cname_records.len == 0 {
|
||||
config.cname_records << CNAMERecord{'www', '@'}
|
||||
}
|
||||
|
||||
if config.caa_records.len == 0 {
|
||||
config.caa_records << CAARecord{'', 'letsencrypt.org', 'issue'}
|
||||
config.caa_records << CAARecord{'', 'mailto:info@threefold.io', 'iodef'}
|
||||
}
|
||||
|
||||
dns.save_config(config)!
|
||||
}
|
||||
|
||||
fn (mut dns LuaDNS) find_or_create_config(domain string) DNSConfig {
|
||||
for mut config in dns.configs {
|
||||
if config.domain == domain {
|
||||
return config
|
||||
}
|
||||
}
|
||||
dns.configs << DNSConfig{
|
||||
domain: domain
|
||||
}
|
||||
return dns.configs[dns.configs.len - 1]
|
||||
}
|
||||
|
||||
fn (dns LuaDNS) save_config(config DNSConfig) ! {
|
||||
mut repo := dns.repository()!
|
||||
repo.pull()!
|
||||
|
||||
mut file := pathlib.get_file(path: '${dns.directory()!.path}/${config.domain}.lua')!
|
||||
|
||||
mut content := ''
|
||||
|
||||
for record in config.a_records {
|
||||
if record.name == '' || record.name == '_a' {
|
||||
content += 'a(_a, "${record.ip}")\n'
|
||||
} else {
|
||||
content += 'a("${record.name}", "${record.ip}")\n'
|
||||
}
|
||||
}
|
||||
|
||||
for record in config.cname_records {
|
||||
if record.alias == '_a' {
|
||||
content += 'cname("${record.name}", _a)\n'
|
||||
} else {
|
||||
content += 'cname("${record.name}", "${record.alias}")\n'
|
||||
}
|
||||
}
|
||||
|
||||
for record in config.caa_records {
|
||||
content += 'caa("${record.name}", "${record.value}", "${record.tag}")\n'
|
||||
}
|
||||
|
||||
file.write(content)!
|
||||
repo.commit('Update DNS records')!
|
||||
repo.pull()!
|
||||
repo.push()!
|
||||
}
|
||||
28
lib/develop/luadns/model.v
Normal file
28
lib/develop/luadns/model.v
Normal file
@@ -0,0 +1,28 @@
|
||||
module luadns
|
||||
|
||||
struct ARecord {
|
||||
mut:
|
||||
name string
|
||||
ip string
|
||||
}
|
||||
|
||||
struct CNAMERecord {
|
||||
mut:
|
||||
name string
|
||||
alias string
|
||||
}
|
||||
|
||||
struct CAARecord {
|
||||
mut:
|
||||
name string
|
||||
value string
|
||||
tag string
|
||||
}
|
||||
|
||||
struct DNSConfig {
|
||||
mut:
|
||||
domain string
|
||||
a_records []ARecord
|
||||
cname_records []CNAMERecord
|
||||
caa_records []CAARecord
|
||||
}
|
||||
56
lib/develop/luadns/parse.v
Normal file
56
lib/develop/luadns/parse.v
Normal file
@@ -0,0 +1,56 @@
|
||||
module luadns
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
|
||||
fn parse_dns_configs(directory_path string) ![]DNSConfig {
|
||||
mut configs := []DNSConfig{}
|
||||
|
||||
mut luadns_dir := pathlib.get_dir(path: directory_path)!
|
||||
|
||||
mut list := luadns_dir.list()!
|
||||
|
||||
for mut file in list.paths {
|
||||
if file.extension() == 'lua' {
|
||||
config := parse_luadns_file(file.path)!
|
||||
configs << config
|
||||
}
|
||||
}
|
||||
|
||||
return configs
|
||||
}
|
||||
|
||||
fn parse_luadns_file(file_path string) !DNSConfig {
|
||||
mut config := DNSConfig{}
|
||||
|
||||
mut file := pathlib.get_file(path: file_path)!
|
||||
content := file.read()!
|
||||
|
||||
for line in content.split('\n') {
|
||||
trimmed_line := line.trim_space()
|
||||
if trimmed_line.len == 0 || trimmed_line.starts_with('//') {
|
||||
continue
|
||||
}
|
||||
|
||||
if trimmed_line.starts_with('a(') {
|
||||
parts := trimmed_line.all_after('a(').all_before(')').split(',')
|
||||
name := parts[0].trim('" ')
|
||||
ip := parts[1].trim('" ')
|
||||
config.a_records << ARecord{name, ip}
|
||||
} else if trimmed_line.starts_with('cname(') {
|
||||
parts := trimmed_line.all_after('cname(').all_before(')').split(',')
|
||||
name := parts[0].trim('" ')
|
||||
alias := parts[1].trim('" ')
|
||||
config.cname_records << CNAMERecord{name, alias}
|
||||
} else if trimmed_line.starts_with('caa(') {
|
||||
parts := trimmed_line.all_after('caa(').all_before(')').split(',')
|
||||
name := parts[0].trim('" ')
|
||||
value := parts[1].trim('" ')
|
||||
tag := parts[2].trim('" ')
|
||||
config.caa_records << CAARecord{name, value, tag}
|
||||
}
|
||||
}
|
||||
|
||||
config.domain = os.base(file_path).all_before('.lua')
|
||||
return config
|
||||
}
|
||||
20
lib/develop/luadns/utils.v
Normal file
20
lib/develop/luadns/utils.v
Normal file
@@ -0,0 +1,20 @@
|
||||
module luadns
|
||||
|
||||
fn is_valid_ip(ip string) bool {
|
||||
parts := ip.split('.')
|
||||
if parts.len != 4 {
|
||||
return false
|
||||
}
|
||||
for part in parts {
|
||||
num := part.int()
|
||||
if num < 0 || num > 255 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn is_valid_domain(domain string) bool {
|
||||
// TODO: implement
|
||||
return true
|
||||
}
|
||||
120
lib/installers/develapps/chrome/chrome.v
Normal file
120
lib/installers/develapps/chrome/chrome.v
Normal file
@@ -0,0 +1,120 @@
|
||||
module chrome
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import os
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
uninstall bool
|
||||
}
|
||||
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
// base.install()!
|
||||
if args.reset || args.uninstall {
|
||||
console.print_header('uninstall chrome')
|
||||
uninstall()!
|
||||
console.print_debug(' - ok')
|
||||
if args.uninstall {
|
||||
return
|
||||
}
|
||||
}
|
||||
console.print_header('package_install install chrome')
|
||||
if !args.reset && osal.done_exists('install_chrome') && exists()! {
|
||||
console.print_debug(' - already installed')
|
||||
return
|
||||
}
|
||||
mut url := ''
|
||||
platform := core.platform()!
|
||||
if platform in [.alpine, .arch, .ubuntu] {
|
||||
// url = 'https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'
|
||||
panic('not implemented yet')
|
||||
} else if platform == .osx {
|
||||
url = 'https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg'
|
||||
}
|
||||
console.print_debug(' download ${url}')
|
||||
_ = osal.download(
|
||||
url: url
|
||||
minsize_kb: 5000
|
||||
reset: args.reset
|
||||
dest: '/tmp/googlechrome.dmg'
|
||||
)!
|
||||
|
||||
cmd := "
|
||||
hdiutil attach /tmp/googlechrome.dmg
|
||||
echo ' - copy chrome into app folder'
|
||||
echo ' - will now copy all files to Application folder, this can take a while'
|
||||
cp -r /Volumes/Google\\ Chrome/Google\\ Chrome.app /Applications/
|
||||
sleep 30
|
||||
echo ' - copy done'
|
||||
hdiutil detach /Volumes/Google\\ Chrome/
|
||||
rm -f /tmp/googlechrome.dmg
|
||||
"
|
||||
osal.exec(cmd: cmd)!
|
||||
console.print_debug(' - copy done to Application folder.')
|
||||
|
||||
if exists()! {
|
||||
console.print_debug(' - exists check ok.')
|
||||
}
|
||||
|
||||
osal.done_set('install_chrome', 'OK')!
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ExtensionsInstallArgs {
|
||||
pub mut:
|
||||
extensions string
|
||||
default bool = true
|
||||
}
|
||||
|
||||
pub fn exists() !bool {
|
||||
cmd := 'mdfind "kMDItemKind == \'Application\'" | grep "Google Chrome"'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn install_path() !string {
|
||||
cmd := 'mdfind "kMDItemKind == \'Application\'" | grep "Google Chrome"'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code > 0 {
|
||||
return error("can't find install path")
|
||||
}
|
||||
return res.output.trim_space()
|
||||
}
|
||||
|
||||
pub fn uninstall() ! {
|
||||
cmd := '
|
||||
# Quit Google Chrome
|
||||
osascript -e \'quit app "Google Chrome"\'
|
||||
|
||||
# Wait a bit to ensure Chrome has completely quit
|
||||
sleep 2
|
||||
|
||||
# Remove the Google Chrome Application
|
||||
rm -rf "/Applications/Google Chrome.app"
|
||||
|
||||
# Remove Chrome’s Application Support Data
|
||||
rm -rf ~/Library/Application\\ Support/Google/Chrome
|
||||
|
||||
# Remove Chrome\'s Caches
|
||||
rm -rf ~/Library/Caches/Google/Chrome
|
||||
|
||||
# Delete Chrome Preferences
|
||||
rm -rf ~/Library/Preferences/com.google.Chrome.plist
|
||||
|
||||
# Clear Chrome Saved Application State
|
||||
rm -rf ~/Library/Saved\\ Application\\ State/com.google.Chrome.savedState
|
||||
|
||||
'
|
||||
osal.exec(cmd: cmd)!
|
||||
}
|
||||
|
||||
// # Optional: Empty the Trash
|
||||
// osascript -e 'tell app "Finder" to empty'
|
||||
132
lib/installers/develapps/vscode/vscode.v
Normal file
132
lib/installers/develapps/vscode/vscode.v
Normal file
@@ -0,0 +1,132 @@
|
||||
module vscode
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import os
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
// base.install()!
|
||||
console.print_header('install vscode')
|
||||
if !args.reset && osal.done_exists('install_vscode') && osal.cmd_exists('code') {
|
||||
console.print_debug(' - already installed')
|
||||
return
|
||||
}
|
||||
mut url := ''
|
||||
platform := core.platform()!
|
||||
if platform in [.alpine, .arch, .ubuntu] {
|
||||
if core.cputype()! == .arm {
|
||||
url = 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-arm64'
|
||||
} else {
|
||||
url = 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64'
|
||||
}
|
||||
} else if platform == .osx {
|
||||
if core.cputype()! == .arm {
|
||||
url = 'https://code.visualstudio.com/sha/download?build=stable&os=cli-darwin-arm64'
|
||||
} else {
|
||||
url = 'https://code.visualstudio.com/sha/download?build=stable&os=cli-darwin-x64'
|
||||
}
|
||||
}
|
||||
console.print_debug(' download ${url}')
|
||||
_ = osal.download(
|
||||
url: url
|
||||
minsize_kb: 5000
|
||||
reset: args.reset
|
||||
dest: '/tmp/vscode.zip'
|
||||
expand_file: '/tmp/download/vscode'
|
||||
)!
|
||||
|
||||
osal.cmd_add(
|
||||
cmdname: 'code'
|
||||
source: '/tmp/download/vscode/code'
|
||||
reset: true
|
||||
)!
|
||||
|
||||
extensions_install(default: true)!
|
||||
|
||||
osal.done_set('install_vscode', 'OK')!
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ExtensionsInstallArgs {
|
||||
pub mut:
|
||||
extensions string
|
||||
default bool = true
|
||||
}
|
||||
|
||||
pub fn extensions_install(args_ ExtensionsInstallArgs) ! {
|
||||
mut args := args_
|
||||
mut items := []string{}
|
||||
for item in args.extensions.split(',').map(it.trim_space()) {
|
||||
if item.trim_space() == '' {
|
||||
continue
|
||||
}
|
||||
if item !in items {
|
||||
items << item
|
||||
}
|
||||
}
|
||||
default := [
|
||||
'golang.go',
|
||||
'ms-azuretools.vscode-docker',
|
||||
'ms-python.autopep8',
|
||||
'ms-python.python',
|
||||
'ms-vscode-remote.remote-ssh',
|
||||
'ms-vscode-remote.remote-ssh-edit',
|
||||
'ms-vscode-remote.remote-containers',
|
||||
'ms-vscode.cmake-tools',
|
||||
'ms-vscode.makefile-tools',
|
||||
'ms-vscode.remote-explorer',
|
||||
'ms-vscode.remote-repositories',
|
||||
'ms-vsliveshare.vsliveshare',
|
||||
'redhat.vscode-yaml',
|
||||
'rust-lang.rust-analyzer',
|
||||
'sumneko.lua',
|
||||
'shd101wyy.markdown-preview-enhanced',
|
||||
'TakumiI.markdowntable',
|
||||
'telesoho.vscode-markdown-paste-image',
|
||||
'tamasfe.even-better-toml',
|
||||
'tomoki1207.pdf',
|
||||
'VOSCA.vscode-v-analyzer',
|
||||
'yzhang.markdown-all-in-one',
|
||||
'zamerick.vscode-caddyfile-syntax',
|
||||
'zxh404.vscode-proto3',
|
||||
]
|
||||
if args.default {
|
||||
for item in default {
|
||||
if item !in items {
|
||||
items << item
|
||||
}
|
||||
}
|
||||
}
|
||||
for item in items {
|
||||
cmd := 'code --install-extension ${item}'
|
||||
console.print_debug(' - extension install: ${item}')
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code > 0 {
|
||||
return error("could not install visual studio code extension:'${item}'.\n${res}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extensions_list() ![]string {
|
||||
cmd := 'code --list-extensions'
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code > 0 {
|
||||
return error('could not list visual studio code extensions.\n${res}')
|
||||
}
|
||||
mut res2 := []string{}
|
||||
for i in res.output.split_into_lines().map(it.trim_space()) {
|
||||
if i.trim_space() == '' {
|
||||
continue
|
||||
}
|
||||
res2 << i
|
||||
}
|
||||
return res2
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import os
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
res := os.execute('${osal.profile_path_source_and()} livekit-server -v')
|
||||
res := os.execute('${osal.profile_path_source_and()!} livekit-server -v')
|
||||
if res.exit_code != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
13
lib/installers/infra/zinit/.heroscript
Normal file
13
lib/installers/infra/zinit/.heroscript
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
!!hero_code.generate_installer
|
||||
name:'zinit'
|
||||
classname:'Zinit'
|
||||
singleton:1
|
||||
templates:0
|
||||
default:1
|
||||
title:''
|
||||
supported_platforms:''
|
||||
reset:0
|
||||
startupmanager:1
|
||||
hasconfig:0
|
||||
build:1
|
||||
34
lib/installers/infra/zinit/readme.md
Normal file
34
lib/installers/infra/zinit/readme.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# zinit
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.installers.something. zinit
|
||||
|
||||
mut installer:= zinit.get()!
|
||||
|
||||
installer.start()!
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
```hero
|
||||
!!zinit.install
|
||||
homedir: '/home/user/zinit'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
title: 'Some Title'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
```
|
||||
|
||||
|
||||
132
lib/installers/infra/zinit/zinit_actions.v
Normal file
132
lib/installers/infra/zinit/zinit_actions.v
Normal file
@@ -0,0 +1,132 @@
|
||||
module zinit
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.installers.ulist
|
||||
import freeflowuniverse.herolib.installers.lang.rust
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.osal.systemd
|
||||
import os
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
cmd := 'zinit --version'
|
||||
// console.print_debug(cmd)
|
||||
res := os.execute(cmd)
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.trim_space().starts_with('zinit v'))
|
||||
if r.len != 1 {
|
||||
return error("couldn't parse zinit version.\n${res.output}")
|
||||
}
|
||||
if texttools.version(version) == texttools.version(r[0].all_after_first('zinit v')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
console.print_debug(res.str())
|
||||
return false
|
||||
}
|
||||
|
||||
fn install() ! {
|
||||
console.print_header('install zinit')
|
||||
if !osal.is_linux() {
|
||||
return error('only support linux for now')
|
||||
}
|
||||
|
||||
release_url := 'https://github.com/threefoldtech/zinit/releases/download/v0.2.14/zinit'
|
||||
|
||||
mut dest := osal.download(
|
||||
url: release_url
|
||||
minsize_kb: 2000
|
||||
reset: true
|
||||
)!
|
||||
|
||||
osal.cmd_add(
|
||||
cmdname: 'zinit'
|
||||
source: dest.path
|
||||
)!
|
||||
|
||||
osal.dir_ensure('/etc/zinit')!
|
||||
|
||||
console.print_header('install zinit done')
|
||||
}
|
||||
|
||||
fn build() ! {
|
||||
if !osal.is_linux() {
|
||||
return error('only support linux for now')
|
||||
}
|
||||
|
||||
rust.install()!
|
||||
|
||||
// install zinit if it was already done will return true
|
||||
console.print_header('build zinit')
|
||||
|
||||
mut gs := gittools.get(coderoot: '/tmp/builder')!
|
||||
mut repo := gs.get_repo(
|
||||
url: 'https://github.com/threefoldtech/zinit'
|
||||
reset: true
|
||||
pull: true
|
||||
)!
|
||||
gitpath := repo.get_path()!
|
||||
|
||||
// source ${osal.profile_path()}
|
||||
|
||||
cmd := '
|
||||
source ~/.cargo/env
|
||||
cd ${gitpath}
|
||||
make release
|
||||
'
|
||||
osal.execute_stdout(cmd)!
|
||||
|
||||
osal.cmd_add(
|
||||
cmdname: 'zinit'
|
||||
source: '/tmp/builder/github/threefoldtech/zinit/target/x86_64-unknown-linux-musl/release/zinit'
|
||||
)!
|
||||
}
|
||||
|
||||
// get the Upload List of the files
|
||||
fn ulist_get() !ulist.UList {
|
||||
return ulist.UList{}
|
||||
}
|
||||
|
||||
// uploads to S3 server if configured
|
||||
fn upload() ! {
|
||||
}
|
||||
|
||||
fn startupcmd() ![]ZProcessNewArgs {
|
||||
mut res := []zinit.ZProcessNewArgs{}
|
||||
res << ZProcessNewArgs{
|
||||
name: 'zinit'
|
||||
cmd: '/usr/local/bin/zinit init'
|
||||
startuptype: .systemd
|
||||
start: true
|
||||
restart: true
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn running() !bool {
|
||||
cmd := 'zinit list'
|
||||
return osal.execute_ok(cmd)
|
||||
}
|
||||
|
||||
fn start_pre() ! {
|
||||
}
|
||||
|
||||
fn start_post() ! {
|
||||
}
|
||||
|
||||
fn stop_pre() ! {
|
||||
}
|
||||
|
||||
fn stop_post() ! {
|
||||
}
|
||||
|
||||
fn destroy() ! {
|
||||
mut systemdfactory := systemd.new()!
|
||||
systemdfactory.destroy('zinit')!
|
||||
|
||||
osal.process_kill_recursive(name: 'zinit')!
|
||||
osal.cmd_delete('zinit')!
|
||||
}
|
||||
153
lib/installers/infra/zinit/zinit_factory_.v
Normal file
153
lib/installers/infra/zinit/zinit_factory_.v
Normal file
@@ -0,0 +1,153 @@
|
||||
module zinit
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
__global (
|
||||
zinit_global map[string]&Zinit
|
||||
zinit_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&Zinit {
|
||||
return &Zinit{}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn startupmanager_get(cat 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()!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) start() ! {
|
||||
switch(self.name)
|
||||
if self.running()! {
|
||||
return
|
||||
}
|
||||
|
||||
console.print_header('zinit start')
|
||||
|
||||
if !installed()! {
|
||||
install()!
|
||||
}
|
||||
|
||||
configure()!
|
||||
|
||||
start_pre()!
|
||||
|
||||
for zprocess in startupcmd()! {
|
||||
mut sm := startupmanager_get(zprocess.startuptype)!
|
||||
|
||||
console.print_debug('starting zinit 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('zinit did not install properly.')
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) install_start(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
self.install(args)!
|
||||
self.start()!
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) 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 Zinit) restart() ! {
|
||||
switch(self.name)
|
||||
self.stop()!
|
||||
self.start()!
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) 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()!
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset || (!installed()!) {
|
||||
install()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) build() ! {
|
||||
switch(self.name)
|
||||
build()!
|
||||
}
|
||||
|
||||
pub fn (mut self Zinit) destroy() ! {
|
||||
switch(self.name)
|
||||
self.stop() or {}
|
||||
destroy()!
|
||||
}
|
||||
|
||||
// switch instance to be used for zinit
|
||||
pub fn switch(name string) {
|
||||
zinit_default = name
|
||||
}
|
||||
26
lib/installers/infra/zinit/zinit_model.v
Normal file
26
lib/installers/infra/zinit/zinit_model.v
Normal file
@@ -0,0 +1,26 @@
|
||||
module zinit
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
import os
|
||||
|
||||
pub const version = '0.2.14'
|
||||
const singleton = true
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
|
||||
pub struct Zinit {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
fn obj_init(obj_ Zinit) !Zinit {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
|
||||
// called before start if done
|
||||
fn configure() ! {
|
||||
// mut installer := get()!
|
||||
}
|
||||
@@ -16,8 +16,8 @@ import freeflowuniverse.herolib.installers.lang.nodejs
|
||||
import freeflowuniverse.herolib.installers.lang.python
|
||||
import freeflowuniverse.herolib.installers.web.zola
|
||||
import freeflowuniverse.herolib.installers.web.tailwind
|
||||
import freeflowuniverse.herolib.installers.hero.heroweb
|
||||
import freeflowuniverse.herolib.installers.hero.herodev
|
||||
// import freeflowuniverse.herolib.installers.hero.heroweb
|
||||
// import freeflowuniverse.herolib.installers.hero.herodev
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.rclone
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.prometheus
|
||||
@@ -51,7 +51,7 @@ pub fn names(args_ InstallArgs) []string {
|
||||
grafana
|
||||
hero
|
||||
herodev
|
||||
heroweb
|
||||
// heroweb
|
||||
lima
|
||||
mycelium
|
||||
nodejs
|
||||
@@ -108,9 +108,9 @@ pub fn install_multi(args_ InstallArgs) ! {
|
||||
git_reset: args.gitreset
|
||||
)!
|
||||
}
|
||||
'hero' {
|
||||
herolib.hero_install(reset: args.reset)!
|
||||
}
|
||||
// 'hero' {
|
||||
// herolib.hero_install(reset: args.reset)!
|
||||
// }
|
||||
'caddy' {
|
||||
// caddy.install(reset: args.reset)!
|
||||
// caddy.configure_examples()!
|
||||
@@ -123,30 +123,30 @@ pub fn install_multi(args_ InstallArgs) ! {
|
||||
mycelium.start()!
|
||||
}
|
||||
'garage_s3' {
|
||||
garage_s3.install(reset: args.reset, config_reset: args.reset, restart: true)!
|
||||
mut garages3 := garage_s3.get()!
|
||||
garages3.install(reset: args.reset)!
|
||||
}
|
||||
'fungistor' {
|
||||
fungistor.install(reset: args.reset)!
|
||||
}
|
||||
'lima' {
|
||||
lima.install(reset: args.reset, uninstall: args.uninstall)!
|
||||
}
|
||||
'herocontainers' {
|
||||
mut podman_installer0 := podman_installer.get()!
|
||||
mut buildah_installer0 := buildah_installer.get()!
|
||||
|
||||
if args.reset {
|
||||
podman_installer0.destroy()! // will remove all
|
||||
buildah_installer0.destroy()! // will remove all
|
||||
}
|
||||
podman_installer0.install()!
|
||||
buildah_installer0.install()!
|
||||
lima.install_(reset: args.reset, uninstall: args.uninstall)!
|
||||
}
|
||||
// 'herocontainers' {
|
||||
// mut podman_installer0 := podman_installer.get()!
|
||||
// mut buildah_installer0 := buildah_installer.get()!
|
||||
// if args.reset {
|
||||
// podman_installer0.destroy()! // will remove all
|
||||
// buildah_installer0.destroy()! // will remove all
|
||||
// }
|
||||
// podman_installer0.install()!
|
||||
// buildah_installer0.install()!
|
||||
// }
|
||||
'prometheus' {
|
||||
prometheus.install(reset: args.reset, uninstall: args.uninstall)!
|
||||
prometheus.install(reset: args.reset)!
|
||||
}
|
||||
'grafana' {
|
||||
grafana.install(reset: args.reset, uninstall: args.uninstall)!
|
||||
grafana.install(reset: args.reset)!
|
||||
}
|
||||
'vscode' {
|
||||
vscode.install(reset: args.reset)!
|
||||
@@ -157,11 +157,11 @@ pub fn install_multi(args_ InstallArgs) ! {
|
||||
'python' {
|
||||
python.install()!
|
||||
}
|
||||
'herodev' {
|
||||
herodev.install()!
|
||||
}
|
||||
// 'herodev' {
|
||||
// herodev.install()!
|
||||
// }
|
||||
// 'heroweb' {
|
||||
// heroweb.install()!
|
||||
// heroweb.install()!
|
||||
// }
|
||||
'dagu' {
|
||||
// will call the installer underneith
|
||||
|
||||
129
lib/installers/lang/herolib/crystallib.v
Normal file
129
lib/installers/lang/herolib/crystallib.v
Normal file
@@ -0,0 +1,129 @@
|
||||
module herolib
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.installers.base
|
||||
import freeflowuniverse.herolib.installers.lang.vlang
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import os
|
||||
// install herolib will return true if it was already installed
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
git_pull bool
|
||||
git_reset bool
|
||||
reset bool // means reinstall
|
||||
}
|
||||
|
||||
pub fn install(args InstallArgs) ! {
|
||||
// install herolib if it was already done will return true
|
||||
console.print_header('install herolib (reset: ${args.reset})')
|
||||
// osal.package_refresh()!
|
||||
if args.reset {
|
||||
osal.done_reset()!
|
||||
}
|
||||
base.install(develop: true)!
|
||||
vlang.install(reset: args.reset)!
|
||||
vlang.v_analyzer_install(reset: args.reset)!
|
||||
|
||||
mut gs := gittools.get()!
|
||||
gs.config.light = true // means we clone depth 1
|
||||
|
||||
mut repo := gs.get_repo(
|
||||
pull: args.git_pull
|
||||
reset: args.git_reset
|
||||
url: 'https://github.com/freeflowuniverse/herolib/tree/development/lib'
|
||||
)!
|
||||
|
||||
// mut repo2 := gs.get_repo(
|
||||
// pull: args.git_pull
|
||||
// reset: args.git_reset
|
||||
// url: 'https://github.com/freeflowuniverse/webcomponents/tree/main/webcomponents'
|
||||
// )!
|
||||
|
||||
mut path1 := repo.get_path()!
|
||||
// mut path2 := repo2.get_path()!
|
||||
|
||||
mut path1p := pathlib.get_dir(path: path1, create: false)!
|
||||
// mut path2p := pathlib.get_dir(path: path2, create: false)!
|
||||
path1p.link('${os.home_dir()}/.vmodules/freeflowuniverse/herolib', true)!
|
||||
// path2p.link('${os.home_dir()}/.vmodules/freeflowuniverse/webcomponents', true)!
|
||||
|
||||
// hero_compile()!
|
||||
|
||||
osal.done_set('install_herolib', 'OK')!
|
||||
return
|
||||
}
|
||||
|
||||
// check if herolib installed and hero, if not do so
|
||||
pub fn check() ! {
|
||||
if osal.done_exists('install_herolib') {
|
||||
return
|
||||
}
|
||||
install()!
|
||||
}
|
||||
|
||||
// remove hero, crystal, ...
|
||||
pub fn uninstall() ! {
|
||||
console.print_debug('uninstall hero & herolib')
|
||||
cmd := '
|
||||
rm -rf ${os.home_dir()}/hero
|
||||
rm -rf ${os.home_dir()}/_code
|
||||
rm -f /usr/local/bin/hero
|
||||
rm -f /tmp/hero
|
||||
rm -f /tmp/install*
|
||||
rm -f /tmp/build_hero*
|
||||
rm -rf /tmp/execscripts
|
||||
'
|
||||
osal.execute_stdout(cmd) or { return error('Cannot uninstall herolib/hero.\n${err}') }
|
||||
}
|
||||
|
||||
pub fn hero_install(args InstallArgs) ! {
|
||||
if args.reset == false && osal.done_exists('install_hero') {
|
||||
console.print_debug('hero already installed')
|
||||
return
|
||||
}
|
||||
console.print_header('install hero')
|
||||
base.install()!
|
||||
|
||||
cmd := "
|
||||
cd /tmp
|
||||
export TERM=xterm
|
||||
curl 'https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/main/install_v.sh' > /tmp/install_v.sh
|
||||
bash /tmp/install_v.sh --analyzer --herolib
|
||||
"
|
||||
osal.execute_stdout(cmd) or { return error('Cannot install hero.\n${err}') }
|
||||
osal.done_set('install_hero', 'OK')!
|
||||
return
|
||||
}
|
||||
|
||||
pub fn hero_compile(args InstallArgs) ! {
|
||||
if args.reset == false && osal.done_exists('compile_hero') {
|
||||
console.print_debug('hero already compiled')
|
||||
return
|
||||
}
|
||||
console.print_header('compile hero')
|
||||
|
||||
home_dir := os.home_dir()
|
||||
cmd_hero := texttools.template_replace($tmpl('templates/hero.sh'))
|
||||
osal.exec(cmd: cmd_hero, stdout: false)!
|
||||
|
||||
osal.execute_stdout(cmd_hero) or { return error('Cannot compile hero.\n${err}') }
|
||||
osal.done_set('compile_hero', 'OK')!
|
||||
return
|
||||
}
|
||||
|
||||
// pub fn update() ! {
|
||||
// console.print_header('package_install update herolib')
|
||||
// if !(i.state == .reset) && osal.done_exists('install_crystaltools') {
|
||||
// console.print_debug(' package_install was already done')
|
||||
// return
|
||||
// }
|
||||
// osal.execute_silent('cd /tmp && export TERM=xterm && source /root/env.sh && ct_upgrade') or {
|
||||
// return error('Cannot update crystal tools.\n${err}')
|
||||
// }
|
||||
// osal.done_set('update_crystaltools', 'OK')!
|
||||
// }
|
||||
21
lib/installers/lang/herolib/templates/hero.sh
Normal file
21
lib/installers/lang/herolib/templates/hero.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
export PATH=${home_dir}/hero/bin:??PATH
|
||||
export TERM=xterm
|
||||
|
||||
cd ${home_dir}/code/github/freeflowuniverse/crystallib/cli/hero
|
||||
|
||||
PRF="${home_dir}/.profile"
|
||||
[ -f "??PRF" ] && source "??PRF"
|
||||
|
||||
if [[ "??OSTYPE" == "linux-gnu"* ]]; then
|
||||
#v -enable-globals -w -cflags -static -cc gcc hero.v
|
||||
v -enable-globals -w -n hero.v
|
||||
export HEROPATH='/usr/local/bin/hero'
|
||||
elif [[ "??OSTYPE" == "darwin"* ]]; then
|
||||
v -enable-globals -w -n hero.v
|
||||
export HEROPATH=${home_dir}/hero/bin/hero
|
||||
fi
|
||||
|
||||
chmod +x hero
|
||||
|
||||
cp hero ??HEROPATH
|
||||
rm hero
|
||||
1
lib/installers/lang/vlang/readme.md
Normal file
1
lib/installers/lang/vlang/readme.md
Normal file
@@ -0,0 +1 @@
|
||||
https://github.com/v-analyzer/v-analyzer
|
||||
98
lib/installers/lang/vlang/v-analyzer.v
Normal file
98
lib/installers/lang/vlang/v-analyzer.v
Normal file
@@ -0,0 +1,98 @@
|
||||
module vlang
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
// import freeflowuniverse.herolib.sysadmin.downloader
|
||||
|
||||
pub fn v_analyzer_install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
console.print_header('install v-analyzer (reset: ${args.reset})')
|
||||
version := '0.0.4'
|
||||
_ := core.platform()!
|
||||
res := os.execute('${osal.profile_path_source_and()!} v-analyzer version')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.trim_space().starts_with('v-analyzer'))
|
||||
if r.len != 1 {
|
||||
return error("couldn't parse v-analyzer version.\n${res.output}")
|
||||
}
|
||||
mut myversion := r[0].all_after_first('version').trim_space()
|
||||
if texttools.version(version) > texttools.version(myversion) {
|
||||
args.reset = true
|
||||
}
|
||||
} else {
|
||||
args.reset = true
|
||||
}
|
||||
|
||||
if args.reset == false {
|
||||
console.print_debug('v-analyzer already installed')
|
||||
return
|
||||
}
|
||||
|
||||
install()!
|
||||
|
||||
if args.reset {
|
||||
console.print_header('install v-analyzer')
|
||||
cmd := '
|
||||
export TERM=xterm
|
||||
mkdir -p ${os.home_dir()}/_code
|
||||
cd ${os.home_dir()}/_code
|
||||
rm -rf ${os.home_dir()}/_code/v-analyzer
|
||||
git clone --filter=blob:none --recursive --shallow-submodules https://github.com/vlang/v-analyzer
|
||||
cd v-analyzer
|
||||
v build.vsh debug
|
||||
'
|
||||
osal.execute_stdout(cmd) or { return error('Cannot install hero.\n${err}') }
|
||||
osal.cmd_add(
|
||||
cmdname: 'v-analyzer'
|
||||
source: '${os.home_dir()}/_code/v-analyzer/bin/v-analyzer'
|
||||
)!
|
||||
}
|
||||
|
||||
// if pl == .ubuntu {
|
||||
// }else{
|
||||
// mut url := ''
|
||||
// if osal.is_linux_intel() {
|
||||
// url = 'https://github.com/vlang/v-analyzer/releases/download/nightly/v-analyzer-linux-x86_64.zip'
|
||||
// } else if osal.is_osx_arm() {
|
||||
// url = 'https://github.com/vlang/v-analyzer/releases/download/nightly/v-analyzer-darwin-arm64.zip'
|
||||
// } else if osal.is_osx_intel() {
|
||||
// url = 'https://github.com/vlang/v-analyzer/releases/download/nightly/v-analyzer-darwin-x86_64.zip'
|
||||
// } else {
|
||||
// return error('unsported platform for installing v-analyzer')
|
||||
// }
|
||||
|
||||
// mut dest := osal.download(
|
||||
// url: url
|
||||
// minsize_kb: 1000
|
||||
// expand_dir: '/tmp/v-analyzer'
|
||||
// )!
|
||||
|
||||
// mut binpath := dest.file_get('v-analyzer')!
|
||||
// osal.cmd_add(
|
||||
// cmdname: 'v-analyzer'
|
||||
// source: binpath.path
|
||||
// )!
|
||||
// }
|
||||
|
||||
// if args.reset == false && osal.done_exists('install_v_analyzer') {
|
||||
// console.print_debug(' v analyzer already installed')
|
||||
// return
|
||||
// }
|
||||
// console.print_header('install v analyzer')
|
||||
|
||||
// cmd := '
|
||||
// cd /tmp
|
||||
// export TERM=xterm
|
||||
// source ~/.profile
|
||||
// rm -f install.sh
|
||||
// curl -fksSL https://raw.githubusercontent.com/v-lang/v-analyzer/master/install.vsh > install.vsh
|
||||
// v run install.vsh --no-interaction
|
||||
// '
|
||||
// osal.execute_stdout(cmd) or { return error('Cannot install hero.\n${err}') }
|
||||
|
||||
osal.done_set('install_v_analyzer', 'OK')!
|
||||
return
|
||||
}
|
||||
73
lib/installers/lang/vlang/vlang.v
Normal file
73
lib/installers/lang/vlang/vlang.v
Normal file
@@ -0,0 +1,73 @@
|
||||
module vlang
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import os
|
||||
import freeflowuniverse.herolib.installers.base
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
// import freeflowuniverse.herolib.sysadmin.downloader
|
||||
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
version := '0.4.8'
|
||||
console.print_header('install vlang (reset: ${args.reset})')
|
||||
res := os.execute('${osal.profile_path_source_and()!} v --version')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.trim_space().starts_with('V'))
|
||||
if r.len != 1 {
|
||||
return error("couldn't parse v version.\n${res.output}")
|
||||
}
|
||||
myversion := r[0].all_after_first('V ').all_before(' ').trim_space()
|
||||
console.print_debug("V version: '${myversion}'")
|
||||
if texttools.version(version) > texttools.version(myversion) {
|
||||
// println(texttools.version(version))
|
||||
// println(texttools.version(myversion))
|
||||
// if true{panic("s")}
|
||||
args.reset = true
|
||||
}
|
||||
} else {
|
||||
args.reset = true
|
||||
}
|
||||
|
||||
// install vlang if it was already done will return true
|
||||
if args.reset == false {
|
||||
return
|
||||
}
|
||||
|
||||
base.develop()!
|
||||
|
||||
mut gs := gittools.get(coderoot: '${os.home_dir()}/_code')!
|
||||
mut repo := gs.get_repo(
|
||||
pull: true
|
||||
reset: true
|
||||
url: 'https://github.com/vlang/v/tree/master'
|
||||
)!
|
||||
|
||||
mut path1 := repo.get_path()!
|
||||
|
||||
mut extra := ''
|
||||
if core.is_linux()! {
|
||||
extra = './v symlink'
|
||||
} else {
|
||||
extra = 'cp v ${os.home_dir()}/bin/'
|
||||
}
|
||||
cmd := '
|
||||
cd ${path1}
|
||||
make
|
||||
${extra}
|
||||
'
|
||||
console.print_header('compile')
|
||||
osal.exec(cmd: cmd, stdout: true)!
|
||||
console.print_header('compile done')
|
||||
|
||||
osal.done_set('install_vlang', 'OK')!
|
||||
return
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import os
|
||||
import time
|
||||
|
||||
// install yggdrasil will return true if it was already installed
|
||||
pub fn installll(args_ InstallArgs) ! {
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
peers := '
|
||||
Peers:
|
||||
[
|
||||
|
||||
@@ -5,7 +5,7 @@ import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
|
||||
pub fn installlll(args_ InstallArgs) ! {
|
||||
pub fn installl(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
version := '0.2.10'
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.lang.python
|
||||
// import os
|
||||
|
||||
pub fn installll(args_ InstallArgs) ! {
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
if args.reset == false && osal.done_exists('install_b2') {
|
||||
|
||||
13
lib/installers/sysadmintools/daguserver/.heroscript
Normal file
13
lib/installers/sysadmintools/daguserver/.heroscript
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
!!hero_code.generate_installer
|
||||
name:'daguserver'
|
||||
classname:'DaguInstaller'
|
||||
singleton:1
|
||||
templates:1
|
||||
default:1
|
||||
title:''
|
||||
supported_platforms:''
|
||||
reset:0
|
||||
startupmanager:1
|
||||
hasconfig:1
|
||||
build:0
|
||||
1
lib/installers/sysadmintools/daguserver/dagu_test.v
Normal file
1
lib/installers/sysadmintools/daguserver/dagu_test.v
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
152
lib/installers/sysadmintools/daguserver/daguserver_actions.v
Normal file
152
lib/installers/sysadmintools/daguserver/daguserver_actions.v
Normal file
@@ -0,0 +1,152 @@
|
||||
module daguserver
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
// import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.crypt.secrets
|
||||
import os
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
res := os.execute('${osal.profile_path_source_and()!} dagu version')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.trim_space().len > 0)
|
||||
if r.len != 1 {
|
||||
return error("couldn't parse dagu version.\n${res.output}")
|
||||
}
|
||||
if texttools.version(version) > texttools.version(r[0]) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn install() ! {
|
||||
console.print_header('install daguserver')
|
||||
mut url := ''
|
||||
if core.is_linux_arm()! {
|
||||
url = 'https://github.com/dagu-dev/dagu/releases/download/v${version}/dagu_${version}_linux_arm64.tar.gz'
|
||||
} else if core.is_linux_intel()! {
|
||||
url = 'https://github.com/dagu-dev/dagu/releases/download/v${version}/dagu_${version}_linux_amd64.tar.gz'
|
||||
} else if core.is_osx_arm()! {
|
||||
url = 'https://github.com/dagu-dev/dagu/releases/download/v${version}/dagu_${version}_darwin_arm64.tar.gz'
|
||||
} else if core.is_osx_intel()! {
|
||||
url = 'https://github.com/dagu-dev/dagu/releases/download/v${version}/dagu_${version}_darwin_amd64.tar.gz'
|
||||
} else {
|
||||
return error('unsported platform')
|
||||
}
|
||||
|
||||
mut dest := osal.download(
|
||||
url: url
|
||||
minsize_kb: 9000
|
||||
expand_dir: '/tmp/dagu'
|
||||
)!
|
||||
|
||||
mut binpath := dest.file_get('dagu')!
|
||||
osal.cmd_add(
|
||||
cmdname: 'dagu'
|
||||
source: binpath.path
|
||||
)!
|
||||
}
|
||||
|
||||
fn startupcmd() ![]zinit.ZProcessNewArgs {
|
||||
mut res := []zinit.ZProcessNewArgs{}
|
||||
mut cfg := get()!
|
||||
|
||||
res << zinit.ZProcessNewArgs{
|
||||
name: 'dagu'
|
||||
cmd: 'dagu server'
|
||||
env: {
|
||||
'HOME ': os.home_dir()
|
||||
'DAGU_HOME ': cfg.configpath // config for dagu is called admin.yml and is in this dir
|
||||
}
|
||||
}
|
||||
|
||||
res << zinit.ZProcessNewArgs{
|
||||
name: 'dagu_scheduler'
|
||||
cmd: 'dagu scheduler'
|
||||
env: {
|
||||
'HOME ': os.home_dir()
|
||||
'DAGU_HOME ': cfg.configpath
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// user needs to us switch to make sure we get the right object
|
||||
fn configure() ! {
|
||||
mut cfg := get()!
|
||||
|
||||
if cfg.password == '' {
|
||||
cfg.password = secrets.hex_secret()!
|
||||
}
|
||||
|
||||
// TODO:use DAGU_SECRET from env variables in os if not set then empty string
|
||||
if cfg.secret == '' {
|
||||
cfg.secret = secrets.openssl_hex_secret(input: cfg.password)!
|
||||
}
|
||||
|
||||
mut mycode := $tmpl('templates/dagu.yaml')
|
||||
mut path := pathlib.get_file(path: '${cfg.configpath}/admin.yaml', create: true)!
|
||||
path.write(mycode)!
|
||||
console.print_debug(mycode)
|
||||
}
|
||||
|
||||
fn running() !bool {
|
||||
mut cfg := get()!
|
||||
// this checks health of dagu
|
||||
// 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: 'dagu', 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('Dagu is answering.')
|
||||
return true
|
||||
}
|
||||
|
||||
fn destroy() ! {
|
||||
cmd := '
|
||||
systemctl disable daguserver_scheduler.service
|
||||
systemctl disable daguserver.service
|
||||
systemctl stop daguserver_scheduler.service
|
||||
systemctl stop daguserver.service
|
||||
|
||||
systemctl list-unit-files | grep daguserver
|
||||
|
||||
pkill -9 -f daguserver
|
||||
|
||||
ps aux | grep daguserver
|
||||
|
||||
'
|
||||
|
||||
osal.execute_silent(cmd) or {}
|
||||
}
|
||||
|
||||
fn start_pre() ! {
|
||||
}
|
||||
|
||||
fn start_post() ! {
|
||||
}
|
||||
|
||||
fn stop_pre() ! {
|
||||
}
|
||||
|
||||
fn stop_post() ! {
|
||||
}
|
||||
266
lib/installers/sysadmintools/daguserver/daguserver_factory_.v
Normal file
266
lib/installers/sysadmintools/daguserver/daguserver_factory_.v
Normal file
@@ -0,0 +1,266 @@
|
||||
module daguserver
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
__global (
|
||||
daguserver_global map[string]&DaguInstaller
|
||||
daguserver_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = daguserver_default
|
||||
}
|
||||
if args.name == '' {
|
||||
args.name = 'default'
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&DaguInstaller {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in daguserver_global {
|
||||
if args.name == 'default' {
|
||||
if !config_exists(args) {
|
||||
if default {
|
||||
config_save(args)!
|
||||
}
|
||||
}
|
||||
config_load(args)!
|
||||
}
|
||||
}
|
||||
return daguserver_global[args.name] or {
|
||||
println(daguserver_global)
|
||||
panic('could not get config for daguserver with name:${args.name}')
|
||||
}
|
||||
}
|
||||
|
||||
fn config_exists(args_ ArgsGet) bool {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context() or { panic('bug') }
|
||||
return context.hero_config_exists('daguserver', args.name)
|
||||
}
|
||||
|
||||
fn config_load(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
mut heroscript := context.hero_config_get('daguserver', args.name)!
|
||||
play(heroscript: heroscript)!
|
||||
}
|
||||
|
||||
fn config_save(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_set('daguserver', args.name, heroscript_default()!)!
|
||||
}
|
||||
|
||||
fn set(o DaguInstaller) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
daguserver_global[o.name] = &o2
|
||||
daguserver_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.heroscript == '' {
|
||||
args.heroscript = heroscript_default()!
|
||||
}
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut install_actions := plbook.find(filter: 'daguserver.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 daguserver.configure\n${mycfg}')
|
||||
set(mycfg)!
|
||||
}
|
||||
}
|
||||
|
||||
mut other_actions := plbook.find(filter: 'daguserver.')!
|
||||
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 daguserver.destroy')
|
||||
destroy()!
|
||||
}
|
||||
if other_action.name == 'install' {
|
||||
console.print_debug('install action daguserver.install')
|
||||
install()!
|
||||
}
|
||||
}
|
||||
if other_action.name in ['start', 'stop', 'restart'] {
|
||||
mut p := other_action.params
|
||||
name := p.get('name')!
|
||||
mut daguserver_obj := get(name: name)!
|
||||
console.print_debug('action object:\n${daguserver_obj}')
|
||||
if other_action.name == 'start' {
|
||||
console.print_debug('install action daguserver.${other_action.name}')
|
||||
daguserver_obj.start()!
|
||||
}
|
||||
|
||||
if other_action.name == 'stop' {
|
||||
console.print_debug('install action daguserver.${other_action.name}')
|
||||
daguserver_obj.stop()!
|
||||
}
|
||||
if other_action.name == 'restart' {
|
||||
console.print_debug('install action daguserver.${other_action.name}')
|
||||
daguserver_obj.restart()!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# 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 DaguInstaller) reload() ! {
|
||||
switch(self.name)
|
||||
self = obj_init(self)!
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) start() ! {
|
||||
switch(self.name)
|
||||
if self.running()! {
|
||||
return
|
||||
}
|
||||
|
||||
console.print_header('daguserver start')
|
||||
|
||||
if !installed()! {
|
||||
install()!
|
||||
}
|
||||
|
||||
configure()!
|
||||
|
||||
start_pre()!
|
||||
|
||||
for zprocess in startupcmd()! {
|
||||
mut sm := startupmanager_get(zprocess.startuptype)!
|
||||
|
||||
console.print_debug('starting daguserver 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('daguserver did not install properly.')
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) install_start(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
self.install(args)!
|
||||
self.start()!
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) 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 DaguInstaller) restart() ! {
|
||||
switch(self.name)
|
||||
self.stop()!
|
||||
self.start()!
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) 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()!
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset || (!installed()!) {
|
||||
install()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) destroy() ! {
|
||||
switch(self.name)
|
||||
self.stop() or {}
|
||||
destroy()!
|
||||
}
|
||||
|
||||
// switch instance to be used for daguserver
|
||||
pub fn switch(name string) {
|
||||
daguserver_default = name
|
||||
}
|
||||
60
lib/installers/sysadmintools/daguserver/daguserver_model.v
Normal file
60
lib/installers/sysadmintools/daguserver/daguserver_model.v
Normal file
@@ -0,0 +1,60 @@
|
||||
module daguserver
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
import os
|
||||
|
||||
pub const version = '1.14.3'
|
||||
const singleton = true
|
||||
const default = true
|
||||
|
||||
pub fn heroscript_default() !string {
|
||||
heroscript := "
|
||||
!!daguserver.configure
|
||||
name:'daguserver'
|
||||
title: 'My Hero DAG'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
"
|
||||
|
||||
return heroscript
|
||||
}
|
||||
|
||||
pub struct DaguInstaller {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
|
||||
dagsdir string
|
||||
configpath string
|
||||
username string
|
||||
password string @[secret]
|
||||
secret string @[secret]
|
||||
title string
|
||||
host string
|
||||
port int
|
||||
}
|
||||
|
||||
fn cfg_play(p paramsparser.Params) !DaguInstaller {
|
||||
// THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
|
||||
mut mycfg := DaguInstaller{
|
||||
name: p.get_default('name', 'default')!
|
||||
dagsdir: p.get_default('homedir', '${os.home_dir()}/hero/var/daguserver')!
|
||||
configpath: p.get_default('configpath', '${os.home_dir()}/hero/cfg/dagu')!
|
||||
username: p.get_default('username', 'admin')!
|
||||
password: p.get_default('password', 'secretpassword')!
|
||||
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 daguserver')
|
||||
}
|
||||
return mycfg
|
||||
}
|
||||
|
||||
fn obj_init(obj_ DaguInstaller) !DaguInstaller {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
48
lib/installers/sysadmintools/daguserver/model_comms.v
Normal file
48
lib/installers/sysadmintools/daguserver/model_comms.v
Normal file
@@ -0,0 +1,48 @@
|
||||
module daguserver
|
||||
|
||||
import os
|
||||
|
||||
@[params]
|
||||
pub struct DaguCommunicationConfig {
|
||||
pub:
|
||||
log_dir string // directory path to save logs from standard output
|
||||
history_retention_days int // history retention days (default: 30)
|
||||
mail_on MailOn // Email notification settings
|
||||
smtp SMTP // SMTP server settings
|
||||
error_mail Mail // Error mail configuration
|
||||
info_mail Mail // Info mail configuration
|
||||
}
|
||||
|
||||
pub struct SMTP {
|
||||
pub:
|
||||
host string
|
||||
port string
|
||||
username string
|
||||
password string
|
||||
error_mail Mail
|
||||
}
|
||||
|
||||
pub struct Mail {
|
||||
pub:
|
||||
from string
|
||||
to string
|
||||
prefix string
|
||||
}
|
||||
|
||||
pub struct MailOn {
|
||||
pub:
|
||||
failure bool
|
||||
success bool
|
||||
}
|
||||
|
||||
pub fn (mut self DaguInstaller) comms_configure(config DaguCommunicationConfig) ! {
|
||||
// mut homedir := self.config()!.homedir
|
||||
|
||||
// config_yaml := $tmpl('./templates/communication.yaml')
|
||||
// os.write_file('${homedir}/communication.yaml', config_yaml)!
|
||||
|
||||
// dags_dir := '${homedir}/dags'
|
||||
// if !os.exists(dags_dir) {
|
||||
// os.mkdir(dags_dir)!
|
||||
// }
|
||||
}
|
||||
36
lib/installers/sysadmintools/daguserver/readme.md
Normal file
36
lib/installers/sysadmintools/daguserver/readme.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# daguserver
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.installers.something. daguserver
|
||||
|
||||
mut installer:= daguserver.get()!
|
||||
|
||||
installer.start()!
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
|
||||
```hero
|
||||
!!daguserver.install
|
||||
homedir: '/home/user/daguserver'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
title: 'Some Title'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# directory path to save logs from standard output
|
||||
logDir: @{config.log_dir}
|
||||
|
||||
# history retention days (default: 30)
|
||||
histRetentionDays: @{config.history_retention_days}
|
||||
|
||||
# Email notification settings
|
||||
mailOn:
|
||||
failure: @{config.mail_on.failure}
|
||||
success: @{config.mail_on.success}
|
||||
|
||||
# SMTP server settings
|
||||
smtp:
|
||||
host: @{config.smtp.host}
|
||||
port: @{config.smtp.port}
|
||||
username: @{config.smtp.username}
|
||||
password: @{config.smtp.password}
|
||||
|
||||
# Error mail configuration
|
||||
errorMail:
|
||||
from: @{config.error_mail.from}
|
||||
to: @{config.error_mail.to}
|
||||
prefix: @{config.error_mail.prefix}
|
||||
|
||||
# Info mail configuration
|
||||
infoMail:
|
||||
from: @{config.info_mail.from}
|
||||
to: @{config.info_mail.to}
|
||||
prefix: @{config.info_mail.prefix}
|
||||
27
lib/installers/sysadmintools/daguserver/templates/dagu.yaml
Normal file
27
lib/installers/sysadmintools/daguserver/templates/dagu.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
host: "${cfg.host}" # default: 127.0.0.1
|
||||
port: ${cfg.port}
|
||||
|
||||
# path to the DAGs directory
|
||||
dags: ${cfg.dagsdir}
|
||||
|
||||
# Web UI Color & Title
|
||||
# navbarColor: <ui header color> # header color for web UI (e.g. "#ff0000")
|
||||
navbarTitle: ${cfg.title} # header title for web UI (e.g. "PROD")
|
||||
|
||||
isBasicAuth: true
|
||||
basicAuthUsername: ${cfg.username}
|
||||
basicAuthPassword: ${cfg.password}
|
||||
|
||||
isAuthToken: true # enables API token
|
||||
authToken: ${cfg.secret}
|
||||
|
||||
# Base Config
|
||||
# baseConfig:
|
||||
|
||||
# Working Directory
|
||||
# workDir: # default: DAG location
|
||||
|
||||
# SSL Configuration
|
||||
# tls:
|
||||
# certFile: <path to SSL certificate file>
|
||||
# keyFile: <path to SSL key file>
|
||||
@@ -5,7 +5,7 @@ import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
|
||||
pub fn installlll(args_ InstallArgs) ! {
|
||||
pub fn installl(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
version := '2.0.6'
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
!!hero_code.generate_installer
|
||||
name: "garage_s3"
|
||||
classname: "GarageS3"
|
||||
hasconfig: false
|
||||
singleton: true
|
||||
default: true
|
||||
title: ""
|
||||
templates: false
|
||||
build: true
|
||||
startupmanager: true
|
||||
|
||||
!!hero_code.generate_installer
|
||||
name:'garage_s3'
|
||||
classname:'GarageS3'
|
||||
singleton:0
|
||||
templates:1
|
||||
default:1
|
||||
title:''
|
||||
supported_platforms:''
|
||||
reset:0
|
||||
startupmanager:1
|
||||
hasconfig:1
|
||||
build:0
|
||||
@@ -0,0 +1,56 @@
|
||||
// module garage_s3
|
||||
|
||||
// import freeflowuniverse.herolib.osal
|
||||
// import freeflowuniverse.herolib.core
|
||||
// import freeflowuniverse.herolib.ui.console
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
// import os
|
||||
|
||||
// pub fn install(args_ GarageS3) ! {
|
||||
// mut args := args_
|
||||
// version := '1.0.0'
|
||||
|
||||
// res := os.execute('garage --version')
|
||||
// if res.exit_code == 0 {
|
||||
// r := res.output.split(' ')
|
||||
// if r.len < 2 {
|
||||
// return error("couldn't parse garage version, expected 'garage v*'.\n${res.output}")
|
||||
// }
|
||||
|
||||
// v := r[1]
|
||||
// if texttools.version(v) < texttools.version(version) {
|
||||
// args.reset = true
|
||||
// }
|
||||
// } else {
|
||||
// args.reset = true
|
||||
// }
|
||||
|
||||
// if args.reset {
|
||||
// console.print_header('install garage')
|
||||
|
||||
// mut url := ''
|
||||
// if core.is_linux_arm()! {
|
||||
// url = 'https://garagehq.deuxfleurs.fr/_releases/v${version}/aarch64-unknown-linux-musl/garage'
|
||||
// } else if core.is_linux_intel()! {
|
||||
// url = 'https://garagehq.deuxfleurs.fr/_releases/v${version}/x86_64-unknown-linux-musl/garage'
|
||||
// } else {
|
||||
// return error('unsported platform')
|
||||
// }
|
||||
|
||||
// mut dest := osal.download(
|
||||
// url: url
|
||||
// minsize_kb: 15 * 1024
|
||||
// dest: '/tmp/garage'
|
||||
// reset: true
|
||||
// )!
|
||||
// console.print_debug('download garage done')
|
||||
// osal.cmd_add(
|
||||
// cmdname: 'garage'
|
||||
// source: '${dest.path}'
|
||||
// )!
|
||||
// }
|
||||
|
||||
// if args.start {
|
||||
// start(args)!
|
||||
// }
|
||||
// }
|
||||
@@ -1,121 +1,121 @@
|
||||
module garage_s3
|
||||
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.crypt.secrets
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
// import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
import time
|
||||
// import freeflowuniverse.herolib.ui.console
|
||||
// import freeflowuniverse.herolib.core.pathlib
|
||||
// import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
// import freeflowuniverse.herolib.crypt.secrets
|
||||
// // import freeflowuniverse.herolib.core.texttools
|
||||
// // import freeflowuniverse.herolib.core.httpconnection
|
||||
// import os
|
||||
// import time
|
||||
|
||||
@[params]
|
||||
pub struct S3Config {
|
||||
pub mut:
|
||||
replication_mode string = '3'
|
||||
metadata_dir string = '/var/garage/meta'
|
||||
data_dir string = '/var/garage/data'
|
||||
sled_cache_capacity u32 = 128 // in MB
|
||||
compression_level u8 = 1
|
||||
// @[params]
|
||||
// pub struct S3Config {
|
||||
// pub mut:
|
||||
// replication_mode string = '3'
|
||||
// metadata_dir string = '/var/garage/meta'
|
||||
// data_dir string = '/var/garage/data'
|
||||
// sled_cache_capacity u32 = 128 // in MB
|
||||
// compression_level u8 = 1
|
||||
|
||||
rpc_secret string //{GARAGE_RPCSECRET}
|
||||
rpc_bind_addr string = '[::]:3901'
|
||||
rpc_bind_outgoing bool
|
||||
rpc_public_addr string = '127.0.0.1:3901'
|
||||
// rpc_secret string //{GARAGE_RPCSECRET}
|
||||
// rpc_bind_addr string = '[::]:3901'
|
||||
// rpc_bind_outgoing bool
|
||||
// rpc_public_addr string = '127.0.0.1:3901'
|
||||
|
||||
bootstrap_peers []string
|
||||
// bootstrap_peers []string
|
||||
|
||||
api_bind_addr string = '[::]:3900'
|
||||
s3_region string = 'garage'
|
||||
root_domain string = '.s3.garage'
|
||||
// api_bind_addr string = '[::]:3900'
|
||||
// s3_region string = 'garage'
|
||||
// root_domain string = '.s3.garage'
|
||||
|
||||
web_bind_addr string = '[::]:3902'
|
||||
web_root_domain string = '.web.garage'
|
||||
// web_bind_addr string = '[::]:3902'
|
||||
// web_root_domain string = '.web.garage'
|
||||
|
||||
admin_api_bind_addr string = '[::]:3903'
|
||||
admin_metrics_token string //{GARAGE_METRICSTOKEN}
|
||||
admin_token string //{GARAGE_ADMINTOKEN}
|
||||
admin_trace_sink string = 'http://localhost:4317'
|
||||
// admin_api_bind_addr string = '[::]:3903'
|
||||
// admin_metrics_token string //{GARAGE_METRICSTOKEN}
|
||||
// admin_token string //{GARAGE_ADMINTOKEN}
|
||||
// admin_trace_sink string = 'http://localhost:4317'
|
||||
|
||||
reset bool
|
||||
config_reset bool
|
||||
start bool = true
|
||||
restart bool = true
|
||||
}
|
||||
// reset bool
|
||||
// config_reset bool
|
||||
// start bool = true
|
||||
// restart bool = true
|
||||
// }
|
||||
|
||||
pub fn configure(args_ S3Config) !S3Config {
|
||||
mut args := args_
|
||||
// pub fn configure(args_ S3Config) !S3Config {
|
||||
// mut args := args_
|
||||
|
||||
if args.rpc_secret == '' {
|
||||
args.rpc_secret = secrets.openssl_hex_secret()!
|
||||
println('export GARAGE_RPCSECRET=${args.rpc_secret}')
|
||||
}
|
||||
// if args.rpc_secret == '' {
|
||||
// args.rpc_secret = secrets.openssl_hex_secret()!
|
||||
// println('export GARAGE_RPCSECRET=${args.rpc_secret}')
|
||||
// }
|
||||
|
||||
if args.admin_metrics_token == '' {
|
||||
args.admin_metrics_token = secrets.openssl_base64_secret()!
|
||||
println('export GARAGE_METRICSTOKEN=${args.admin_metrics_token}')
|
||||
}
|
||||
// if args.admin_metrics_token == '' {
|
||||
// args.admin_metrics_token = secrets.openssl_base64_secret()!
|
||||
// println('export GARAGE_METRICSTOKEN=${args.admin_metrics_token}')
|
||||
// }
|
||||
|
||||
if args.admin_token == '' {
|
||||
args.admin_token = secrets.openssl_base64_secret()!
|
||||
println('export GARAGE_ADMINTOKEN=${args.admin_token}')
|
||||
}
|
||||
// if args.admin_token == '' {
|
||||
// args.admin_token = secrets.openssl_base64_secret()!
|
||||
// println('export GARAGE_ADMINTOKEN=${args.admin_token}')
|
||||
// }
|
||||
|
||||
mut config_file := $tmpl('templates/garage.toml')
|
||||
// mut config_file := $tmpl('templates/garage.toml')
|
||||
|
||||
myconfigpath_ := '/etc/garage.toml'
|
||||
mut myconfigpath := pathlib.get_file(path: myconfigpath_, create: true)!
|
||||
myconfigpath.write(config_file)!
|
||||
// myconfigpath_ := '/etc/garage.toml'
|
||||
// mut myconfigpath := pathlib.get_file(path: myconfigpath_, create: true)!
|
||||
// myconfigpath.write(config_file)!
|
||||
|
||||
console.print_header('garage start')
|
||||
// console.print_header('garage start')
|
||||
|
||||
return args
|
||||
}
|
||||
// return args
|
||||
// }
|
||||
|
||||
pub fn start(args_ S3Config) !S3Config {
|
||||
mut args := args_
|
||||
// pub fn start(args_ S3Config) !S3Config {
|
||||
// mut args := args_
|
||||
|
||||
myconfigpath_ := '/etc/garage.toml'
|
||||
// myconfigpath_ := '/etc/garage.toml'
|
||||
|
||||
if args.config_reset || !os.exists(myconfigpath_) {
|
||||
args = configure(args)!
|
||||
}
|
||||
// if args.config_reset || !os.exists(myconfigpath_) {
|
||||
// args = configure(args)!
|
||||
// }
|
||||
|
||||
if args.restart {
|
||||
stop()!
|
||||
}
|
||||
// if args.restart {
|
||||
// stop()!
|
||||
// }
|
||||
|
||||
mut sm := startupmanager.get()!
|
||||
// mut sm := startupmanager.get()!
|
||||
|
||||
sm.new(
|
||||
name: 'garage'
|
||||
cmd: 'garage -c ${myconfigpath_} server'
|
||||
start: true
|
||||
)!
|
||||
// sm.new(
|
||||
// name: 'garage'
|
||||
// cmd: 'garage -c ${myconfigpath_} server'
|
||||
// start: true
|
||||
// )!
|
||||
|
||||
console.print_debug('garage -c ${myconfigpath_} server')
|
||||
// console.print_debug('garage -c ${myconfigpath_} server')
|
||||
|
||||
for _ in 0 .. 50 {
|
||||
if check(args)! {
|
||||
return args
|
||||
}
|
||||
time.sleep(100 * time.millisecond)
|
||||
}
|
||||
// for _ in 0 .. 50 {
|
||||
// if check(args)! {
|
||||
// return args
|
||||
// }
|
||||
// time.sleep(100 * time.millisecond)
|
||||
// }
|
||||
|
||||
return error('garage server did not start properly.')
|
||||
}
|
||||
// return error('garage server did not start properly.')
|
||||
// }
|
||||
|
||||
pub fn stop() ! {
|
||||
console.print_header('garage stop')
|
||||
mut sm := startupmanager.get()!
|
||||
sm.stop('garage')!
|
||||
}
|
||||
// pub fn stop() ! {
|
||||
// console.print_header('garage stop')
|
||||
// mut sm := startupmanager.get()!
|
||||
// sm.stop('garage')!
|
||||
// }
|
||||
|
||||
fn check(args S3Config) !bool {
|
||||
_ := 'garage status'
|
||||
res := os.execute('garage status')
|
||||
if res.exit_code == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// fn check(args S3Config) !bool {
|
||||
// _ := 'garage status'
|
||||
// res := os.execute('garage status')
|
||||
// if res.exit_code == 0 {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
|
||||
@@ -3,26 +3,73 @@ module garage_s3
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.osal.systemd
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.installers.ulist
|
||||
import freeflowuniverse.herolib.installers.lang.golang
|
||||
import freeflowuniverse.herolib.installers.lang.rust
|
||||
import freeflowuniverse.herolib.installers.lang.python
|
||||
// import freeflowuniverse.herolib.osal.systemd
|
||||
import os
|
||||
|
||||
fn startupcmd() ![]zinit.ZProcessNewArgs {
|
||||
// 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()!} garage_s3 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 garage_s3 version.\n${res.output}")
|
||||
}
|
||||
|
||||
if texttools.version(version) > texttools.version(r[0]) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fn install() ! {
|
||||
console.print_header('install garage_s3')
|
||||
mut installer := get()!
|
||||
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
|
||||
mut url := ''
|
||||
if core.is_linux_arm()! {
|
||||
url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_linux_arm64.tar.gz'
|
||||
} else if core.is_linux_intel()! {
|
||||
url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_linux_amd64.tar.gz'
|
||||
} else if core.is_osx_arm()! {
|
||||
url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_darwin_arm64.tar.gz'
|
||||
} else if core.is_osx_intel()! {
|
||||
url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_darwin_amd64.tar.gz'
|
||||
} else {
|
||||
return error('unsported platform')
|
||||
}
|
||||
|
||||
mut dest := osal.download(
|
||||
url: url
|
||||
minsize_kb: 9000
|
||||
expand_dir: '/tmp/garage_s3'
|
||||
)!
|
||||
|
||||
// dest.moveup_single_subdir()!
|
||||
|
||||
mut binpath := dest.file_get('garage_s3')!
|
||||
osal.cmd_add(
|
||||
cmdname: 'garage_s3'
|
||||
source: binpath.path
|
||||
)!
|
||||
}
|
||||
|
||||
fn startupcmd() ![]zinit.ZProcessNewArgs {
|
||||
mut res := []zinit.ZProcessNewArgs{}
|
||||
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
|
||||
// res << zinit.ZProcessNewArgs{
|
||||
// name: 'garage_s3'
|
||||
// cmd: 'garage_s3 server'
|
||||
// env: {
|
||||
// 'HOME': '/root'
|
||||
// }
|
||||
// }
|
||||
res << zinit.ZProcessNewArgs{
|
||||
name: 'garage_s3'
|
||||
cmd: 'garage_s3 server'
|
||||
env: {
|
||||
'HOME': '/root'
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
@@ -61,99 +108,6 @@ fn stop_pre() ! {
|
||||
fn stop_post() ! {
|
||||
}
|
||||
|
||||
//////////////////// following actions are not specific to instance of the object
|
||||
|
||||
// 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()!} garage_s3 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 garage_s3 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: 'garage_s3'
|
||||
// source: '${gitpath}/target/x86_64-unknown-linux-musl/release/garage_s3'
|
||||
// )!
|
||||
}
|
||||
|
||||
fn install_() ! {
|
||||
console.print_header('install garage_s3')
|
||||
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
|
||||
// mut url := ''
|
||||
// if core.is_linux_arm()! {
|
||||
// url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_linux_arm64.tar.gz'
|
||||
// } else if core.is_linux_intel()! {
|
||||
// url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_linux_amd64.tar.gz'
|
||||
// } else if core.is_osx_arm()! {
|
||||
// url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_darwin_arm64.tar.gz'
|
||||
// } else if core.is_osx_intel()! {
|
||||
// url = 'https://github.com/garage_s3-dev/garage_s3/releases/download/v${version}/garage_s3_${version}_darwin_amd64.tar.gz'
|
||||
// } else {
|
||||
// return error('unsported platform')
|
||||
// }
|
||||
|
||||
// mut dest := osal.download(
|
||||
// url: url
|
||||
// minsize_kb: 9000
|
||||
// expand_dir: '/tmp/garage_s3'
|
||||
// )!
|
||||
|
||||
// //dest.moveup_single_subdir()!
|
||||
|
||||
// mut binpath := dest.file_get('garage_s3')!
|
||||
// osal.cmd_add(
|
||||
// cmdname: 'garage_s3'
|
||||
// source: binpath.path
|
||||
// )!
|
||||
}
|
||||
|
||||
fn build_() ! {
|
||||
// url := 'https://github.com/threefoldtech/garage_s3'
|
||||
|
||||
// make sure we install base on the node
|
||||
// if core.platform()!= .ubuntu {
|
||||
// return error('only support ubuntu for now')
|
||||
// }
|
||||
// golang.install()!
|
||||
|
||||
// console.print_header('build garage_s3')
|
||||
|
||||
// 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
|
||||
// )!
|
||||
}
|
||||
|
||||
fn destroy_() ! {
|
||||
// mut systemdfactory := systemd.new()!
|
||||
// systemdfactory.destroy("zinit")!
|
||||
|
||||
@@ -2,9 +2,9 @@ module garage_s3
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
__global (
|
||||
@@ -14,6 +14,96 @@ __global (
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = garage_s3_default
|
||||
}
|
||||
if args.name == '' {
|
||||
args.name = 'default'
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&GarageS3 {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in garage_s3_global {
|
||||
if !config_exists() {
|
||||
if default {
|
||||
config_save()!
|
||||
}
|
||||
}
|
||||
config_load()!
|
||||
}
|
||||
return garage_s3_global[args.name] or {
|
||||
println(garage_s3_global)
|
||||
panic('bug in get from factory: ')
|
||||
}
|
||||
}
|
||||
|
||||
fn config_exists(args_ ArgsGet) bool {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context() or { panic('bug') }
|
||||
return context.hero_config_exists('garage_s3', args.name)
|
||||
}
|
||||
|
||||
fn config_load(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
mut heroscript := context.hero_config_get('garage_s3', args.name)!
|
||||
play(heroscript: heroscript)!
|
||||
}
|
||||
|
||||
fn config_save(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_set('garage_s3', args.name, heroscript_default()!)!
|
||||
}
|
||||
|
||||
fn set(o GarageS3) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
garage_s3_global['default'] = &o2
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
|
||||
start bool
|
||||
stop bool
|
||||
restart bool
|
||||
delete bool
|
||||
configure bool // make sure there is at least one installed
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
if args.heroscript == '' {
|
||||
args.heroscript = heroscript_default()!
|
||||
}
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut install_actions := plbook.find(filter: 'garage_s3.configure')!
|
||||
if install_actions.len > 0 {
|
||||
for install_action in install_actions {
|
||||
mut p := install_action.params
|
||||
mycfg := cfg_play(p)!
|
||||
set(mycfg)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -40,6 +130,12 @@ fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManag
|
||||
}
|
||||
}
|
||||
|
||||
// load from disk and make sure is properly intialized
|
||||
pub fn (mut self GarageS3) reload() ! {
|
||||
switch(self.name)
|
||||
self = obj_init(self)!
|
||||
}
|
||||
|
||||
pub fn (mut self GarageS3) start() ! {
|
||||
switch(self.name)
|
||||
if self.running()! {
|
||||
@@ -48,8 +144,8 @@ pub fn (mut self GarageS3) start() ! {
|
||||
|
||||
console.print_header('garage_s3 start')
|
||||
|
||||
if !installed_()! {
|
||||
install_()!
|
||||
if !installed()! {
|
||||
install()!
|
||||
}
|
||||
|
||||
configure()!
|
||||
@@ -77,9 +173,9 @@ pub fn (mut self GarageS3) start() ! {
|
||||
return error('garage_s3 did not install properly.')
|
||||
}
|
||||
|
||||
pub fn (mut self GarageS3) install_start(model InstallArgs) ! {
|
||||
pub fn (mut self GarageS3) install_start(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
self.install(model)!
|
||||
self.install(args)!
|
||||
self.start()!
|
||||
}
|
||||
|
||||
@@ -110,7 +206,7 @@ pub fn (mut self GarageS3) running() !bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return running()!
|
||||
return running_()!
|
||||
}
|
||||
|
||||
@[params]
|
||||
@@ -119,19 +215,21 @@ pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn install(args InstallArgs) ! {
|
||||
if args.reset {
|
||||
destroy()!
|
||||
}
|
||||
if !(installed_()!) {
|
||||
install_()!
|
||||
pub fn (mut self GarageS3) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset || (!installed()!) {
|
||||
install()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy() ! {
|
||||
pub fn (mut self GarageS3) destroy() ! {
|
||||
switch(self.name)
|
||||
|
||||
self.stop() or {}
|
||||
destroy_()!
|
||||
}
|
||||
|
||||
pub fn build() ! {
|
||||
build_()!
|
||||
// switch instance to be used for garage_s3
|
||||
pub fn switch(name string) {
|
||||
garage_s3_default = name
|
||||
}
|
||||
|
||||
@@ -3,25 +3,109 @@ module garage_s3
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
import os
|
||||
|
||||
pub const version = '0.0.0'
|
||||
const singleton = true
|
||||
pub const version = '1.14.3'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
|
||||
pub fn heroscript_default() !string {
|
||||
heroscript := "
|
||||
!!garage_s3.configure
|
||||
name:'garage_s3'
|
||||
homedir: '{HOME}/hero/var/garage_s3'
|
||||
configpath: '{HOME}/.config/garage_s3/admin.yaml'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
secret: ''
|
||||
title: 'My Hero DAG'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
"
|
||||
|
||||
return heroscript
|
||||
}
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
@[heap]
|
||||
|
||||
pub struct GarageS3 {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
|
||||
replication_mode string = '3'
|
||||
metadata_dir string = '/var/garage/meta'
|
||||
data_dir string = '/var/garage/data'
|
||||
sled_cache_capacity u32 = 128 // in MB
|
||||
compression_level u8 = 1
|
||||
|
||||
rpc_secret string //{GARAGE_RPCSECRET}
|
||||
rpc_bind_addr string = '[::]:3901'
|
||||
rpc_bind_outgoing bool
|
||||
rpc_public_addr string = '127.0.0.1:3901'
|
||||
|
||||
bootstrap_peers []string
|
||||
|
||||
api_bind_addr string = '[::]:3900'
|
||||
s3_region string = 'garage'
|
||||
root_domain string = '.s3.garage'
|
||||
|
||||
web_bind_addr string = '[::]:3902'
|
||||
web_root_domain string = '.web.garage'
|
||||
|
||||
admin_api_bind_addr string = '[::]:3903'
|
||||
admin_metrics_token string //{GARAGE_METRICSTOKEN}
|
||||
admin_token string //{GARAGE_ADMINTOKEN}
|
||||
admin_trace_sink string = 'http://localhost:4317'
|
||||
|
||||
reset bool
|
||||
config_reset bool
|
||||
start bool = true
|
||||
restart bool = true
|
||||
}
|
||||
|
||||
fn cfg_play(p paramsparser.Params) !GarageS3 {
|
||||
mut mycfg := GarageS3{
|
||||
name: p.get_default('name', 'default')!
|
||||
replication_mode: p.get_default('replication_mode', '3')!
|
||||
metadata_dir: p.get_default('metadata_dir', '/var/garage/meta')!
|
||||
data_dir: p.get_default('data_dir', '/var/garage/data')!
|
||||
sled_cache_capacity: p.get_u32_default('sled_cache_capacity', 128)!
|
||||
compression_level: p.get_u8_default('compression_level', 1)!
|
||||
rpc_secret: p.get_default('rpc_secret', '')!
|
||||
rpc_bind_addr: p.get_default('rpc_bind_addr', '[::]:3901')!
|
||||
rpc_public_addr: p.get_default('rpc_public_addr', '127.0.0.1:3901')!
|
||||
api_bind_addr: p.get_default('api_bind_addr', '[::]:3900')!
|
||||
s3_region: p.get_default('s3_region', 'garage')!
|
||||
root_domain: p.get_default('root_domain', '.s3.garage')!
|
||||
web_bind_addr: p.get_default('web_bind_addr', '[::]:3902')!
|
||||
web_root_domain: p.get_default('web_root_domain', '.web.garage')!
|
||||
admin_api_bind_addr: p.get_default('admin_api_bind_addr', '[::]:3903')!
|
||||
admin_metrics_token: p.get_default('admin_metrics_token', '')!
|
||||
admin_token: p.get_default('admin_token', '')!
|
||||
admin_trace_sink: p.get_default('admin_trace_sink', 'http://localhost:4317')!
|
||||
bootstrap_peers: p.get_list_default('bootstrap_peers', [])!
|
||||
rpc_bind_outgoing: p.get_default_false('rpc_bind_outgoing')
|
||||
reset: p.get_default_false('reset')
|
||||
config_reset: p.get_default_false('config_reset')
|
||||
start: p.get_default_true('start')
|
||||
restart: p.get_default_true('restart')
|
||||
}
|
||||
|
||||
return mycfg
|
||||
}
|
||||
|
||||
fn obj_init(obj_ GarageS3) !GarageS3 {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
panic('implement')
|
||||
return obj
|
||||
}
|
||||
|
||||
// called before start if done
|
||||
fn configure() ! {
|
||||
// mut installer := get()!
|
||||
|
||||
// mut mycode := $tmpl('templates/atemplate.yaml')
|
||||
// mut path := pathlib.get_file(path: cfg.configpath, create: true)!
|
||||
// path.write(mycode)!
|
||||
// console.print_debug(mycode)
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
module garage_s3
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
|
||||
pub fn installll(args_ S3Config) ! {
|
||||
mut args := args_
|
||||
version := '1.0.0'
|
||||
|
||||
res := os.execute('garage --version')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split(' ')
|
||||
if r.len < 2 {
|
||||
return error("couldn't parse garage version, expected 'garage v*'.\n${res.output}")
|
||||
}
|
||||
|
||||
v := r[1]
|
||||
if texttools.version(v) < texttools.version(version) {
|
||||
args.reset = true
|
||||
}
|
||||
} else {
|
||||
args.reset = true
|
||||
}
|
||||
|
||||
if args.reset {
|
||||
console.print_header('install garage')
|
||||
|
||||
mut url := ''
|
||||
if core.is_linux_arm()! {
|
||||
url = 'https://garagehq.deuxfleurs.fr/_releases/v${version}/aarch64-unknown-linux-musl/garage'
|
||||
} else if core.is_linux_intel()! {
|
||||
url = 'https://garagehq.deuxfleurs.fr/_releases/v${version}/x86_64-unknown-linux-musl/garage'
|
||||
} else {
|
||||
return error('unsported platform')
|
||||
}
|
||||
|
||||
mut dest := osal.download(
|
||||
url: url
|
||||
minsize_kb: 15 * 1024
|
||||
dest: '/tmp/garage'
|
||||
reset: true
|
||||
)!
|
||||
console.print_debug('download garage done')
|
||||
osal.cmd_add(
|
||||
cmdname: 'garage'
|
||||
source: '${dest.path}'
|
||||
)!
|
||||
}
|
||||
|
||||
if args.start {
|
||||
start(args)!
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,36 @@
|
||||
|
||||
## garage S3 server
|
||||
|
||||
see [https://garagehq.deuxfleurs.fr](https://garagehq.deuxfleurs.fr)
|
||||
# garage_s3
|
||||
|
||||
|
||||
https://garagehq.deuxfleurs.fr/documentation/quick-start/
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.installers.something. garage_s3
|
||||
|
||||
mut installer:= garage_s3.get()!
|
||||
|
||||
installer.start()!
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
|
||||
```hero
|
||||
!!garage_s3.install
|
||||
homedir: '/home/user/garage_s3'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
title: 'Some Title'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
name: ${cfg.configpath}
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
replication_mode = "${args.replication_mode}"
|
||||
|
||||
metadata_dir = "${args.metadata_dir}"
|
||||
data_dir = "${args.data_dir}"
|
||||
metadata_fsync = false
|
||||
data_fsync = false
|
||||
|
||||
db_engine = "sqlite"
|
||||
|
||||
block_size = "1M"
|
||||
|
||||
sled_cache_capacity = "${args.sled_cache_capacity}MiB"
|
||||
sled_flush_every_ms = 2000
|
||||
lmdb_map_size = "1T"
|
||||
|
||||
compression_level = ${args.compression_level}
|
||||
|
||||
rpc_secret = "${args.rpc_secret}"
|
||||
rpc_bind_addr = "${args.rpc_bind_addr}"
|
||||
rpc_bind_outgoing = ${args.rpc_bind_outgoing}
|
||||
rpc_public_addr = "${args.rpc_public_addr}"
|
||||
|
||||
bootstrap_peers = ${args.bootstrap_peers}
|
||||
|
||||
|
||||
# [consul_discovery]
|
||||
# api = "catalog"
|
||||
# consul_http_addr = "http://127.0.0.1:8500"
|
||||
# service_name = "garage-daemon"
|
||||
# ca_cert = "/etc/consul/consul-ca.crt"
|
||||
# client_cert = "/etc/consul/consul-client.crt"
|
||||
# client_key = "/etc/consul/consul-key.crt"
|
||||
# # for `agent` API mode, unset client_cert and client_key, and optionally enable `token`
|
||||
# # token = "abcdef-01234-56789"
|
||||
# tls_skip_verify = false
|
||||
# tags = [ "dns-enabled" ]
|
||||
# meta = { dns-acl = "allow trusted" }
|
||||
|
||||
|
||||
# [kubernetes_discovery]
|
||||
# namespace = "garage"
|
||||
# service_name = "garage-daemon"
|
||||
# skip_crd = false
|
||||
|
||||
|
||||
[s3_api]
|
||||
api_bind_addr = "${args.api_bind_addr}"
|
||||
s3_region = "${args.s3_region}"
|
||||
root_domain = "${args.root_domain}"
|
||||
|
||||
[s3_web]
|
||||
bind_addr = "${args.web_bind_addr}"
|
||||
root_domain = "${args.web_root_domain}"
|
||||
|
||||
[admin]
|
||||
api_bind_addr = "${args.admin_api_bind_addr}"
|
||||
metrics_token = "${args.admin_metrics_token}"
|
||||
admin_token = "${args.admin_token}"
|
||||
trace_sink = "${args.admin_trace_sink}"
|
||||
@@ -9,7 +9,7 @@ import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import os
|
||||
import time
|
||||
|
||||
pub fn installll(args_ InstallArgs) ! {
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
version := '11.1.4'
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module rclone
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.httpconnection
|
||||
import os
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
|
||||
@@ -2,10 +2,9 @@ module rclone
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.data.encoderhero
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
__global (
|
||||
@@ -18,108 +17,86 @@ __global (
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut model := args_
|
||||
if model.name == '' {
|
||||
model.name = rclone_default
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = rclone_default
|
||||
}
|
||||
if model.name == '' {
|
||||
model.name = 'default'
|
||||
if args.name == '' {
|
||||
args.name = 'default'
|
||||
}
|
||||
return model
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&RClone {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in rclone_global {
|
||||
if args.name == 'default' {
|
||||
if !config_exists(args) {
|
||||
if default {
|
||||
mut context := base.context() or { panic('bug') }
|
||||
context.hero_config_set('rclone', model.name, heroscript_default()!)!
|
||||
}
|
||||
if !config_exists() {
|
||||
if default {
|
||||
config_save()!
|
||||
}
|
||||
load(args)!
|
||||
}
|
||||
config_load()!
|
||||
}
|
||||
return rclone_global[args.name] or {
|
||||
println(rclone_global)
|
||||
panic('could not get config for ${args.name} with name:${model.name}')
|
||||
panic('bug in get from factory: ')
|
||||
}
|
||||
}
|
||||
|
||||
// set the model in mem and the config on the filesystem
|
||||
pub fn set(o RClone) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
rclone_global[o.name] = &o2
|
||||
rclone_default = o.name
|
||||
}
|
||||
|
||||
// check we find the config on the filesystem
|
||||
pub fn exists(args_ ArgsGet) bool {
|
||||
mut model := args_get(args_)
|
||||
fn config_exists(args_ ArgsGet) bool {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context() or { panic('bug') }
|
||||
return context.hero_config_exists('rclone', model.name)
|
||||
return context.hero_config_exists('rclone', args.name)
|
||||
}
|
||||
|
||||
// load the config error if it doesn't exist
|
||||
pub fn load(args_ ArgsGet) ! {
|
||||
mut model := args_get(args_)
|
||||
fn config_load(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
mut heroscript := context.hero_config_get('rclone', model.name)!
|
||||
mut heroscript := context.hero_config_get('rclone', args.name)!
|
||||
play(heroscript: heroscript)!
|
||||
}
|
||||
|
||||
// save the config to the filesystem in the context
|
||||
pub fn save(o RClone) ! {
|
||||
fn config_save(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
heroscript := encoderhero.encode[RClone](o)!
|
||||
context.hero_config_set('rclone', model.name, heroscript)!
|
||||
context.hero_config_set('rclone', args.name, heroscript_default()!)!
|
||||
}
|
||||
|
||||
fn set(o RClone) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
rclone_global['default'] = &o2
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
|
||||
delete bool
|
||||
configure bool // make sure there is at least one installed
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut model := args_
|
||||
mut args := args_
|
||||
|
||||
if model.heroscript == '' {
|
||||
model.heroscript = heroscript_default()!
|
||||
if args.heroscript == '' {
|
||||
args.heroscript = heroscript_default()!
|
||||
}
|
||||
mut plbook := model.plbook or { playbook.new(text: model.heroscript)! }
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut configure_actions := plbook.find(filter: 'rclone.configure')!
|
||||
if configure_actions.len > 0 {
|
||||
for config_action in configure_actions {
|
||||
mut p := config_action.params
|
||||
mut install_actions := plbook.find(filter: 'rclone.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 rclone.configure\n${mycfg}')
|
||||
set(mycfg)!
|
||||
save(mycfg)!
|
||||
}
|
||||
}
|
||||
|
||||
mut other_actions := plbook.find(filter: 'rclone.')!
|
||||
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 rclone.destroy')
|
||||
destroy_()!
|
||||
}
|
||||
if other_action.name == 'install' {
|
||||
console.print_debug('install action rclone.install')
|
||||
install_()!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,6 +105,28 @@ pub fn play(args_ PlayArgs) ! {
|
||||
//////////////////////////# 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)
|
||||
@@ -140,22 +139,20 @@ pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
// switch instance to be used for rclone
|
||||
pub fn switch(name string) {
|
||||
rclone_default = name
|
||||
}
|
||||
|
||||
pub fn (mut self RClone) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset {
|
||||
destroy_()!
|
||||
}
|
||||
if !(installed_()!) {
|
||||
if args.reset || (!installed_()!) {
|
||||
install_()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self RClone) destroy() ! {
|
||||
switch(self.name)
|
||||
|
||||
destroy_()!
|
||||
}
|
||||
|
||||
// switch instance to be used for rclone
|
||||
pub fn switch(name string) {
|
||||
rclone_default = name
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
|
||||
pub fn installll(args_ InstallArgs) ! {
|
||||
pub fn install(args_ InstallArgs) ! {
|
||||
mut args := args_
|
||||
version := '0.16.2'
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import freeflowuniverse.herolib.osal.screen
|
||||
import os
|
||||
|
||||
// install lighttpd will return true if it was already installed
|
||||
pub fn installll(args InstallArgs) ! {
|
||||
pub fn install(args InstallArgs) ! {
|
||||
// make sure we install base on the node
|
||||
base.install()!
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module tailwind
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import os
|
||||
|
||||
pub const version = '3.4.12'
|
||||
|
||||
@@ -2,9 +2,9 @@ module tailwind
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
__global (
|
||||
@@ -17,65 +17,59 @@ __global (
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut model := args_
|
||||
if model.name == '' {
|
||||
model.name = tailwind_default
|
||||
}
|
||||
if model.name == '' {
|
||||
model.name = 'default'
|
||||
}
|
||||
return model
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&Tailwind {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in tailwind_global {
|
||||
if args.name == 'default' {
|
||||
if !config_exists(args) {
|
||||
if default {
|
||||
mut context := base.context() or { panic('bug') }
|
||||
context.hero_config_set('tailwind', model.name, heroscript_default()!)!
|
||||
}
|
||||
}
|
||||
load(args)!
|
||||
}
|
||||
}
|
||||
return tailwind_global[args.name] or {
|
||||
println(tailwind_global)
|
||||
panic('could not get config for ${args.name} with name:${model.name}')
|
||||
}
|
||||
return &Tailwind{}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# 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:
|
||||
reset bool
|
||||
}
|
||||
|
||||
// switch instance to be used for tailwind
|
||||
pub fn switch(name string) {
|
||||
tailwind_default = name
|
||||
}
|
||||
|
||||
pub fn (mut self Tailwind) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset {
|
||||
destroy_()!
|
||||
}
|
||||
if !(installed_()!) {
|
||||
if args.reset || (!installed_()!) {
|
||||
install_()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Tailwind) destroy() ! {
|
||||
switch(self.name)
|
||||
|
||||
destroy_()!
|
||||
}
|
||||
|
||||
// switch instance to be used for tailwind
|
||||
pub fn switch(name string) {
|
||||
tailwind_default = name
|
||||
}
|
||||
|
||||
33
lib/lang/python/freeze.v
Normal file
33
lib/lang/python/freeze.v
Normal file
@@ -0,0 +1,33 @@
|
||||
module python
|
||||
|
||||
// // remember the requirements list for all pips
|
||||
// pub fn (mut py PythonEnv) freeze(name string) ! {
|
||||
// console.print_debug('Freezing requirements for environment: ${py.name}')
|
||||
// cmd := '
|
||||
// cd ${py.path.path}
|
||||
// source bin/activate
|
||||
// python3 -m pip freeze
|
||||
// '
|
||||
// res := os.execute(cmd)
|
||||
// if res.exit_code > 0 {
|
||||
// console.print_stderr('Failed to freeze requirements: ${res}')
|
||||
// return error('could not execute freeze.\n${res}\n${cmd}')
|
||||
// }
|
||||
// console.print_debug('Successfully froze requirements')
|
||||
// }
|
||||
|
||||
// remember the requirements list for all pips
|
||||
// pub fn (mut py PythonEnv) unfreeze(name string) ! {
|
||||
// // requirements := py.db.get('freeze_${name}')!
|
||||
// mut p := py.path.file_get_new('requirements.txt')!
|
||||
// p.write(requirements)!
|
||||
// cmd := '
|
||||
// cd ${py.path.path}
|
||||
// source bin/activate
|
||||
// python3 -m pip install -r requirements.txt
|
||||
// '
|
||||
// res := os.execute(cmd)
|
||||
// if res.exit_code > 0 {
|
||||
// return error('could not execute unfreeze.\n${res}\n${cmd}')
|
||||
// }
|
||||
// }
|
||||
84
lib/lang/python/pyexec.v
Normal file
84
lib/lang/python/pyexec.v
Normal file
@@ -0,0 +1,84 @@
|
||||
module python
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
// import freeflowuniverse.herolib.data.dbfs
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@[params]
|
||||
pub struct PythonExecArgs {
|
||||
pub mut:
|
||||
cmd string @[required]
|
||||
result_delimiter string = '==RESULT=='
|
||||
ok_delimiter string = '==OK=='
|
||||
python_script_name string // if used will put it in root of the sandbox under that name
|
||||
stdout bool = true
|
||||
}
|
||||
|
||||
pub fn (py PythonEnv) exec(args PythonExecArgs) !string {
|
||||
mut cmd := texttools.dedent(args.cmd)
|
||||
mut debug := false
|
||||
if cmd.contains('DEBUG()') {
|
||||
cmd = cmd.replace('DEBUG()', 'from IPython import embed; embed()')
|
||||
debug = true
|
||||
}
|
||||
|
||||
cmd += "\n\nprint(\"${args.ok_delimiter}\")\n"
|
||||
|
||||
mut scriptpath := ''
|
||||
if args.python_script_name.len > 0 {
|
||||
scriptpath = '${py.path.path}/${args.python_script_name}.py'
|
||||
mut p := pathlib.get_file(path: scriptpath, create: true)!
|
||||
p.write(cmd)!
|
||||
} else {
|
||||
scriptpath = pathlib.temp_write(text: cmd, ext: 'py') or {
|
||||
return error('error: cannot write script to execute: ${err}')
|
||||
}
|
||||
}
|
||||
console.print_debug(' - python script exec: ${scriptpath}')
|
||||
os.chmod(scriptpath, 0o777)!
|
||||
|
||||
cmd2 := '
|
||||
cd ${py.path.path}
|
||||
source bin/activate
|
||||
python3 ${scriptpath}
|
||||
'
|
||||
if args.stdout || debug {
|
||||
console.print_debug(cmd2)
|
||||
}
|
||||
mut job := osal.Job{}
|
||||
if debug {
|
||||
osal.execute_interactive(cmd2)!
|
||||
} else {
|
||||
job = osal.exec(cmd: cmd2, stdout: args.stdout, raise_error: false)!
|
||||
}
|
||||
|
||||
if job.exit_code > 0 {
|
||||
// means error
|
||||
mut msg := ' - error in execution of python script: ${scriptpath}\n'
|
||||
msg += 'ERROR:\n'
|
||||
msg += job.error.str()
|
||||
return error(msg)
|
||||
}
|
||||
|
||||
// console.print_debug(job)
|
||||
|
||||
mut o := []string{}
|
||||
mut start := false
|
||||
for l in job.output.split_into_lines() {
|
||||
if l.trim_space().starts_with(args.result_delimiter) {
|
||||
start = true
|
||||
continue
|
||||
}
|
||||
if l.trim_space().starts_with(args.ok_delimiter) {
|
||||
break
|
||||
}
|
||||
if start {
|
||||
o << l
|
||||
}
|
||||
}
|
||||
|
||||
return o.join_lines()
|
||||
}
|
||||
161
lib/lang/python/python.v
Normal file
161
lib/lang/python/python.v
Normal file
@@ -0,0 +1,161 @@
|
||||
module python
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.installers.lang.python
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.data.dbfs
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import os
|
||||
|
||||
pub struct PythonEnv {
|
||||
pub mut:
|
||||
name string
|
||||
path pathlib.Path
|
||||
db dbfs.DB
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PythonEnvArgs {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn new(args_ PythonEnvArgs) !PythonEnv {
|
||||
console.print_debug('Creating new Python environment with name: ${args_.name}')
|
||||
mut args := args_
|
||||
name := texttools.name_fix(args.name)
|
||||
|
||||
pp := '${os.home_dir()}/hero/python/${name}'
|
||||
console.print_debug('Python environment path: ${pp}')
|
||||
|
||||
mut c := base.context()!
|
||||
mut py := PythonEnv{
|
||||
name: name
|
||||
path: pathlib.get_dir(path: pp, create: true)!
|
||||
db: c.db_get('python_${args.name}')!
|
||||
}
|
||||
|
||||
key_install := 'pips_${py.name}_install'
|
||||
key_update := 'pips_${py.name}_update'
|
||||
if !os.exists('${pp}/bin/activate') {
|
||||
console.print_debug('Python environment directory does not exist, triggering reset')
|
||||
args.reset = true
|
||||
}
|
||||
if args.reset {
|
||||
console.print_debug('Resetting Python environment')
|
||||
py.pips_done_reset()!
|
||||
py.db.delete(key: key_install)!
|
||||
py.db.delete(key: key_update)!
|
||||
}
|
||||
|
||||
toinstall := !py.db.exists(key: key_install)!
|
||||
if toinstall {
|
||||
console.print_debug('Installing Python environment')
|
||||
python.install()!
|
||||
py.init_env()!
|
||||
py.db.set(key: key_install, value: 'done')!
|
||||
console.print_debug('Python environment setup complete')
|
||||
}
|
||||
|
||||
toupdate := !py.db.exists(key: key_update)!
|
||||
if toupdate {
|
||||
console.print_debug('Updating Python environment')
|
||||
py.update()!
|
||||
py.db.set(key: key_update, value: 'done')!
|
||||
console.print_debug('Python environment update complete')
|
||||
}
|
||||
|
||||
return py
|
||||
}
|
||||
|
||||
// comma separated list of packages to install
|
||||
pub fn (py PythonEnv) init_env() ! {
|
||||
console.print_green('Initializing Python virtual environment at: ${py.path.path}')
|
||||
cmd := '
|
||||
cd ${py.path.path}
|
||||
python3 -m venv .
|
||||
'
|
||||
osal.exec(cmd: cmd)!
|
||||
console.print_debug('Virtual environment initialization complete')
|
||||
}
|
||||
|
||||
// comma separated list of packages to install
|
||||
pub fn (py PythonEnv) update() ! {
|
||||
console.print_green('Updating pip in Python environment: ${py.name}')
|
||||
cmd := '
|
||||
cd ${py.path.path}
|
||||
source bin/activate
|
||||
python3 -m pip install --upgrade pip
|
||||
'
|
||||
osal.exec(cmd: cmd)!
|
||||
console.print_debug('Pip update complete')
|
||||
}
|
||||
|
||||
// comma separated list of packages to install
|
||||
pub fn (mut py PythonEnv) pip(packages string) ! {
|
||||
mut to_install := []string{}
|
||||
for i in packages.split(',') {
|
||||
pip := i.trim_space()
|
||||
if !py.pips_done_check(pip)! {
|
||||
to_install << pip
|
||||
console.print_debug('Package to install: ${pip}')
|
||||
}
|
||||
}
|
||||
if to_install.len == 0 {
|
||||
return
|
||||
}
|
||||
console.print_debug('Installing Python packages: ${packages}')
|
||||
packages2 := to_install.join(' ')
|
||||
cmd := '
|
||||
cd ${py.path.path}
|
||||
source bin/activate
|
||||
pip3 install ${packages2} -q
|
||||
'
|
||||
osal.exec(cmd: cmd)!
|
||||
// After successful installation, record the packages as done
|
||||
for pip in to_install {
|
||||
py.pips_done_add(pip)!
|
||||
console.print_debug('Successfully installed package: ${pip}')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut py PythonEnv) pips_done_reset() ! {
|
||||
console.print_debug('Resetting installed packages list for environment: ${py.name}')
|
||||
py.db.delete(key: 'pips_${py.name}')!
|
||||
}
|
||||
|
||||
pub fn (mut py PythonEnv) pips_done() ![]string {
|
||||
// console.print_debug('Getting list of installed packages for environment: ${py.name}')
|
||||
mut res := []string{}
|
||||
pips := py.db.get(key: 'pips_${py.name}') or { '' }
|
||||
for pip_ in pips.split_into_lines() {
|
||||
pip := pip_.trim_space()
|
||||
if pip !in res && pip.len > 0 {
|
||||
res << pip
|
||||
}
|
||||
}
|
||||
// console.print_debug('Found ${res.len} installed packages')
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (mut py PythonEnv) pips_done_add(name string) ! {
|
||||
console.print_debug('Adding package ${name} to installed packages list')
|
||||
mut pips := py.pips_done()!
|
||||
if name in pips {
|
||||
// console.print_debug('Package ${name} already marked as installed')
|
||||
return
|
||||
}
|
||||
pips << name
|
||||
out := pips.join_lines()
|
||||
py.db.set(key: 'pips_${py.name}', value: out)!
|
||||
console.print_debug('Successfully added package ${name} to installed list')
|
||||
}
|
||||
|
||||
pub fn (mut py PythonEnv) pips_done_check(name string) !bool {
|
||||
// console.print_debug('Checking if package ${name} is installed')
|
||||
mut pips := py.pips_done()!
|
||||
return name in pips
|
||||
}
|
||||
7
lib/lang/python/python_test.v
Normal file
7
lib/lang/python/python_test.v
Normal file
@@ -0,0 +1,7 @@
|
||||
module python
|
||||
|
||||
fn test_python() {
|
||||
py := new() or { panic(err) }
|
||||
py.update() or { panic(err) }
|
||||
py.pip('ipython') or { panic(err) }
|
||||
}
|
||||
96
lib/lang/python/readme.md
Normal file
96
lib/lang/python/readme.md
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
## use virtual env
|
||||
|
||||
```v
|
||||
import freeflowuniverse.herolib.lang.python
|
||||
py:=python.new(name:'default')! //a python env with name default
|
||||
py.update()!
|
||||
py.pip("ipython")!
|
||||
|
||||
```
|
||||
|
||||
### to activate an environment and use the installed python
|
||||
|
||||
```bash
|
||||
source ~/hero/python/default/bin/activate
|
||||
```
|
||||
|
||||
|
||||
### how to write python scripts to execute
|
||||
|
||||
```v
|
||||
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.lang.python
|
||||
import json
|
||||
|
||||
|
||||
pub struct Person {
|
||||
name string
|
||||
age int
|
||||
is_member bool
|
||||
skills []string
|
||||
}
|
||||
|
||||
|
||||
mut py:=python.new(name:'test')! //a python env with name test
|
||||
//py.update()!
|
||||
py.pip("ipython")!
|
||||
|
||||
|
||||
nrcount:=5
|
||||
//this is used in the pythonexample
|
||||
cmd:=$tmpl("pythonexample.py")
|
||||
|
||||
mut res:=""
|
||||
for i in 0..5{
|
||||
println(i)
|
||||
res=py.exec(cmd:cmd)!
|
||||
|
||||
}
|
||||
//res:=py.exec(cmd:cmd)!
|
||||
|
||||
person:=json.decode(Person,res)!
|
||||
println(person)
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
example python script which is in the pythonscripts/ dir
|
||||
|
||||
```py
|
||||
|
||||
import json
|
||||
|
||||
for counter in range(1, @nrcount): # Loop from 1 to the specified param
|
||||
print(f"done_{counter}")
|
||||
|
||||
|
||||
# Define a simple Python structure (e.g., a dictionary)
|
||||
example_struct = {
|
||||
"name": "John Doe",
|
||||
"age": @nrcount,
|
||||
"is_member": True,
|
||||
"skills": ["Python", "Data Analysis", "Machine Learning"]
|
||||
}
|
||||
|
||||
# Convert the structure to a JSON string
|
||||
json_string = json.dumps(example_struct, indent=4)
|
||||
|
||||
# Print the JSON string
|
||||
print("==RESULT==")
|
||||
print(json_string)
|
||||
```
|
||||
|
||||
> see `crystallib/examples/lang/python/pythonexample.vsh`
|
||||
|
||||
|
||||
## remark
|
||||
|
||||
This is a slow way how to execute python, is about 2 per second on a fast machine, need to implement something where we keep the python in mem and reading from a queue e.g. redis this will go much faster, but ok for now.
|
||||
|
||||
see also examples dir, there is a working example
|
||||
|
||||
14
lib/lang/python/shell.v
Normal file
14
lib/lang/python/shell.v
Normal file
@@ -0,0 +1,14 @@
|
||||
module python
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
|
||||
pub fn (py PythonEnv) shell(name_ string) ! {
|
||||
_ := texttools.name_fix(name_)
|
||||
cmd := '
|
||||
cd ${py.path.path}
|
||||
source bin/activate
|
||||
|
||||
'
|
||||
osal.exec(cmd: cmd)!
|
||||
}
|
||||
@@ -104,7 +104,7 @@ pub fn usr_local_path() !string {
|
||||
|
||||
// return the source statement if the profile exists
|
||||
pub fn profile_path_source() !string {
|
||||
if hostname() or { '' } == 'rescue' {
|
||||
if core.hostname() or { '' } == 'rescue' {
|
||||
return ''
|
||||
}
|
||||
pp := profile_path()!
|
||||
@@ -117,7 +117,7 @@ pub fn profile_path_source() !string {
|
||||
// return source $path && .
|
||||
// or empty if it doesn't exist
|
||||
pub fn profile_path_source_and() !string {
|
||||
if hostname() or { '' } == 'rescue' {
|
||||
if core.hostname() or { '' } == 'rescue' {
|
||||
return ''
|
||||
}
|
||||
pp := profile_path()!
|
||||
|
||||
@@ -4,7 +4,7 @@ module tfrobot
|
||||
import freeflowuniverse.herolib.builder
|
||||
import freeflowuniverse.herolib.osal
|
||||
// import freeflowuniverse.herolib.servers.daguserver as dagu
|
||||
import freeflowuniverse.herolib.clients.daguclient as dagu_client
|
||||
// import freeflowuniverse.herolib.clients.daguclient as dagu_client
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import time
|
||||
|
||||
|
||||
8
lib/web/mdbook/.heroscript
Normal file
8
lib/web/mdbook/.heroscript
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
!!hero_code.generate_client
|
||||
name:'mdbook'
|
||||
classname:'MDBooks'
|
||||
singleton:0
|
||||
default:1
|
||||
hasconfig:1
|
||||
reset:0
|
||||
49
lib/web/mdbook/_archive/old_factory.v
Normal file
49
lib/web/mdbook/_archive/old_factory.v
Normal file
@@ -0,0 +1,49 @@
|
||||
// module mdbook
|
||||
|
||||
// import freeflowuniverse.herolib.core.base
|
||||
// import os
|
||||
// import crypto.md5
|
||||
|
||||
// @[params]
|
||||
// pub struct Config {
|
||||
// pub mut:
|
||||
// path_build string = '${os.home_dir()}/hero/var/mdbuild'
|
||||
// path_publish string = '${os.home_dir()}/hero/www/info'
|
||||
// }
|
||||
|
||||
// // @[heap]
|
||||
// // pub struct MDBooks {
|
||||
// // pub:
|
||||
// // cfg Config
|
||||
// // }
|
||||
|
||||
// @[params]
|
||||
// pub struct InitParams{
|
||||
// action string
|
||||
// name string
|
||||
// }
|
||||
|
||||
// fn (cfg MDBooks) init(args InitParams) {
|
||||
// }
|
||||
|
||||
// pub fn get(cfg_ Config) !MDBooks {
|
||||
// mut c := base.context()!
|
||||
// // lets get a unique name based on the used build and publishpaths
|
||||
// mut cfg := cfg_
|
||||
// cfg.path_build = cfg.path_build.replace('~', os.home_dir())
|
||||
// cfg.path_publish = cfg.path_publish.replace('~', os.home_dir())
|
||||
// mut name := md5.hexhash('${cfg.path_build}${cfg.path_publish}')
|
||||
// mut myparams := c.params()!
|
||||
// mut self := MDBooks{
|
||||
// cfg: cfg
|
||||
// }
|
||||
|
||||
// if myparams.exists('mdbookname') {
|
||||
// name = myparams.get('mdbookname')!
|
||||
// self.init('mdbook', name: name, .get, cfg)!
|
||||
// } else {
|
||||
// self.init('mdbook', name, .set, cfg)!
|
||||
// myparams.set('mdbookname', name)
|
||||
// }
|
||||
// return self
|
||||
// }
|
||||
37
lib/web/mdbook/edit_open.v
Normal file
37
lib/web/mdbook/edit_open.v
Normal file
@@ -0,0 +1,37 @@
|
||||
module mdbook
|
||||
|
||||
import freeflowuniverse.herolib.develop.vscode
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import os
|
||||
|
||||
pub fn book_open(name string) ! {
|
||||
mut c := base.context()!
|
||||
mut r := c.redis()!
|
||||
mut path_publish := r.get('mdbook:${name}:publish')!
|
||||
path_publish = path_publish.replace('~', os.home_dir())
|
||||
if path_publish.len == 0 {
|
||||
return error("can't find book: ${name}, was it generated before?")
|
||||
}
|
||||
if !os.exists(path_publish) {
|
||||
return error("can't find generated book in ${path_publish}, was it generated properly.")
|
||||
}
|
||||
cmd3 := "open '${path_publish}/index.html'"
|
||||
// console.print_debug(cmd3)
|
||||
osal.exec(cmd: cmd3)!
|
||||
}
|
||||
|
||||
pub fn book_edit(name string) ! {
|
||||
mut c := base.context()!
|
||||
mut r := c.redis()!
|
||||
path_build := r.get('mdbook:${name}:build')!
|
||||
if path_build.len == 0 {
|
||||
return error("can't find book: ${name}, was it generated before?")
|
||||
}
|
||||
edit_path := '${path_build}/edit'.replace('~', os.home_dir())
|
||||
if !os.exists(edit_path) {
|
||||
return error("can't find book edit path in ${edit_path}, was it generated properly.")
|
||||
}
|
||||
vscode_helper := vscode.new(edit_path)
|
||||
vscode_helper.open()!
|
||||
}
|
||||
101
lib/web/mdbook/load.v
Normal file
101
lib/web/mdbook/load.v
Normal file
@@ -0,0 +1,101 @@
|
||||
module mdbook
|
||||
|
||||
import v.embed_file
|
||||
// import freeflowuniverse.herolib.installers.web.mdbook as mdbook_installer
|
||||
// import freeflowuniverse.herolib.installers.web.imagemagick
|
||||
import os
|
||||
|
||||
@[heap]
|
||||
pub struct FileLoader {
|
||||
pub mut:
|
||||
embedded_files []embed_file.EmbedFileData @[skip; str: skip]
|
||||
}
|
||||
|
||||
fn (mut loader FileLoader) load() ! {
|
||||
loader.embedded_files << $embed_file('template/css/print.css')
|
||||
loader.embedded_files << $embed_file('template/css/variables.css')
|
||||
loader.embedded_files << $embed_file('template/css/general.css')
|
||||
loader.embedded_files << $embed_file('template/mermaid-init.js')
|
||||
loader.embedded_files << $embed_file('template/echarts.min.js')
|
||||
loader.embedded_files << $embed_file('template/mermaid.min.js')
|
||||
}
|
||||
|
||||
fn loader() !FileLoader {
|
||||
if 'OFFLINE' !in os.environ() {
|
||||
// console.print_debug(" - CHECK INSTALLER")
|
||||
// mdbook_installer.install()!
|
||||
// imagemagick.install()!
|
||||
}
|
||||
mut loader := FileLoader{}
|
||||
return loader
|
||||
}
|
||||
|
||||
// if true {
|
||||
// panic('generate')
|
||||
// }
|
||||
// now we have to reset the rev keys, so we remember current status
|
||||
// for key, mut status in self.gitrepos_status {
|
||||
// osal.done_set('mdbookrev_${key}', status.revnew)!
|
||||
// status.revlast = status.revnew
|
||||
// }
|
||||
|
||||
// pub struct RepoStatus {
|
||||
// pub mut:
|
||||
// revlast string
|
||||
// revnew string
|
||||
// }
|
||||
|
||||
// make sure all intial states for the revisions are reset
|
||||
// fn (mut self MDBooksFactory) reset_state() ! {
|
||||
// for key, mut status in self.gitrepos_status {
|
||||
// osal.done_set('mdbookrev_${key}', '')!
|
||||
// status.revlast = ''
|
||||
// }
|
||||
// }
|
||||
|
||||
// get all content
|
||||
// pub fn (mut self MDBooksFactory) pull(reset bool) ! {
|
||||
// console.print_header(' pull mdbooks')
|
||||
// print_backtrace()
|
||||
// self.init()!
|
||||
// for key, repo_ in self.gitrepos {
|
||||
// mut repo := repo_
|
||||
// if reset {
|
||||
// repo.pull_reset(reload: true)! // need to overwrite all changes
|
||||
// } else {
|
||||
// repo.pull(reload: true)! // will not overwrite changes
|
||||
// }
|
||||
// revnew := repo.rev()!
|
||||
// lastrev := osal.done_get('mdbookrev_${key}') or { '' }
|
||||
// self.gitrepos_status[key] = RepoStatus{
|
||||
// revnew: revnew
|
||||
// revlast: lastrev
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// @[params]
|
||||
// pub struct WatchArgs {
|
||||
// pub mut:
|
||||
// period int = 300 // 5 min default
|
||||
// reset bool
|
||||
// }
|
||||
|
||||
// pub fn (mut self MDBooksFactory) watch(args WatchArgs) {
|
||||
// mut t := ourtime.now()
|
||||
// mut last := i64(0)
|
||||
// for {
|
||||
// t.now()
|
||||
// console.print_stdout('${t} ${t.unix()} period:${args.period}')
|
||||
// if t.unix() > last + args.period {
|
||||
// console.print_header(' will try to check the mdbooks')
|
||||
// self.pull(args.reset) or { panic(" - ERROR: couldn't pull the repo's.\n${err}") }
|
||||
// self.generate() or { panic(" - ERROR: couldn't generate the repo's.\n${err}") }
|
||||
// last = t.unix()
|
||||
// }
|
||||
// time.sleep(time.second)
|
||||
// if args.period == 0 {
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
296
lib/web/mdbook/mdbook.v
Normal file
296
lib/web/mdbook/mdbook.v
Normal file
@@ -0,0 +1,296 @@
|
||||
module mdbook
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import os
|
||||
import freeflowuniverse.herolib.data.doctree.collection
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
|
||||
@[heap]
|
||||
pub struct MDBook {
|
||||
pub mut:
|
||||
name string
|
||||
books &MDBooks @[skip; str: skip]
|
||||
path_build pathlib.Path
|
||||
path_publish pathlib.Path
|
||||
args MDBookArgs
|
||||
errors []collection.CollectionError
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct MDBookArgs {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
title string
|
||||
|
||||
foldlevel int
|
||||
printbook bool
|
||||
// summary_url string // url of the summary.md file
|
||||
summary_path string // can also give the path to the summary file (can be the dir or the summary itself)
|
||||
// doctree_url string
|
||||
// doctree_path string
|
||||
publish_path string
|
||||
build_path string
|
||||
production bool
|
||||
collections []string
|
||||
description string
|
||||
export bool // whether mdbook should be built
|
||||
}
|
||||
|
||||
pub fn (mut books MDBooks) generate(args_ MDBookArgs) !&MDBook {
|
||||
console.print_header(' mdbook: ${args_.name}')
|
||||
mut args := args_
|
||||
|
||||
if args.title == '' {
|
||||
args.title = args.name
|
||||
}
|
||||
if args.build_path.len == 0 {
|
||||
args.build_path = '${books.path_build}/${args.name}'
|
||||
}
|
||||
if args.publish_path.len == 0 {
|
||||
args.publish_path = '${books.path_publish}/${args.name}'
|
||||
}
|
||||
|
||||
mut mycontext := base.context()!
|
||||
mut r := mycontext.redis()!
|
||||
r.set('mdbook:${args.name}:build', args.build_path)!
|
||||
r.set('mdbook:${args.name}:publish', args.publish_path)!
|
||||
r.expire('mdbook:${args.name}:build', 3600 * 12)! // expire after 12h
|
||||
r.expire('mdbook:${args.name}:publish', 3600 * 12)!
|
||||
|
||||
_ := gittools.get()!
|
||||
|
||||
mut src_path := pathlib.get_dir(path: '${args.build_path}/src', create: true)!
|
||||
_ := pathlib.get_dir(path: '${args.build_path}/.edit', create: true)!
|
||||
mut collection_set := map[string]bool{}
|
||||
for col_path in args.collections {
|
||||
// link collections from col_path to src
|
||||
mut p := pathlib.get_dir(path: col_path)!
|
||||
_ := p.list(dirs_only: true, recursive: false)!
|
||||
|
||||
if _ := collection_set[p.name()] {
|
||||
return error('collection with name ${p.name()} already exists')
|
||||
}
|
||||
p.link('${src_path.path}/${p.name()}', true)!
|
||||
|
||||
// QUESTION: why was this ever implemented per entry?
|
||||
// for mut entry in entries.paths {
|
||||
// if _ := collection_set[entry.name()] {
|
||||
// println('collection with name ${entry.name()} already exists')
|
||||
// // return error('collection with name ${entry.name()} already exists')
|
||||
// }
|
||||
|
||||
// collection_set[entry.name()] = true
|
||||
// entry.link('${src_path.path}/${entry.name()}', true)!
|
||||
// }
|
||||
}
|
||||
|
||||
mut book := MDBook{
|
||||
args: args
|
||||
path_build: pathlib.get_dir(path: args.build_path, create: true)!
|
||||
path_publish: pathlib.get_dir(path: args.publish_path, create: true)!
|
||||
books: &books
|
||||
}
|
||||
|
||||
mut summary := book.summary(args_.production)!
|
||||
|
||||
mut dir_list := src_path.list(dirs_only: true, include_links: true, recursive: false)!
|
||||
for mut collection_dir_path in dir_list.paths {
|
||||
collectionname := collection_dir_path.path.all_after_last('/')
|
||||
// should always work because done in summary
|
||||
// check if there are errors, if yes add to summary
|
||||
if os.exists('${collection_dir_path.path}/errors.md') {
|
||||
summary.add_error_page(collectionname, 'errors.md')
|
||||
}
|
||||
// now link the exported collection into the build dir
|
||||
collection_dirbuild_str := '${book.path_build.path}/src/${collectionname}'.replace('~',
|
||||
os.home_dir())
|
||||
if !pathlib.path_equal(collection_dirbuild_str, collection_dir_path.path) {
|
||||
collection_dir_path.link(collection_dirbuild_str, true)!
|
||||
}
|
||||
|
||||
if !os.exists('${collection_dir_path.path}/.linkedpages') {
|
||||
continue
|
||||
}
|
||||
|
||||
mut linked_pages := pathlib.get_file(path: '${collection_dir_path.path}/.linkedpages')!
|
||||
lpagescontent := linked_pages.read()!
|
||||
for lpagestr in lpagescontent.split_into_lines().filter(it.trim_space() != '') {
|
||||
// console.print_green('find linked page: ${lpagestr}')
|
||||
// format $collection:$pagename.md
|
||||
splitted := lpagestr.split(':')
|
||||
assert splitted.len == 2
|
||||
summary.add_page_additional(splitted[0], splitted[1])
|
||||
}
|
||||
|
||||
// if collection_dir_path.file_exists('.linkedpages') {
|
||||
// mut lpages := collection_dir_path.file_get('.linkedpages')!
|
||||
// lpagescontent := lpages.read()!
|
||||
// for lpagestr in lpagescontent.split_into_lines().filter(it.trim_space() != '') {
|
||||
// // console.print_green('find linked page: ${lpagestr}')
|
||||
// // format $collection:$pagename.md
|
||||
// splitted := lpagestr.split(':')
|
||||
// assert splitted.len == 2
|
||||
// summary.add_page_additional(splitted[0], splitted[1])
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// create the additional collection (is a system collection)
|
||||
addpath := '${book.path_build.path}/src/additional'
|
||||
mut a := pathlib.get_file(path: '${addpath}/additional.md', create: true)!
|
||||
mut b := pathlib.get_file(path: '${addpath}/errors.md', create: true)!
|
||||
mut c := pathlib.get_file(path: '${addpath}/pages.md', create: true)!
|
||||
|
||||
a.write('
|
||||
# Additional pages
|
||||
|
||||
A normal user can ignore these pages, they are for the authors to see e.g. errors
|
||||
|
||||
')!
|
||||
|
||||
b.write('
|
||||
# Errors
|
||||
|
||||
Be the mother for our errors.
|
||||
|
||||
')!
|
||||
c.write('
|
||||
# Additional pages
|
||||
|
||||
You can ignore these pages, they are just to get links to work.
|
||||
|
||||
')!
|
||||
|
||||
if book.errors.len > 0 {
|
||||
book.errors_report()!
|
||||
|
||||
summary.errors << SummaryItem{
|
||||
level: 2
|
||||
description: 'errors mdbook'
|
||||
pagename: 'errors_mdbook.md'
|
||||
collection: 'additional'
|
||||
}
|
||||
}
|
||||
|
||||
path_summary_str := '${book.path_build.path}/src/SUMMARY.md'
|
||||
mut path_summary := pathlib.get_file(path: path_summary_str, create: true)!
|
||||
path_summary.write(summary.str())!
|
||||
|
||||
book.template_install()!
|
||||
|
||||
if args.export {
|
||||
book.generate()!
|
||||
}
|
||||
|
||||
console.print_header(' mdbook prepared: ${book.path_build.path}')
|
||||
|
||||
return &book
|
||||
}
|
||||
|
||||
// write errors.md in the collection, this allows us to see what the errors are
|
||||
fn (book MDBook) errors_report() ! {
|
||||
errors_path_str := '${book.path_build.path}/src/additional/errors_mdbook.md'
|
||||
mut dest := pathlib.get_file(path: errors_path_str, create: true)!
|
||||
if book.errors.len == 0 {
|
||||
dest.delete()!
|
||||
return
|
||||
}
|
||||
c := $tmpl('template/errors.md')
|
||||
dest.write(c)!
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ErrorArgs {
|
||||
pub mut:
|
||||
path string
|
||||
msg string
|
||||
cat collection.CollectionErrorCat
|
||||
}
|
||||
|
||||
pub fn (mut book MDBook) error(args ErrorArgs) {
|
||||
path2 := pathlib.get(args.path)
|
||||
e := collection.CollectionError{
|
||||
path: path2
|
||||
msg: args.msg
|
||||
cat: args.cat
|
||||
}
|
||||
book.errors << e
|
||||
console.print_stderr(args.msg)
|
||||
}
|
||||
|
||||
pub fn (mut book MDBook) open() ! {
|
||||
console.print_header('open book: ${book.name}')
|
||||
cmd := 'open \'${book.path_publish.path}/index.html\''
|
||||
// console.print_debug(cmd)
|
||||
// cmd:='bash ${book.path_build.path}/develop.sh'
|
||||
osal.exec(cmd: cmd)!
|
||||
}
|
||||
|
||||
pub fn (mut book MDBook) generate() ! {
|
||||
console.print_header(' book generate: ${book.name} on ${book.path_build.path}')
|
||||
|
||||
book.summary_image_set()!
|
||||
osal.exec(
|
||||
cmd: '
|
||||
cd ${book.path_build.path}
|
||||
mdbook build --dest-dir ${book.path_publish.path}
|
||||
'
|
||||
retry: 0
|
||||
)!
|
||||
}
|
||||
|
||||
fn (mut book MDBook) template_install() ! {
|
||||
// get embedded files to the mdbook dir
|
||||
// console.print_debug(book.str())
|
||||
mut l := loader()!
|
||||
l.load()!
|
||||
for item in l.embedded_files {
|
||||
dpath := '${book.path_build.path}/${item.path.all_after_first('/')}'
|
||||
// console.print_debug(' embed: ${dpath}')
|
||||
mut dpatho := pathlib.get_file(path: dpath, create: true)!
|
||||
dpatho.write(item.to_string())!
|
||||
}
|
||||
|
||||
c := $tmpl('template/book.toml')
|
||||
mut tomlfile := book.path_build.file_get_new('book.toml')!
|
||||
tomlfile.write(c)!
|
||||
|
||||
c1 := $tmpl('template/build.sh')
|
||||
mut file1 := book.path_build.file_get_new('build.sh')!
|
||||
file1.write(c1)!
|
||||
file1.chmod(0o770)!
|
||||
|
||||
c2 := $tmpl('template/develop.sh')
|
||||
mut file2 := book.path_build.file_get_new('develop.sh')!
|
||||
file2.write(c2)!
|
||||
file2.chmod(0o770)!
|
||||
}
|
||||
|
||||
fn (mut book MDBook) summary_image_set() ! {
|
||||
// this is needed to link the first image dir in the summary to the src, otherwise empty home image
|
||||
|
||||
summaryfile := '${book.path_build.path}/src/SUMMARY.md'
|
||||
mut p := pathlib.get_file(path: summaryfile)!
|
||||
c := p.read()!
|
||||
mut first := true
|
||||
for line in c.split_into_lines() {
|
||||
if !(line.trim_space().starts_with('-')) {
|
||||
continue
|
||||
}
|
||||
if line.contains('](') && first {
|
||||
folder_first := line.all_after('](').all_before_last(')')
|
||||
folder_first_dir_img := '${book.path_build.path}/src/${folder_first.all_before_last('/')}/img'
|
||||
// console.print_debug(folder_first_dir_img)
|
||||
// if true{panic("s")}
|
||||
if os.exists(folder_first_dir_img) {
|
||||
mut image_dir := pathlib.get_dir(path: folder_first_dir_img)!
|
||||
image_dir.link('${book.path_build.path}/src/img', true)!
|
||||
}
|
||||
|
||||
first = false
|
||||
}
|
||||
}
|
||||
}
|
||||
105
lib/web/mdbook/mdbook_factory_.v
Normal file
105
lib/web/mdbook/mdbook_factory_.v
Normal file
@@ -0,0 +1,105 @@
|
||||
module mdbook
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
|
||||
__global (
|
||||
mdbook_global map[string]&MDBooks
|
||||
mdbook_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
fn args_get(args_ ArgsGet) ArgsGet {
|
||||
mut args := args_
|
||||
if args.name == '' {
|
||||
args.name = mdbook_default
|
||||
}
|
||||
if args.name == '' {
|
||||
args.name = 'default'
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&MDBooks {
|
||||
mut args := args_get(args_)
|
||||
if args.name !in mdbook_global {
|
||||
if !config_exists() {
|
||||
if default {
|
||||
config_save()!
|
||||
}
|
||||
}
|
||||
config_load()!
|
||||
}
|
||||
return mdbook_global[args.name] or {
|
||||
println(mdbook_global)
|
||||
panic('bug in get from factory: ')
|
||||
}
|
||||
}
|
||||
|
||||
fn config_exists(args_ ArgsGet) bool {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context() or { panic('bug') }
|
||||
return context.hero_config_exists('mdbook', args.name)
|
||||
}
|
||||
|
||||
fn config_load(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
mut heroscript := context.hero_config_get('mdbook', args.name)!
|
||||
play(heroscript: heroscript)!
|
||||
}
|
||||
|
||||
fn config_save(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_set('mdbook', args.name, heroscript_default()!)!
|
||||
}
|
||||
|
||||
fn set(o MDBooks) ! {
|
||||
mut o2 := obj_init(o)!
|
||||
mdbook_global['default'] = &o2
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
|
||||
start bool
|
||||
stop bool
|
||||
restart bool
|
||||
delete bool
|
||||
configure bool // make sure there is at least one installed
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
if args.heroscript == '' {
|
||||
args.heroscript = heroscript_default()!
|
||||
}
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut install_actions := plbook.find(filter: 'mdbook.configure')!
|
||||
if install_actions.len > 0 {
|
||||
for install_action in install_actions {
|
||||
mut p := install_action.params
|
||||
cfg_play(p)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// switch instance to be used for mdbook
|
||||
pub fn switch(name string) {
|
||||
mdbook_default = name
|
||||
}
|
||||
66
lib/web/mdbook/mdbook_model.v
Normal file
66
lib/web/mdbook/mdbook_model.v
Normal file
@@ -0,0 +1,66 @@
|
||||
module mdbook
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
import os
|
||||
|
||||
pub const version = '1.14.3'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// TODO: THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE TO STRUCT BELOW, IS STRUCTURED AS HEROSCRIPT
|
||||
pub fn heroscript_default() !string {
|
||||
heroscript := "
|
||||
!!mdbook.configure
|
||||
name:'mdbook'
|
||||
mail_from: 'info@example.com'
|
||||
mail_password: 'secretpassword'
|
||||
mail_port: 587
|
||||
mail_server: 'smtp-relay.brevo.com'
|
||||
mail_username: 'kristof@incubaid.com'
|
||||
|
||||
"
|
||||
|
||||
// mail_from := os.getenv_opt('MAIL_FROM') or {'info@example.com'}
|
||||
// mail_password := os.getenv_opt('MAIL_PASSWORD') or {'secretpassword'}
|
||||
// mail_port := (os.getenv_opt('MAIL_PORT') or {"587"}).int()
|
||||
// mail_server := os.getenv_opt('MAIL_SERVER') or {'smtp-relay.brevo.com'}
|
||||
// mail_username := os.getenv_opt('MAIL_USERNAME') or {'kristof@incubaid.com'}
|
||||
//
|
||||
// heroscript:="
|
||||
// !!mailclient.configure name:'default'
|
||||
// mail_from: '${mail_from}'
|
||||
// mail_password: '${mail_password}'
|
||||
// mail_port: ${mail_port}
|
||||
// mail_server: '${mail_server}'
|
||||
// mail_username: '${mail_username}'
|
||||
//
|
||||
// "
|
||||
//
|
||||
|
||||
return heroscript
|
||||
}
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
@[heap]
|
||||
pub struct MDBooks {
|
||||
pub mut:
|
||||
name string
|
||||
path_build string
|
||||
path_publish string
|
||||
}
|
||||
|
||||
fn cfg_play(p paramsparser.Params) ! {
|
||||
// THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
|
||||
mut mycfg := MDBooks{
|
||||
name: p.get_default('name', 'default')!
|
||||
path_build: p.get_default('path_build', '${os.home_dir()}/hero/var/mdbuild')!
|
||||
path_publish: p.get_default('path_publish', '${os.home_dir()}/hero/www/info')!
|
||||
}
|
||||
set(mycfg)!
|
||||
}
|
||||
|
||||
fn obj_init(obj_ MDBooks) !MDBooks {
|
||||
// never call get here, only thing we can do here is work on object itself
|
||||
mut obj := obj_
|
||||
return obj
|
||||
}
|
||||
32
lib/web/mdbook/readme.md
Normal file
32
lib/web/mdbook/readme.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# mdbook
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.clients. mdbook
|
||||
|
||||
mut client:= mdbook.get()!
|
||||
|
||||
client...
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
|
||||
```hero
|
||||
!!mdbook.configure
|
||||
secret: '...'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
```
|
||||
|
||||
|
||||
222
lib/web/mdbook/summary.v
Normal file
222
lib/web/mdbook/summary.v
Normal file
@@ -0,0 +1,222 @@
|
||||
module mdbook
|
||||
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import os
|
||||
|
||||
@[heap]
|
||||
pub struct Summary {
|
||||
pub mut:
|
||||
items []SummaryItem
|
||||
errors []SummaryItem // means we found errors, so we need to add to summary
|
||||
addpages []SummaryItem // means we found pages as links, so we need to add them to the summary
|
||||
collections []string
|
||||
production bool
|
||||
}
|
||||
|
||||
pub struct SummaryItem {
|
||||
pub mut:
|
||||
level int
|
||||
description string
|
||||
relpath string // relative path of summary item to source
|
||||
collection string
|
||||
pagename string
|
||||
}
|
||||
|
||||
pub fn (mut book MDBook) summary(production bool) !Summary {
|
||||
if !os.exists(book.args.summary_path) {
|
||||
panic("summary file ${book.args.summary_path} doesn't exist")
|
||||
}
|
||||
mut summary := Summary{
|
||||
production: production
|
||||
}
|
||||
mut summary_path := pathlib.get_file(path: book.args.summary_path, create: false)!
|
||||
c := summary_path.read()!
|
||||
|
||||
summary_path.link('${book.path_build.path}/edit/summary.md', true)!
|
||||
|
||||
mut level := 0
|
||||
mut ident := 2
|
||||
|
||||
for mut line in c.split_into_lines() {
|
||||
if !(line.trim_space().starts_with('-')) {
|
||||
continue
|
||||
}
|
||||
pre := line.all_before('-')
|
||||
level = int(pre.len / ident)
|
||||
// console.print_debug("${line} === '${pre}' ${level}")
|
||||
line = line.trim_left(' -')
|
||||
|
||||
// - [Dunia Yetu](dy_intro/dunia_yetu/dunia_yetu.md)
|
||||
// - [About Us](dy_intro/dunia_yetu/about_us.md)
|
||||
|
||||
if !line.starts_with('[') {
|
||||
book.error(msg: "syntax error in summary: '${line}', needs to start with [")
|
||||
continue
|
||||
}
|
||||
|
||||
if !line.contains('](') {
|
||||
book.error(msg: "syntax error in summary: '${line}', needs to have ](")
|
||||
continue
|
||||
}
|
||||
|
||||
description := line.all_after_first('[').all_before(']').trim_space()
|
||||
path := line.all_after_last('(').all_before_last(')').trim_space()
|
||||
|
||||
if !path.contains('/') {
|
||||
book.error(
|
||||
msg: "syntax error in summary: '${line}', doesn't contain collectionname (is first element of path)"
|
||||
)
|
||||
continue
|
||||
}
|
||||
pagename := texttools.name_fix(path.all_after_last('/'))
|
||||
collection := texttools.name_fix(path.all_before('/'))
|
||||
|
||||
if collection !in summary.collections {
|
||||
summary.collections << collection
|
||||
}
|
||||
|
||||
mut path_collection_str := '${book.args.build_path}/src/${collection}'.replace('~',
|
||||
os.home_dir())
|
||||
|
||||
mut path_collection := pathlib.get_dir(path: path_collection_str, create: false) or {
|
||||
book.error(
|
||||
msg: "collection find error in summary: '${line}', can't find collection: ${path_collection_str} "
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
list := path_collection.list()!
|
||||
file_path_ := list.paths.filter(it.name() == pagename)
|
||||
if file_path_.len == 0 {
|
||||
book.error(
|
||||
msg: "page find error in summary: '${line}', can't find page: ${pagename} in collection: ${path_collection_str}\n${file_path_} doesnt exist"
|
||||
)
|
||||
continue
|
||||
} else if file_path_.len > 1 {
|
||||
book.error(msg: 'duplicate page in collection: ${pagename}')
|
||||
continue
|
||||
}
|
||||
|
||||
file_path := file_path_[0].path
|
||||
|
||||
if !os.exists(file_path) || !os.is_file(file_path) {
|
||||
book.error(
|
||||
msg: "page find error in summary: '${line}', can't find page: ${pagename} in collection: ${path_collection_str}\n${file_path} doesnt exist"
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
// NOTE: using this returns false because path_collection is a link
|
||||
// if !path_collection.file_exists(pagename) {
|
||||
// book.error(
|
||||
// msg: "page find error in summary: '${line}', can't find page: ${pagename} in collection: ${path_collection_str}"
|
||||
// )
|
||||
// continue
|
||||
// }
|
||||
|
||||
summary.items << SummaryItem{
|
||||
level: level
|
||||
description: description
|
||||
pagename: pagename
|
||||
relpath: file_path.all_after('${book.args.build_path}/src/') // relative path of page to src dir
|
||||
collection: collection
|
||||
}
|
||||
}
|
||||
|
||||
return summary
|
||||
}
|
||||
|
||||
fn (mut self Summary) add_error_page(collectionname string, pagename string) {
|
||||
description := 'errors ${collectionname}'
|
||||
self.errors << SummaryItem{
|
||||
level: 2
|
||||
description: description
|
||||
pagename: pagename
|
||||
collection: collectionname
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut self Summary) is_in_summary(collection_name_ string, page_name_ string) bool {
|
||||
mut collection_name := texttools.name_fix(collection_name_).to_lower()
|
||||
mut page_name := texttools.name_fix(page_name_).to_lower()
|
||||
if !(page_name.ends_with('.md')) {
|
||||
page_name += '.md'
|
||||
}
|
||||
|
||||
for i in self.items {
|
||||
mut pname := texttools.name_fix(i.pagename.to_lower())
|
||||
if !(pname.ends_with('.md')) {
|
||||
pname += '.md'
|
||||
}
|
||||
if i.collection.to_lower() == collection_name && pname == page_name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for i in self.addpages {
|
||||
mut pname := texttools.name_fix(i.pagename.to_lower())
|
||||
if !(pname.ends_with('.md')) {
|
||||
pname += '.md'
|
||||
}
|
||||
if i.collection.to_lower() == collection_name && pname == page_name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fn (mut self Summary) add_page_additional(collectionname string, pagename string) {
|
||||
if self.is_in_summary(collectionname, pagename) {
|
||||
return
|
||||
}
|
||||
|
||||
shortname := pagename.all_before_last('.').to_lower()
|
||||
description := '${shortname}'
|
||||
self.addpages << SummaryItem{
|
||||
level: 2
|
||||
description: description
|
||||
pagename: pagename
|
||||
collection: collectionname
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Summary) str() string {
|
||||
mut out := []string{}
|
||||
|
||||
for item in self.items {
|
||||
mut pre := ''
|
||||
for _ in 0 .. item.level {
|
||||
pre += ' '
|
||||
}
|
||||
out << '${pre}- [${item.description}](${item.relpath})'
|
||||
}
|
||||
|
||||
if self.addpages.len > 0 || (!self.production && self.errors.len > 0) {
|
||||
out << '- [_](additional/additional.md)'
|
||||
}
|
||||
|
||||
if self.addpages.len > 0 {
|
||||
out << ' - [unlisted_pages](additional/pages.md)'
|
||||
for item in self.addpages {
|
||||
mut pre := ''
|
||||
for _ in 0 .. item.level {
|
||||
pre += ' '
|
||||
}
|
||||
out << '${pre}- [${item.description}](${item.collection}/${item.pagename})'
|
||||
}
|
||||
}
|
||||
|
||||
if !self.production && self.errors.len > 0 {
|
||||
out << ' - [errors](additional/errors.md)'
|
||||
for item in self.errors {
|
||||
mut pre := ''
|
||||
for _ in 0 .. item.level {
|
||||
pre += ' '
|
||||
}
|
||||
out << '${pre}- [${item.description}](${item.collection}/${item.pagename})'
|
||||
}
|
||||
}
|
||||
|
||||
return out.join_lines()
|
||||
}
|
||||
70
lib/web/mdbook/template/book.toml
Normal file
70
lib/web/mdbook/template/book.toml
Normal file
@@ -0,0 +1,70 @@
|
||||
[book]
|
||||
authors = []
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "@book.args.title"
|
||||
|
||||
[output.html.fold]
|
||||
enable = true
|
||||
level = @book.args.foldlevel
|
||||
|
||||
[output]
|
||||
|
||||
[output.html]
|
||||
no-section-label = true
|
||||
additional-css = ["css/general.css"]
|
||||
additional-js = ["mermaid.min.js", "mermaid-init.js", "echarts.min.js"]
|
||||
default-theme = "light"
|
||||
mathjax-support = true
|
||||
preserve-inline-html = true
|
||||
|
||||
[build]
|
||||
create-missing = false
|
||||
|
||||
[output.html.print]
|
||||
enable = @book.args.printbook
|
||||
|
||||
[preprocessor]
|
||||
|
||||
[preprocessor.mermaid]
|
||||
command = "mdbook-mermaid"
|
||||
|
||||
# [preprocessor.last-changed]
|
||||
# command = "mdbook-last-changed"
|
||||
# renderer = ["html"]
|
||||
|
||||
#use as mdbook preprocessor
|
||||
[preprocessor.echarts]
|
||||
|
||||
# [preprocessor.embed]
|
||||
|
||||
[preprocessor.kroki-preprocessor]
|
||||
|
||||
# [output.linkcheck]
|
||||
# follow-web-links = true
|
||||
# traverse-parent-directories = true
|
||||
# warning-policy = "warn"
|
||||
|
||||
# [output.pdf]
|
||||
# landscape = false
|
||||
# display-header-footer = true
|
||||
# print-background = true
|
||||
# theme = "ayu"
|
||||
# # scale = 0.7
|
||||
# paper-width = 8.3
|
||||
# paper-height = 11.7
|
||||
# margin-top = 0.5
|
||||
# margin-bottom = 0.5
|
||||
# margin-left = 0.5
|
||||
# margin-right = 0.5
|
||||
# page-ranges = ""
|
||||
# ignore-invalid-page-ranges = false
|
||||
# header-template = "<h3 style='font-size:8px; margin-left: 48%' class='title'></h3>"
|
||||
# footer-template = "<p style='font-size:10px; margin-left: 48%'><span class='pageNumber'></span> / <span class='totalPages'></span></p>"
|
||||
# prefer-css-page-size = false
|
||||
|
||||
# [preprocessor.plantuml]
|
||||
# plantuml-cmd="http://localhost:8080/plantuml"
|
||||
# # plantuml-cmd="http://www.plantuml.com/plantuml"
|
||||
# use-data-uris=true
|
||||
3
lib/web/mdbook/template/build.sh
Normal file
3
lib/web/mdbook/template/build.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
set -e
|
||||
cd ${book.path_build.path}
|
||||
mdbook build --dest-dir ${book.path_publish.path}
|
||||
208
lib/web/mdbook/template/css/general.css
Normal file
208
lib/web/mdbook/template/css/general.css
Normal file
@@ -0,0 +1,208 @@
|
||||
/* Base styles and content styles */
|
||||
|
||||
@import 'variables.css';
|
||||
|
||||
:root {
|
||||
/* Browser default font-size is 16px, this way 1 rem = 10px */
|
||||
font-size: 62.5%;
|
||||
color-scheme: var(--color-scheme);
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
color: var(--fg);
|
||||
background-color: var(--bg);
|
||||
text-size-adjust: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: 1.6rem;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: var(--mono-font) !important;
|
||||
font-size: var(--code-font-size);
|
||||
}
|
||||
|
||||
/* make long words/inline code not x overflow */
|
||||
main {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* make wide tables scroll if they overflow */
|
||||
.table-wrapper {
|
||||
overflow-x: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Don't change font size in headers. */
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
font-size: unset;
|
||||
}
|
||||
|
||||
.left { float: left; }
|
||||
.right { float: right; }
|
||||
.boring { opacity: 0.6; }
|
||||
.hide-boring .boring { display: none; }
|
||||
.hidden { display: none !important; }
|
||||
|
||||
h2, h3 { margin-top: 2.5em; }
|
||||
h4, h5 { margin-top: 2em; }
|
||||
|
||||
.header + .header h3,
|
||||
.header + .header h4,
|
||||
.header + .header h5 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
h1:target::before,
|
||||
h2:target::before,
|
||||
h3:target::before,
|
||||
h4:target::before,
|
||||
h5:target::before,
|
||||
h6:target::before {
|
||||
display: inline-block;
|
||||
content: "»";
|
||||
margin-left: -30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
/* This is broken on Safari as of version 14, but is fixed
|
||||
in Safari Technology Preview 117 which I think will be Safari 14.2.
|
||||
https://bugs.webkit.org/show_bug.cgi?id=218076
|
||||
*/
|
||||
:target {
|
||||
scroll-margin-top: calc(var(--menu-bar-height) + 0.5em);
|
||||
}
|
||||
|
||||
.page {
|
||||
outline: 0;
|
||||
padding: 0 var(--page-padding);
|
||||
margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */
|
||||
}
|
||||
.page-wrapper {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.js:not(.sidebar-resizing) .page-wrapper {
|
||||
transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */
|
||||
}
|
||||
|
||||
.content {
|
||||
overflow-y: auto;
|
||||
padding: 0 5px 5px 5px;
|
||||
}
|
||||
.content main {
|
||||
margin-left: 20;
|
||||
margin-right: auto;
|
||||
max-width: 1000px;
|
||||
}
|
||||
.content p { line-height: 1.45em; }
|
||||
.content ol { line-height: 1.45em; }
|
||||
.content ul { line-height: 1.45em; }
|
||||
.content a { text-decoration: none; }
|
||||
.content a:hover { text-decoration: underline; }
|
||||
.content img, .content video { max-width: 100%; }
|
||||
.content .header:link,
|
||||
.content .header:visited {
|
||||
color: var(--fg);
|
||||
}
|
||||
.content .header:link,
|
||||
.content .header:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 0 auto;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
table td {
|
||||
padding: 3px 20px;
|
||||
border: 1px var(--table-border-color) solid;
|
||||
}
|
||||
table thead {
|
||||
background: var(--table-header-bg);
|
||||
}
|
||||
table thead td {
|
||||
font-weight: 700;
|
||||
border: none;
|
||||
}
|
||||
table thead th {
|
||||
padding: 3px 20px;
|
||||
}
|
||||
table thead tr {
|
||||
border: 1px var(--table-header-bg) solid;
|
||||
}
|
||||
/* Alternate background colors for rows */
|
||||
table tbody tr:nth-child(2n) {
|
||||
background: var(--table-alternate-bg);
|
||||
}
|
||||
|
||||
|
||||
blockquote {
|
||||
margin: 20px 0;
|
||||
padding: 0 20px;
|
||||
color: var(--fg);
|
||||
background-color: var(--quote-bg);
|
||||
border-top: .1em solid var(--quote-border);
|
||||
border-bottom: .1em solid var(--quote-border);
|
||||
}
|
||||
|
||||
kbd {
|
||||
background-color: var(--table-border-color);
|
||||
border-radius: 4px;
|
||||
border: solid 1px var(--theme-popup-border);
|
||||
box-shadow: inset 0 -1px 0 var(--theme-hover);
|
||||
display: inline-block;
|
||||
font-size: var(--code-font-size);
|
||||
font-family: var(--mono-font);
|
||||
line-height: 10px;
|
||||
padding: 4px 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
:not(.footnote-definition) + .footnote-definition,
|
||||
.footnote-definition + :not(.footnote-definition) {
|
||||
margin-top: 2em;
|
||||
}
|
||||
.footnote-definition {
|
||||
font-size: 0.9em;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.footnote-definition p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.tooltiptext {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */
|
||||
left: -8px; /* Half of the width of the icon */
|
||||
top: -35px;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px 8px;
|
||||
margin: 5px;
|
||||
z-index: 1000;
|
||||
}
|
||||
.tooltipped .tooltiptext {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.chapter li.part-title {
|
||||
color: var(--sidebar-fg);
|
||||
margin: 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.result-no-output {
|
||||
font-style: italic;
|
||||
}
|
||||
71
lib/web/mdbook/template/css/print.css
Normal file
71
lib/web/mdbook/template/css/print.css
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
#sidebar,
|
||||
#menu-bar,
|
||||
.nav-collections,
|
||||
.mobile-nav-collections {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-wrapper.page-wrapper {
|
||||
transform: none;
|
||||
margin-left: 0px;
|
||||
overflow-y: initial;
|
||||
}
|
||||
|
||||
#content {
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page {
|
||||
overflow-y: initial;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #666666;
|
||||
border-radius: 5px;
|
||||
|
||||
/* Force background to be printed in Chrome */
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
pre > .buttons {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
a, a:visited, a:active, a:hover {
|
||||
color: #4183c4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
page-break-inside: avoid;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 {
|
||||
page-break-inside: avoid;
|
||||
/* page-break-before: avoid; */
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
|
||||
pre, code {
|
||||
page-break-inside: avoid;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.fa {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1.25rem !important;
|
||||
}
|
||||
|
||||
@@media print {
|
||||
h1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
}
|
||||
265
lib/web/mdbook/template/css/variables.css
Normal file
265
lib/web/mdbook/template/css/variables.css
Normal file
@@ -0,0 +1,265 @@
|
||||
|
||||
/* Globals */
|
||||
|
||||
:root {
|
||||
--sidebar-width: 250px;
|
||||
--page-padding: 15px;
|
||||
--content-max-width: 1600px;
|
||||
--menu-bar-height: 50px;
|
||||
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
|
||||
--code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */
|
||||
}
|
||||
|
||||
/* Themes */
|
||||
|
||||
.ayu {
|
||||
--bg: hsl(210, 25%, 8%);
|
||||
--fg: #c5c5c5;
|
||||
|
||||
--sidebar-bg: #14191f;
|
||||
--sidebar-fg: #c8c9db;
|
||||
--sidebar-non-existant: #5c6773;
|
||||
--sidebar-active: #ffb454;
|
||||
--sidebar-spacer: #2d334f;
|
||||
|
||||
--scrollbar: var(--sidebar-fg);
|
||||
|
||||
--icons: #737480;
|
||||
--icons-hover: #b7b9cc;
|
||||
|
||||
--links: #0096cf;
|
||||
|
||||
--inline-code-color: #ffb454;
|
||||
|
||||
--theme-popup-bg: #14191f;
|
||||
--theme-popup-border: #5c6773;
|
||||
--theme-hover: #191f26;
|
||||
|
||||
--quote-bg: hsl(226, 15%, 17%);
|
||||
--quote-border: hsl(226, 15%, 22%);
|
||||
|
||||
--table-border-color: hsl(210, 25%, 13%);
|
||||
--table-header-bg: hsl(210, 25%, 28%);
|
||||
--table-alternate-bg: hsl(210, 25%, 11%);
|
||||
|
||||
--searchbar-border-color: #848484;
|
||||
--searchbar-bg: #424242;
|
||||
--searchbar-fg: #fff;
|
||||
--searchbar-shadow-color: #d4c89f;
|
||||
--searchresults-header-fg: #666;
|
||||
--searchresults-border-color: #888;
|
||||
--searchresults-li-bg: #252932;
|
||||
--search-mark-bg: #e3b171;
|
||||
|
||||
--color-scheme: dark;
|
||||
}
|
||||
|
||||
.coal {
|
||||
--bg: hsl(200, 7%, 8%);
|
||||
--fg: #98a3ad;
|
||||
|
||||
--sidebar-bg: #292c2f;
|
||||
--sidebar-fg: #a1adb8;
|
||||
--sidebar-non-existant: #505254;
|
||||
--sidebar-active: #3473ad;
|
||||
--sidebar-spacer: #393939;
|
||||
|
||||
--scrollbar: var(--sidebar-fg);
|
||||
|
||||
--icons: #43484d;
|
||||
--icons-hover: #b3c0cc;
|
||||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #c5c8c6;
|
||||
|
||||
--theme-popup-bg: #141617;
|
||||
--theme-popup-border: #43484d;
|
||||
--theme-hover: #1f2124;
|
||||
|
||||
--quote-bg: hsl(234, 21%, 18%);
|
||||
--quote-border: hsl(234, 21%, 23%);
|
||||
|
||||
--table-border-color: hsl(200, 7%, 13%);
|
||||
--table-header-bg: hsl(200, 7%, 28%);
|
||||
--table-alternate-bg: hsl(200, 7%, 11%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
--searchbar-bg: #b7b7b7;
|
||||
--searchbar-fg: #000;
|
||||
--searchbar-shadow-color: #aaa;
|
||||
--searchresults-header-fg: #666;
|
||||
--searchresults-border-color: #98a3ad;
|
||||
--searchresults-li-bg: #2b2b2f;
|
||||
--search-mark-bg: #355c7d;
|
||||
|
||||
--color-scheme: dark;
|
||||
}
|
||||
|
||||
.light {
|
||||
--bg: hsl(0, 0%, 100%);
|
||||
--fg: hsl(0, 0%, 0%);
|
||||
|
||||
--sidebar-bg: #fafafa;
|
||||
--sidebar-fg: hsl(0, 0%, 0%);
|
||||
--sidebar-non-existant: #aaaaaa;
|
||||
--sidebar-active: #1f1fff;
|
||||
--sidebar-spacer: #f4f4f4;
|
||||
|
||||
--scrollbar: #8F8F8F;
|
||||
|
||||
--icons: #747474;
|
||||
--icons-hover: #000000;
|
||||
|
||||
--links: #20609f;
|
||||
|
||||
--inline-code-color: #301900;
|
||||
|
||||
--theme-popup-bg: #fafafa;
|
||||
--theme-popup-border: #cccccc;
|
||||
--theme-hover: #e6e6e6;
|
||||
|
||||
--quote-bg: hsl(197, 37%, 96%);
|
||||
--quote-border: hsl(197, 37%, 91%);
|
||||
|
||||
--table-border-color: hsl(0, 0%, 95%);
|
||||
--table-header-bg: hsl(0, 0%, 80%);
|
||||
--table-alternate-bg: hsl(0, 0%, 97%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
--searchbar-bg: #fafafa;
|
||||
--searchbar-fg: #000;
|
||||
--searchbar-shadow-color: #aaa;
|
||||
--searchresults-header-fg: #666;
|
||||
--searchresults-border-color: #888;
|
||||
--searchresults-li-bg: #e4f2fe;
|
||||
--search-mark-bg: #a2cff5;
|
||||
|
||||
--color-scheme: light;
|
||||
}
|
||||
|
||||
.navy {
|
||||
--bg: hsl(226, 23%, 11%);
|
||||
--fg: #bcbdd0;
|
||||
|
||||
--sidebar-bg: #282d3f;
|
||||
--sidebar-fg: #c8c9db;
|
||||
--sidebar-non-existant: #505274;
|
||||
--sidebar-active: #2b79a2;
|
||||
--sidebar-spacer: #2d334f;
|
||||
|
||||
--scrollbar: var(--sidebar-fg);
|
||||
|
||||
--icons: #737480;
|
||||
--icons-hover: #b7b9cc;
|
||||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #c5c8c6;
|
||||
|
||||
--theme-popup-bg: #161923;
|
||||
--theme-popup-border: #737480;
|
||||
--theme-hover: #282e40;
|
||||
|
||||
--quote-bg: hsl(226, 15%, 17%);
|
||||
--quote-border: hsl(226, 15%, 22%);
|
||||
|
||||
--table-border-color: hsl(226, 23%, 16%);
|
||||
--table-header-bg: hsl(226, 23%, 31%);
|
||||
--table-alternate-bg: hsl(226, 23%, 14%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
--searchbar-bg: #aeaec6;
|
||||
--searchbar-fg: #000;
|
||||
--searchbar-shadow-color: #aaa;
|
||||
--searchresults-header-fg: #5f5f71;
|
||||
--searchresults-border-color: #5c5c68;
|
||||
--searchresults-li-bg: #242430;
|
||||
--search-mark-bg: #a2cff5;
|
||||
|
||||
--color-scheme: dark;
|
||||
}
|
||||
|
||||
.rust {
|
||||
--bg: hsl(60, 9%, 87%);
|
||||
--fg: #262625;
|
||||
|
||||
--sidebar-bg: #3b2e2a;
|
||||
--sidebar-fg: #c8c9db;
|
||||
--sidebar-non-existant: #505254;
|
||||
--sidebar-active: #e69f67;
|
||||
--sidebar-spacer: #45373a;
|
||||
|
||||
--scrollbar: var(--sidebar-fg);
|
||||
|
||||
--icons: #737480;
|
||||
--icons-hover: #262625;
|
||||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #6e6b5e;
|
||||
|
||||
--theme-popup-bg: #e1e1db;
|
||||
--theme-popup-border: #b38f6b;
|
||||
--theme-hover: #99908a;
|
||||
|
||||
--quote-bg: hsl(60, 5%, 75%);
|
||||
--quote-border: hsl(60, 5%, 70%);
|
||||
|
||||
--table-border-color: hsl(60, 9%, 82%);
|
||||
--table-header-bg: #b3a497;
|
||||
--table-alternate-bg: hsl(60, 9%, 84%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
--searchbar-bg: #fafafa;
|
||||
--searchbar-fg: #000;
|
||||
--searchbar-shadow-color: #aaa;
|
||||
--searchresults-header-fg: #666;
|
||||
--searchresults-border-color: #888;
|
||||
--searchresults-li-bg: #dec2a2;
|
||||
--search-mark-bg: #e69f67;
|
||||
|
||||
--color-scheme: light;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.light.no-js {
|
||||
--bg: hsl(200, 7%, 8%);
|
||||
--fg: #98a3ad;
|
||||
|
||||
--sidebar-bg: #292c2f;
|
||||
--sidebar-fg: #a1adb8;
|
||||
--sidebar-non-existant: #505254;
|
||||
--sidebar-active: #3473ad;
|
||||
--sidebar-spacer: #393939;
|
||||
|
||||
--scrollbar: var(--sidebar-fg);
|
||||
|
||||
--icons: #43484d;
|
||||
--icons-hover: #b3c0cc;
|
||||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #c5c8c6;
|
||||
|
||||
--theme-popup-bg: #141617;
|
||||
--theme-popup-border: #43484d;
|
||||
--theme-hover: #1f2124;
|
||||
|
||||
--quote-bg: hsl(234, 21%, 18%);
|
||||
--quote-border: hsl(234, 21%, 23%);
|
||||
|
||||
--table-border-color: hsl(200, 7%, 13%);
|
||||
--table-header-bg: hsl(200, 7%, 28%);
|
||||
--table-alternate-bg: hsl(200, 7%, 11%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
--searchbar-bg: #b7b7b7;
|
||||
--searchbar-fg: #000;
|
||||
--searchbar-shadow-color: #aaa;
|
||||
--searchresults-header-fg: #666;
|
||||
--searchresults-border-color: #98a3ad;
|
||||
--searchresults-li-bg: #2b2b2f;
|
||||
--search-mark-bg: #355c7d;
|
||||
}
|
||||
}
|
||||
3
lib/web/mdbook/template/develop.sh
Normal file
3
lib/web/mdbook/template/develop.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
set -e
|
||||
cd ${book.path_build.path}
|
||||
mdbook serve . -p 8884 -n localhost --open --dest-dir ${book.path_publish.path}
|
||||
45
lib/web/mdbook/template/echarts.min.js
vendored
Normal file
45
lib/web/mdbook/template/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user