WIP: Building hero
- The work is still in progress Co-authored-by: supermario <mariobassem12@gmail.com>
This commit is contained in:
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
9
lib/web/mdbook/template/errors.md
Normal file
9
lib/web/mdbook/template/errors.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Errors
|
||||
|
||||
@for error in book.errors
|
||||
|
||||
## @error.cat
|
||||
|
||||
@error.msg
|
||||
|
||||
@end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user