This commit is contained in:
2025-02-06 21:09:20 +03:00
parent f4f5eb06a4
commit a66ef2e8b3
21 changed files with 738 additions and 842 deletions

View File

@@ -31,7 +31,7 @@ fn do() ! {
mut cmd := Command{
name: 'hero'
description: 'Your HERO toolset.'
version: '2.0.5'
version: '2.0.6'
}
// herocmds.cmd_run_add_flags(mut cmd)

24
examples/clients/mail.vsh Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.clients. mailclient
//remove the previous one, otherwise the env variables are not read
mailclient.config_delete(name:"test")!
// env variables which need to be set are:
// - MAIL_FROM=...
// - MAIL_PASSWORD=...
// - MAIL_PORT=465
// - MAIL_SERVER=...
// - MAIL_USERNAME=...
mut client:= mailclient.get(name:"test")!
println(client)
client.send(subject:'this is a test',to:'kristof@incubaid.com',body:'
this is my email content
')!

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.data.encoderhero
import freeflowuniverse.herolib.core.base
import time
struct Person {
mut:
name string
age int = 20
birthday time.Time
}
mut person := Person{
name: 'Bob'
birthday: time.now()
}
heroscript := encoderhero.encode[Person](person)!
println(heroscript)
person2 := encoderhero.decode[Person](heroscript)!
println(person2)
//show that it doesn't matter which action & method is used
heroscript2:="!!a.b name:Bob age:20 birthday:'2025-02-06 09:57:30'"
person3 := encoderhero.decode[Person](heroscript)!
println(person3)

View File

@@ -1,9 +1,28 @@
#!/usr/bin/env -S v -n -w -cg -d use_openssl -enable-globals run
import freeflowuniverse.herolib.clients.postgresql_client
import freeflowuniverse.herolib.data.location
// Configure PostgreSQL client
heroscript := "
!!postgresql_client.configure
name:'test'
user: 'postgres'
port: 5432
host: 'localhost'
password: '1234'
dbname: 'postgres'
"
// Process the heroscript configuration
postgresql_client.play(heroscript: heroscript)!
// Get the configured client
mut db_client := postgresql_client.get(name: "test")!
// Create a new location instance
mut loc := location.new(false) or { panic(err) }
mut loc := location.new(mut db_client, false) or { panic(err) }
println('Location database initialized')
// Initialize the database (downloads and imports data)

View File

@@ -2,33 +2,14 @@
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
// First of all, we need to set the gitea configuration
// heroscript := "
// !!gitea.configure
// name:'default'
// version:'1.22.6'
// path: '/var/lib/git'
// passwd: '12345678'
// postgresql_name: 'default'
// mail_from: 'git@meet.tf'
// smtp_addr: 'smtp-relay.brevo.com'
// smtp_login: 'admin'
// smtp_port: 587
// smtp_passwd: '12345678'
// domain: 'meet.tf'
// jwt_secret: ''
// lfs_jwt_secret: ''
// internal_token: ''
// secret_key: ''
// "
// gitea_installer.play(
// name: 'default'
// heroscript: heroscript
// )!
mut installer:= gitea_installer.get(name:'test')!
// Then we need to get an instace of the installer and call the install
mut gitea := gitea_installer.get()!
// println('gitea configs: ${gitea}')
gitea.install()!
gitea.start()!
//if you want to configure using heroscript
gitea_installer.play(heroscript:"
!!gitea.configure name:test
passwd:'something'
domain: 'docs.info.com'
")!
installer.start()!

View File

@@ -17,6 +17,20 @@ else
exit 1
fi
# Check for existing hero installations
existing_hero=$(which hero 2>/dev/null || true)
if [ ! -z "$existing_hero" ]; then
echo "Found existing hero installation at: $existing_hero"
if [ -w "$(dirname "$existing_hero")" ]; then
echo "Removing existing hero installation..."
rm "$existing_hero" || { echo "Error: Failed to remove existing hero binary at $existing_hero"; exit 1; }
else
echo "Error: Cannot remove existing hero installation at $existing_hero (permission denied)"
echo "Please remove it manually with sudo and run this script again"
exit 1
fi
fi
if [[ "${OSNAME}" == "darwin"* ]]; then
# Check if /usr/local/bin/hero exists and remove it
if [ -f /usr/local/bin/hero ]; then

View File

@@ -1,107 +0,0 @@
module mailclient
import freeflowuniverse.herolib.core.base
// import freeflowuniverse.herolib.core.playbook
// __global (
// mailclient_global map[string]&MailClient
// mailclient_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 = mailclient_default
// }
// if args.name == '' {
// args.name = 'default'
// }
// return args
// }
// pub fn get(args_ ArgsGet) !&MailClient {
// mut args := args_get(args_)
// if args.name !in mailclient_global {
// if !config_exists() {
// if default {
// config_save()!
// }
// }
// config_load()!
// }
// return mailclient_global[args.name] or { panic('bug') }
// }
// // switch instance to be used for mailclient
// pub fn switch(name string) {
// mailclient_default = name
// }
fn config_exists(args_ ArgsGet) bool {
mut args := args_get(args_)
mut context := base.context() or { panic('bug') }
return context.hero_config_exists('mailclient', args.name)
}
// fn config_load(args_ ArgsGet) ! {
// mut args := args_get(args_)
// mut context := base.context()!
// mut heroscript := context.hero_config_get('mailclient', args.name)!
// play(heroscript: heroscript)!
// }
// fn config_save(args_ ArgsGet) ! {
// mut args := args_get(args_)
// mut context := base.context()!
// context.hero_config_set('mailclient', args.name, heroscript_default())!
// }
// fn set(o MailClient) ! {
// mut o2 := obj_init(o)!
// mailclient_global['default'] = &o2
// }
// @[params]
// pub struct InstallPlayArgs {
// 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_ InstallPlayArgs) ! {
// mut args := args_
// println('debguzo1')
// mut plbook := args.plbook or {
// println('debguzo2')
// heroscript := if args.heroscript == '' {
// heroscript_default()
// } else {
// args.heroscript
// }
// playbook.new(text: heroscript)!
// }
// mut install_actions := plbook.find(filter: 'mailclient.configure')!
// println('debguzo3 ${install_actions}')
// if install_actions.len > 0 {
// for install_action in install_actions {
// mut p := install_action.params
// cfg_play(p)!
// }
// }
// }

View File

@@ -1,103 +1,127 @@
module mailclient
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.data.encoderhero
__global (
mailclient_global map[string]&MailClient
mailclient_default string
mailclient_global map[string]&MailClient
mailclient_default string
)
/////////FACTORY
@[params]
pub struct ArgsGet {
pub struct ArgsGet{
pub mut:
name string
name string
}
fn args_get(args_ ArgsGet) ArgsGet {
mut model := args_
if model.name == '' {
model.name = mailclient_default
}
if model.name == '' {
model.name = 'default'
}
return model
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = mailclient_default
}
if args.name == ""{
args.name = "default"
}
return args
}
pub fn get(args_ ArgsGet) !&MailClient {
mut args := args_get(args_)
if args.name !in mailclient_global {
if args.name == 'default' {
if !config_exists(args) {
if default {
mut context := base.context() or { panic('bug') }
context.hero_config_set('mailclient', args.name, heroscript_default())!
}
}
load(args)!
}
}
return mailclient_global[args.name] or {
println(mailclient_global)
panic('could not get config for ${args.name} with name:${args.name}')
}
pub fn get(args_ ArgsGet) !&MailClient {
mut args := args_get(args_)
if !(args.name in mailclient_global) {
if ! config_exists(args){
config_save(args)!
}
config_load(args)!
}
return mailclient_global[args.name] or {
println(mailclient_global)
//bug if we get here because should be in globals
panic("could not get config for mailclient with name, is bug:${args.name}")
}
}
// set the model in mem and the config on the filesystem
pub fn set(o MailClient) ! {
mut o2 := obj_init(o)!
mailclient_global[o.name] = &o2
mailclient_default = o.name
pub fn config_exists(args_ ArgsGet) bool {
mut args := args_get(args_)
mut context:=base.context() or { panic("bug") }
return context.hero_config_exists("mailclient",args.name)
}
// check we find the config on the filesystem
pub fn exists(args_ ArgsGet) bool {
mut model := args_get(args_)
mut context := base.context() or { panic('bug') }
return context.hero_config_exists('mailclient', model.name)
pub fn config_load(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
mut heroscript := context.hero_config_get("mailclient",args.name)!
play(heroscript:heroscript)!
}
// load the config error if it doesn't exist
pub fn load(args_ ArgsGet) ! {
mut model := args_get(args_)
mut context := base.context()!
mut heroscript := context.hero_config_get('mailclient', model.name)!
play(heroscript: heroscript)!
pub fn config_save(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_set("mailclient",args.name,heroscript_default(instance:args.name)!)!
}
pub fn config_delete(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("mailclient",args.name)!
}
fn set(o MailClient)! {
mut o2:=obj_init(o)!
mailclient_global[o.name] = &o2
mailclient_default = o.name
}
// // save the config to the filesystem in the context
// pub fn save(o MailClient) ! {
// mut context := base.context()!
// heroscript := encoderhero.encode[MailClient](o)!
// context.hero_config_set('mailclient', model.name, heroscript)!
// }
@[params]
pub struct PlayArgs {
pub mut:
heroscript string // if filled in then plbook will be made out of it
plbook ?playbook.PlayBook
reset bool
heroscript string //if filled in then plbook will be made out of it
plbook ?playbook.PlayBook
reset bool
}
pub fn play(args_ PlayArgs) ! {
mut model := args_
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: 'mailclient.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
mut p := install_action.params
cfg_play(p)!
}
}
if model.heroscript == '' {
model.heroscript = heroscript_default()
}
mut plbook := model.plbook or { playbook.new(text: model.heroscript)! }
mut configure_actions := plbook.find(filter: 'mailclient.configure')!
if configure_actions.len > 0 {
for config_action in configure_actions {
mut p := config_action.params
cfg_play(p)!
}
}
}
//switch instance to be used for mailclient
pub fn switch(name string) {
mailclient_default = name
}
//helpers
@[params]
pub struct DefaultConfigArgs{
instance string = 'default'
}

View File

@@ -1,21 +1,21 @@
module mailclient
import freeflowuniverse.herolib.data.paramsparser
import os
pub const version = '1.0.0'
pub const version = '0.0.0'
const singleton = false
const default = true
pub fn heroscript_default() string {
pub fn heroscript_default(args DefaultConfigArgs) !string {
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 { '465' }).int()
mail_server := os.getenv_opt('MAIL_SERVER') or { 'smtp-relay.brevo.com' }
mail_username := os.getenv_opt('MAIL_USERNAME') or { 'kristof@incubaid.com' }
mail_username := os.getenv_opt('MAIL_USERNAME') or { 'mail@incubaid.com' }
heroscript := "
!!mailclient.configure name:'default'
!!mailclient.configure name:'${args.instance}'
mail_from: '${mail_from}'
mail_password: '${mail_password}'
mail_port: ${mail_port}
@@ -23,9 +23,10 @@ pub fn heroscript_default() string {
mail_username: '${mail_username}'
"
return heroscript
return heroscript
}
@[heap]
pub struct MailClient {
pub mut:
name string = 'default'
@@ -39,31 +40,22 @@ pub mut:
}
fn cfg_play(p paramsparser.Params) ! {
mut mycfg := MailClient{
mut mycfg := MailClient{
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', 465)!
mail_server: p.get('mail_server')!
mail_username: p.get('mail_username')!
}
set(mycfg)!
}
set(mycfg)!
}
fn obj_init(obj_ MailClient)!MailClient{
mut obj:=obj_
return obj
}
fn obj_init(obj_ MailClient) !MailClient {
// never call get here, only thing we can do here is work on object itself
mut obj := obj_
return obj
}
// user needs to us switch to make sure we get the right object
pub fn configure(config MailClient) !MailClient {
client := MailClient{
...config
}
set(client)!
return client
// THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED
// implement if steps need to be done for configuration
}

View File

@@ -1,16 +1,29 @@
# mailclient
To get started
```vlang
import freeflowuniverse.herolib.clients. mailclient
import freeflowuniverse.herolib.clients.mailclient
mut client:= mailclient.get()!
client.send(subject:'this is a test',to:'kds@something.com,kds2@else.com',body:'
//remove the previous one, otherwise the env variables are not read
mailclient.config_delete(name:"test")!
// env variables which need to be set are:
// - MAIL_FROM=...
// - MAIL_PASSWORD=...
// - MAIL_PORT=465
// - MAIL_SERVER=...
// - MAIL_USERNAME=...
mut client:= mailclient.get(name:"test")!
println(client)
client.send(subject:'this is a test',to:'kristof@incubaid.com',body:'
this is my email content
')!

View File

@@ -12,26 +12,49 @@ The PostgreSQL client can be configured using HeroScript. Configuration settings
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.core
import os
import freeflowuniverse.herolib.clients.postgresql_client
// Configure PostgreSQL client
heroscript := "
!!postgresql_client.configure
name:'test'
user: 'root'
port: 5432
host: 'localhost'
password: '1234'
dbname: 'postgres'
name:'test'
user: 'postgres'
port: 5432
host: 'localhost'
password: '1234'
dbname: 'postgres'
"
// Process the heroscript
postgresql_client.play(heroscript:heroscript)!
// Process the heroscript configuration
postgresql_client.play(heroscript: heroscript)!
// Get the configured client
mut db_client := postgresql_client.get(name:"test")!
mut db_client := postgresql_client.get(name: "test")!
// Check if test database exists, create if not
if !db_client.db_exists('test')! {
println('Creating database test...')
db_client.db_create('test')!
}
// Switch to test database
db_client.dbname = 'test'
// Create table if not exists
create_table_sql := "CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"
println('Creating table users if not exists...')
db_client.exec(create_table_sql)!
println('Database and table setup completed successfully!')
println(db_client)
```
### Configuration Parameters
@@ -94,20 +117,3 @@ db_client.backup(dest: '/path/to/backup/dir')!
Backups are created in custom PostgreSQL format (.bak files) which can be restored using pg_restore.
## Default Configuration
If no configuration is provided, the client uses these default settings:
```v
heroscript := "
!!postgresql_client.configure
name:'default'
user: 'root'
port: 5432
host: 'localhost'
password: ''
dbname: 'postgres'
"
```
You can override these defaults by providing your own configuration using the HeroScript configure command.

View File

@@ -138,6 +138,13 @@ pub fn (mut self Context) hero_config_set(cat string, name string, content_ stri
config_file.write(content)!
}
pub fn (mut self Context) hero_config_delete(cat string, name string) ! {
path := '${self.path()!.path}/${cat}__${name}.yaml'
mut config_file := pathlib.get_file(path: path)!
config_file.delete()!
}
pub fn (mut self Context) hero_config_exists(cat string, name string) bool {
path := '${os.home_dir()}/hero/context/${self.config.name}/${cat}__${name}.yaml'
return os.exists(path)

View File

@@ -1,9 +1,9 @@
module ${args.name}
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.data.paramsparser
@if args.cat == .installer
import freeflowuniverse.herolib.sysadmin.startupmanager
@@ -27,9 +27,6 @@ pub mut:
@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"
}
@@ -37,23 +34,53 @@ fn args_get (args_ ArgsGet) ArgsGet {
}
pub fn get(args_ ArgsGet) !&${args.classname} {
mut context:=base.context()!
mut args := args_get(args_)
mut obj := ${args.classname}{}
if !(args.name in ${args.name}_global) {
if args.name=="default"{
if ! config_exists(args){
if default{
config_save(args)!
}
}
config_load(args)!
}
if ! exists(args){
set(obj)!
}else{
heroscript := context.hero_config_get("${args.name}",args.name)!
mut obj:=heroscript_loads(heroscript)!
set_in_mem(obj)!
}
}
return ${args.name}_global[args.name] or {
return ${args.name}_global[args.name] or {
println(${args.name}_global)
panic("could not get config for ${args.name} with name:??{args.name}")
//bug if we get here because should be in globals
panic("could not get config for ${args.name} with name, is bug:??{args.name}")
}
}
//register the config for the future
pub fn set(o ${args.classname})! {
set_in_mem(o)!
heroscript:=heroscript_dumps(obj)!
context.hero_config_set(${args.name},args.name,heroscript)!
}
//does the config exists?
pub fn exists(args_ ArgsGet)! {
mut context:=base.context() or { panic("bug") }
return context.hero_config_exists("${args.name}",args.name)
}
pub fn delete(args_ ArgsGet)! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("${args.name}",args.name)!
if args.name in ${args.name}_global {
//del ${args.name}_global[args.name]
}
}
//only sets in mem, does not set as config
fn set_in_mem(o ${args.classname})! {
mut o2:=obj_init(o)!
${args.name}_global[o.name] = &o2
${args.name}_default = o.name
}
@else
pub fn get(args_ ArgsGet) !&${args.classname} {
@@ -61,34 +88,6 @@ pub fn get(args_ ArgsGet) !&${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:
@@ -102,9 +101,7 @@ 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)!
@@ -114,8 +111,9 @@ pub fn play(args_ PlayArgs) ! {
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
cfg_play(p)!
heroscript:=install_action.heroscript()
mut obj2:=heroscript_loads(heroscript)!
set(obj2)!
}
}
@end
@@ -161,8 +159,6 @@ pub fn play(args_ PlayArgs) ! {
}
@end
@if args.cat == .installer
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -309,3 +305,11 @@ pub fn (mut self ${args.classname}) destroy() ! {
pub fn switch(name string) {
${args.name}_default = name
}
//helpers
^^[params]
pub struct DefaultConfigArgs{
instance string = 'default'
}

View File

@@ -1,47 +1,12 @@
module ${args.name}
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.data.encoderhero
import os
pub const version = '1.14.3'
pub const version = '0.0.0'
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]
@@ -53,33 +18,11 @@ pub mut:
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
@@ -94,27 +37,16 @@ pub mut:
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
//your checking & initialization code if needed
fn obj_init(mycfg_ ${args.classname})!${args.classname}{
mut mycfg:=mycfg_
if mycfg.password == '' && mycfg.secret == '' {
return error('password or secret needs to be filled in for ??{mycfg.name}')
}
return mycfg
}
@if args.cat == .installer
@@ -135,3 +67,13 @@ fn configure() ! {
@end
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj ${args.classname}) !string {
return encoderhero.encode[${args.classname} ](obj)!
}
pub fn heroscript_loads(heroscript string) !${args.classname} {
mut obj := encoderhero.decode[${args.classname}](heroscript)!
return obj
}

View File

@@ -1,23 +1,18 @@
# hero Encoder
> encoder hero is based on json2 from https://github.com/vlang/v/blob/master/vlib/x/json2/README.md
## Usage
#### encode[T]
```v
#!/usr/bin/env -S v -n -cg -w -enable-globals run
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.data.encoderhero
import freeflowuniverse.herolib.core.base
import time
struct Person {
mut:
name string
age ?int = 20
age int = 20
birthday time.Time
deathday ?time.Time
}
mut person := Person{
@@ -26,44 +21,11 @@ mut person := Person{
}
heroscript := encoderhero.encode[Person](person)!
```
println(heroscript)
#### decode[T]
person2 := encoderhero.decode[Person](heroscript)!
```v
import freeflowuniverse.herolib.data.encoderhero
import time
struct Person {
mut:
name string
age ?int = 20
birthday time.Time
deathday ?time.Time
}
data := '
'
person := encoderhero.decode[Person](data)!
/*
struct Person {
mut:
name "Bob"
age 20
birthday "2022-03-11 13:54:25"
}
*/
println(person2)
```
## License
for all original code as used from Alexander:
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

View File

@@ -2,106 +2,61 @@ module gitea
import freeflowuniverse.herolib.osal
import freeflowuniverse.herolib.core
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.installers.base
import freeflowuniverse.herolib.installers.ulist
import freeflowuniverse.herolib.installers.db.postgresql as postgres_installer
import freeflowuniverse.herolib.installers.virt.podman as podman_installer
import freeflowuniverse.herolib.osal.zinit
import os
const postgres_container_name = 'herocontainer_postgresql'
// checks if a certain version or above is installed
fn installed() !bool {
mut podman := podman_installer.get()!
podman.install()!
// We need to check also if postgres is installed
mut result := os.execute('podman healthcheck run ${postgres_container_name}')
if result.exit_code != 0 {
return false
}
result = os.execute('gitea -v')
if result.exit_code != 0 {
res := os.execute('${osal.profile_path_source_and()!} gitea 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 gitea version.\n${res.output}")
}
if texttools.version(version) > texttools.version(r[0]) {
return false
}
} else {
return false
}
return true
}
fn install_postgres(cfg GiteaServer) ! {
postgres_heroscript := "
!!postgresql.configure
name: '${cfg.database_name}'
user: '${cfg.database_user}'
password: '${cfg.database_passwd}'
host: '${cfg.database_host}'
port: ${cfg.database_port}
volume_path:'/var/lib/postgresql/data'
container_name: '${postgres_container_name}'
"
postgres_installer.play(heroscript: postgres_heroscript)!
mut postgres := postgres_installer.get()!
postgres.install()!
postgres.start()!
}
fn install() ! {
if installed()! {
console.print_header('gitea binaraies already installed')
return
}
console.print_header('install gitea')
server := get()!
baseurl:="https://github.com/go-gitea/gitea/releases/download/v${version}/gitea-${version}"
// make sure we install base on the node
base.install()!
install_postgres(server)!
mut download_link := ''
is_linux_intel := core.is_linux_intel()!
is_osx_arm := core.is_osx_arm()!
if is_linux_intel {
download_link = 'https://dl.gitea.com/gitea/${server.version}/gitea-${server.version}-linux-amd64'
mut url := ''
if core.is_linux_arm()! {
//https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-linux-arm64.xz
url = '${baseurl}-linux-arm64.xz'
} else if core.is_linux_intel()! {
// https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-linux-amd64.xz
url = '${baseurl}-linux-amd64.xz'
} else if core.is_osx_arm()! {
//https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-darwin-10.12-arm64.xz
url = '${baseurl}-darwin-10.12-arm64.xz'
} else if core.is_osx_intel()! {
//https://github.com/go-gitea/gitea/releases/download/v1.23.2/gitea-1.23.2-darwin-10.12-amd64.xz
url = '${baseurl}-darwin-10.12-amd64.xz'
} else {
return error('unsported platform')
}
if is_osx_arm {
download_link = 'https://dl.gitea.com/gitea/${server.version}/gitea-${server.version}-darwin-10.12-amd64'
}
mut dest := osal.download(
url: url
minsize_kb: 9000
expand_dir: '/tmp/gitea'
)!
if download_link.len == 0 {
return error('unsupported platform')
}
binary := osal.download(
url: download_link
name: 'gitea'
dest: '/tmp/gitea'
) or { return error('failed to download gitea due to: ${err}') }
mut res := os.execute('sudo cp ${binary.path} /usr/local/bin/gitea')
if res.exit_code != 0 {
return error('failed to add gitea to the path due to: ${res.output}')
}
res = os.execute('sudo chmod +x /usr/local/bin/gitea')
if res.exit_code != 0 {
return error('failed to make gitea executable due to: ${res.output}')
}
// create config file
file_content := $tmpl('./templates/app.ini')
mut file := os.open_file('/etc/gitea_app.ini', 'w')!
file.write(file_content.bytes())!
console.print_header('gitea installed properly.')
mut binpath := dest.file_get('gitea')!
osal.cmd_add(
cmdname: 'gitea'
source: binpath.path
)!
}
fn build() ! {
@@ -137,65 +92,79 @@ fn ulist_get() !ulist.UList {
fn upload() ! {}
fn startupcmd() ![]zinit.ZProcessNewArgs {
mut res := []zinit.ZProcessNewArgs{}
cfg := get()!
mut cfg := get()!
res << zinit.ZProcessNewArgs{
name: 'gitea'
// cmd: 'GITEA_WORK_DIR=${cfg.path} sudo -u git /var/lib/git/gitea web -c /etc/gitea_app.ini'
cmd: '
# Variables
GITEA_USER="${cfg.run_user}"
GITEA_HOME="${cfg.path}"
GITEA_BINARY="/usr/local/bin/gitea"
GITEA_CONFIG="/etc/gitea_app.ini"
GITEA_DATA_PATH="\$GITEA_HOME/data"
GITEA_CUSTOM_PATH="\$GITEA_HOME/custom"
GITEA_LOG_PATH="\$GITEA_HOME/log"
# Ensure the script is run as root
if [[ \$EUID -ne 0 ]]; then
echo "This script must be run as root."
exit 1
fi
echo "Setting up Gitea..."
# Create Gitea user if it doesn\'t exist
if id -u "\$GITEA_USER" &>/dev/null; then
echo "User \$GITEA_USER already exists."
else
echo "Creating Gitea user..."
if ! sudo adduser --system --shell /bin/bash --group --disabled-password --home "/var/lib/\$GITEA_USER" "\$GITEA_USER"; then
echo "Failed to create user \$GITEA_USER."
exit 1
fi
fi
# Create necessary directories
echo "Creating directories..."
mkdir -p "\$GITEA_DATA_PATH" "\$GITEA_CUSTOM_PATH" "\$GITEA_LOG_PATH"
chown -R "\$GITEA_USER:\$GITEA_USER" "\$GITEA_HOME"
chmod -R 750 "\$GITEA_HOME"
chown "\$GITEA_USER:\$GITEA_USER" "\$GITEA_CONFIG"
chmod 640 "\$GITEA_CONFIG"
GITEA_WORK_DIR=\$GITEA_HOME sudo -u git gitea web -c \$GITEA_CONFIG
'
workdir: cfg.path
cmd: 'gitea server'
env: {
'HOME ': os.home_dir()
'GITEA_CONFIG ': cfg.config_path()
}
}
res << zinit.ZProcessNewArgs{
name: 'restart_gitea'
cmd: 'sleep 30 && zinit restart gitea && exit 1'
after: ['gitea']
oneshot: true
workdir: cfg.path
}
return res
// mut res := []zinit.ZProcessNewArgs{}
// cfg := get()!
// res << zinit.ZProcessNewArgs{
// name: 'gitea'
// // cmd: 'GITEA_WORK_DIR=${cfg.path} sudo -u git /var/lib/git/gitea web -c /etc/gitea_app.ini'
// cmd: '
// # Variables
// GITEA_USER="${cfg.run_user}"
// GITEA_HOME="${cfg.path}"
// GITEA_BINARY="/usr/local/bin/gitea"
// GITEA_CONFIG="/etc/gitea_app.ini"
// GITEA_DATA_PATH="\$GITEA_HOME/data"
// GITEA_CUSTOM_PATH="\$GITEA_HOME/custom"
// GITEA_LOG_PATH="\$GITEA_HOME/log"
// # Ensure the script is run as root
// if [[ \$EUID -ne 0 ]]; then
// echo "This script must be run as root."
// exit 1
// fi
// echo "Setting up Gitea..."
// # Create Gitea user if it doesn\'t exist
// if id -u "\$GITEA_USER" &>/dev/null; then
// echo "User \$GITEA_USER already exists."
// else
// echo "Creating Gitea user..."
// if ! sudo adduser --system --shell /bin/bash --group --disabled-password --home "/var/lib/\$GITEA_USER" "\$GITEA_USER"; then
// echo "Failed to create user \$GITEA_USER."
// exit 1
// fi
// fi
// # Create necessary directories
// echo "Creating directories..."
// mkdir -p "\$GITEA_DATA_PATH" "\$GITEA_CUSTOM_PATH" "\$GITEA_LOG_PATH"
// chown -R "\$GITEA_USER:\$GITEA_USER" "\$GITEA_HOME"
// chmod -R 750 "\$GITEA_HOME"
// chown "\$GITEA_USER:\$GITEA_USER" "\$GITEA_CONFIG"
// chmod 640 "\$GITEA_CONFIG"
// GITEA_WORK_DIR=\$GITEA_HOME sudo -u git gitea web -c \$GITEA_CONFIG
// '
// workdir: cfg.path
// }
// res << zinit.ZProcessNewArgs{
// name: 'restart_gitea'
// cmd: 'sleep 30 && zinit restart gitea && exit 1'
// after: ['gitea']
// oneshot: true
// workdir: cfg.path
// }
// return res
}
fn running() !bool {
//TODO: extend with proper gitea client
res := os.execute('curl -fsSL http://localhost:3000 || exit 1')
return res.exit_code == 0
}

View File

@@ -2,239 +2,287 @@ module gitea
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.sysadmin.startupmanager
import freeflowuniverse.herolib.osal.zinit
import freeflowuniverse.herolib.ui.console
import time
__global (
gitea_global map[string]&GiteaServer
gitea_default string
gitea_global map[string]&GiteaServer
gitea_default string
)
/////////FACTORY
@[params]
pub struct ArgsGet {
pub struct ArgsGet{
pub mut:
name string = 'default'
name string
}
fn args_get(args_ ArgsGet) ArgsGet {
mut args := args_
if args.name == '' {
args.name = gitea_default
}
if args.name == '' {
args.name = 'default'
}
return args
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = "default"
}
return args
}
pub fn get(args_ ArgsGet) !&GiteaServer {
mut args := args_get(args_)
if args.name !in gitea_global {
if !config_exists() {
if default {
config_save()!
}
}
config_load()!
}
return gitea_global[args.name] or {
println(gitea_global)
panic('failed to get gitea server for ${args.name}')
}
pub fn get(args_ ArgsGet) !&GiteaServer {
mut context:=base.context()!
mut args := args_get(args_)
mut obj := GiteaServer{}
if !(args.name in gitea_global) {
if ! exists(args){
set(obj)!
}else{
heroscript := context.hero_config_get("gitea",args.name)!
mut obj2:=heroscript_loads(heroscript)!
set_in_mem(obj2)!
}
}
return gitea_global[args.name] or {
println(gitea_global)
//bug if we get here because should be in globals
panic("could not get config for gitea with name, is bug:${args.name}")
}
}
fn config_exists(args_ ArgsGet) bool {
mut args := args_get(args_)
mut context := base.context() or { panic('bug') }
return context.hero_config_exists('gitea', args.name)
//register the config for the future
pub fn set(o GiteaServer)! {
set_in_mem(o)!
heroscript:=heroscript_dumps(obj)!
context.hero_config_set(gitea,args.name,heroscript)!
}
fn config_load(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context := base.context()!
mut heroscript := context.hero_config_get('gitea', args.name)!
play(heroscript: heroscript)!
//does the config exists?
pub fn exists(args_ ArgsGet)! {
mut context:=base.context() or { panic("bug") }
return context.hero_config_exists("gitea",args.name)
}
fn config_save(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context := base.context()!
context.hero_config_set('gitea', args.name, heroscript_default()!)!
pub fn delete(args_ ArgsGet)! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("gitea",args.name)!
if args.name in gitea_global {
//del gitea_global[args.name]
}
}
fn set(o GiteaServer) ! {
mut o2 := obj_init(o)!
gitea_global['default'] = &o2
//only sets in mem, does not set as config
fn set_in_mem(o GiteaServer)! {
mut o2:=obj_init(o)!
gitea_global[o.name] = &o2
gitea_default = o.name
}
@[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
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_
mut args:=args_
if args.heroscript == '' {
args.heroscript = heroscript_default()!
}
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
mut plbook := args.plbook or {
playbook.new(text: args.heroscript)!
}
mut install_actions := plbook.find(filter: 'gitea.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
heroscript:=install_action.heroscript()
mut obj:=heroscript_loads(heroscript)!
set(obj)!
}
}
mut other_actions := plbook.find(filter: 'gitea.')!
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 gitea.destroy")
destroy()!
}
if other_action.name == "install"{
console.print_debug("install action gitea.install")
install()!
}
}
if other_action.name in ["start","stop","restart"]{
mut p := other_action.params
name := p.get('name')!
mut gitea_obj:=get(name:name)!
console.print_debug("action object:\n${gitea_obj}")
if other_action.name == "start"{
console.print_debug("install action gitea.${other_action.name}")
gitea_obj.start()!
}
if other_action.name == "stop"{
console.print_debug("install action gitea.${other_action.name}")
gitea_obj.stop()!
}
if other_action.name == "restart"{
console.print_debug("install action gitea.${other_action.name}")
gitea_obj.restart()!
}
}
}
mut install_actions := plbook.find(filter: 'gitea.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
mut p := install_action.params
cfg := cfg_play(p)!
set(cfg)!
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# 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()!
}
}
// 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
//load from disk and make sure is properly intialized
pub fn (mut self GiteaServer) reload() ! {
switch(self.name)
self = obj_init(self)!
switch(self.name)
self=obj_init(self)!
}
pub fn (mut self GiteaServer) start() ! {
switch(self.name)
if self.running()! {
return
}
switch(self.name)
if self.running()!{
return
}
console.print_header('gitea start')
console.print_header('gitea start')
if !installed()! {
install()!
}
if ! installed()!{
install()!
}
configure()!
configure()!
start_pre()!
start_pre()!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
console.print_debug('starting gitea with ${zprocess.startuptype}...')
console.print_debug('starting gitea with ${zprocess.startuptype}...')
sm.new(zprocess)!
sm.new(zprocess)!
sm.start(zprocess.name)!
}
sm.start(zprocess.name)!
}
start_post()!
start_post()!
for _ in 0 .. 50 {
if self.running()! {
return
}
time.sleep(100 * time.millisecond)
}
return error('gitea did not install properly.')
for _ in 0 .. 50 {
if self.running()! {
return
}
time.sleep(100 * time.millisecond)
}
return error('cannot start gitea')
}
pub fn (mut self GiteaServer) install_start(args InstallArgs) ! {
switch(self.name)
self.install(args)!
self.start()!
switch(self.name)
self.install(args)!
self.start()!
}
pub fn (mut self GiteaServer) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
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 GiteaServer) restart() ! {
switch(self.name)
self.stop()!
self.start()!
switch(self.name)
self.stop()!
self.start()!
}
pub fn (mut self GiteaServer) running() !bool {
switch(self.name)
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()!
//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 struct InstallArgs{
pub mut:
reset bool
reset bool
}
pub fn (mut self GiteaServer) install(args InstallArgs) ! {
switch(self.name)
if args.reset || (!installed()!) {
install()!
}
switch(self.name)
if args.reset || (!installed()!) {
install()!
}
}
pub fn (mut self GiteaServer) build() ! {
switch(self.name)
build()!
switch(self.name)
build()!
}
pub fn (mut self GiteaServer) destroy() ! {
switch(self.name)
self.stop() or {}
destroy()!
switch(self.name)
self.stop() or {}
destroy()!
}
// switch instance to be used for gitea
//switch instance to be used for gitea
pub fn switch(name string) {
gitea_default = name
gitea_default = name
}
//helpers
@[params]
pub struct DefaultConfigArgs{
instance string = 'default'
}

View File

@@ -1,117 +1,93 @@
module gitea
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.osal.zinit
import freeflowuniverse.herolib.data.encoderhero
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.ui.console
import os
import freeflowuniverse.herolib.clients.mailclient
import freeflowuniverse.herolib.clients.postgresql_client
import rand
pub const version = '0.0.0'
const singleton = true
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 := "
!!gitea.configure
name:'gitea'
version:'1.22.6'
run_user: 'git'
path: '/var/lib/git'
passwd: '12345678'
postgresql_name: 'default'
mail_from: 'git@meet.tf'
smtp_addr: 'smtp-relay.brevo.com'
smtp_login: 'admin'
smtp_port: 587
smtp_passwd: '12345678'
domain: 'meet.tf'
jwt_secret: ''
lfs_jwt_secret: ''
internal_token: ''
secret_key: ''
database_passwd: 'postgres'
database_name: 'postgres'
database_user: 'postgres'
database_host: 'localhost'
database_port: 5432
"
return heroscript
}
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
const default = false
@[heap]
pub struct GiteaServer {
pub mut:
name string = 'default'
// reset bool
version string = '1.22.6'
run_user string = 'git'
path string = '/var/lib/git'
name string = 'default'
path string = '${os.home_dir()}/hero/var/gitea'
passwd string
mail_from string = 'git@meet.tf'
smtp_addr string = 'smtp-relay.brevo.com'
smtp_login string @[required]
smtp_port int = 587
smtp_passwd string
domain string @[required]
jwt_secret string
jwt_secret string = rand.hex(12)
lfs_jwt_secret string
internal_token string
secret_key string
// Database config
database_passwd string = 'postgres'
database_name string = 'postgres'
database_user string = 'postgres'
database_host string = 'localhost'
database_port int = 5432
process ?zinit.ZProcess
path_config pathlib.Path
postgresql_client_name string = "default"
mail_client_name string = "default"
}
fn cfg_play(p paramsparser.Params) !GiteaServer {
// THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above
mut mycfg := GiteaServer{
name: p.get_default('name', 'default')!
version: p.get_default('version', '1.22.6')!
run_user: p.get_default('run_user', 'git')!
path: p.get_default('path', '/var/lib/git')!
passwd: p.get('passwd')!
mail_from: p.get_default('mail_from', 'git@meet.tf')!
smtp_addr: p.get_default('smtp_addr', 'smtp-relay.brevo.com')!
smtp_login: p.get('smtp_login')!
smtp_port: p.get_int_default('smtp_port', 587)!
smtp_passwd: p.get('smtp_passwd')!
domain: p.get('domain')!
jwt_secret: p.get('jwt_secret')!
lfs_jwt_secret: p.get('lfs_jwt_secret')!
internal_token: p.get('internal_token')!
secret_key: p.get('secret_key')!
// Set database config
database_passwd: p.get_default('database_passwd', 'postgres')!
database_name: p.get_default('database_name', 'postgres')!
database_user: p.get_default('database_user', 'postgres')!
database_host: p.get_default('database_host', 'localhost')!
database_port: p.get_int_default('database_port', 5432)!
pub fn (obj GiteaServer) config_path() string {
return '${obj.path}/config.ini'
}
//your checking & initialization code if needed
fn obj_init(mycfg_ GiteaServer)!GiteaServer{
mut mycfg:=mycfg_
return mycfg
}
//called before start if done
fn configure() ! {
mut server := get()!
if ! osal.exists("gitea") {
return error('gitea binary not found in path. Please install gitea first.')
}
// Generate and set any missing secrets
if server.lfs_jwt_secret == '' {
server.lfs_jwt_secret = os.execute_opt('gitea generate secret LFS_JWT_SECRET')!.output.trim()
set(server)!
}
if server.internal_token == '' {
server.internal_token = os.execute_opt('gitea generate secret INTERNAL_TOKEN')!.output.trim()
set(server)!
}
if server.secret_key == '' {
server.secret_key = os.execute_opt('gitea generate secret SECRET_KEY')!.output.trim()
set(server)!
}
return mycfg
// Initialize required clients with detailed error handling
mut db_client := postgresql_client.get(name: server.postgresql_client_name) or {
return error('Failed to initialize PostgreSQL client "${server.postgresql_client_name}": ${err}')
}
mut mail_client := mailclient.get(name: server.mail_client_name) or {
return error('Failed to initialize mail client "${server.mail_client_name}": ${err}')
}
//TODO: check database exists
if !db_client.db_exists('gitea_${server.name}')! {
console.print_header('Creating database gitea_${server.name} for gitea.')
db_client.db_create('gitea_${server.name}')!
}
db_client.dbname = 'gitea_${server.name}'
mut mycode := $tmpl('templates/app.ini')
mut path := pathlib.get_file(path: server.config_path(), create: true)!
path.write(mycode)!
console.print_debug(mycode)
}
fn obj_init(obj_ GiteaServer) !GiteaServer {
// never call get here, only thing we can do here is work on object itself
mut obj := obj_
return obj
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj GiteaServer) !string {
return encoderhero.encode[GiteaServer ](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)
pub fn heroscript_loads(heroscript string) !GiteaServer {
mut obj := encoderhero.decode[GiteaServer](heroscript)!
return obj
}

View File

@@ -6,31 +6,24 @@ To get started
```vlang
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
import freeflowuniverse.herolib.installers.something. gitea
mut installer:= gitea.get()!
//if you want to configure using heroscript
gitea_installer.play(heroscript:'
!!gitea.configure name:test
passwd:'something'
domain: 'docs.info.com'
')!
mut installer:= gitea_installer.get(name:'test')!
installer.start()!
```
## example heroscript
```hero
!!gitea.install
homedir: '/home/user/gitea'
username: 'admin'
password: 'secretpassword'
title: 'Some Title'
host: 'localhost'
port: 8888
```
this will look for a configured mail & postgresql client both on instance name: "default", change in heroscript if needed
- postgresql_client_name = "default"
- mail_client_name = "default"

View File

@@ -1,6 +1,6 @@
APP_NAME = ${server.name}
RUN_MODE = prod
RUN_USER = ${server.run_user}
WORK_PATH = ${server.path}
[repository]
@@ -26,12 +26,12 @@ LFS_JWT_SECRET = ${server.lfs_jwt_secret}
OFFLINE_MODE = false
[database]
PATH = ${server.path}/gitea.db
PATH = /tmp/gitea.db
DB_TYPE = postgres
HOST = ${server.database_host}:${server.database_port}
NAME = ${server.database_name}
USER = ${server.database_user}
PASSWD = ${server.database_passwd}
HOST = ${db_client.host}:${db_client.port}
NAME = ${db_client.dbname}
USER = ${db_client.user}
PASSWD = ${db_client.password}
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
@@ -80,12 +80,12 @@ PATH = ${server.path}/lfs
[mailer]
ENABLED = true
FROM = ${server.mail_from}
FROM = ${mail_client.from}
; PROTOCOL = smtps
SMTP_ADDR = ${server.smtp_addr}
SMTP_PORT = ${server.smtp_port}
USER = ${server.smtp_login}
PASSWD = ${server.smtp_passwd}
SMTP_ADDR = ${mail_client.server}
SMTP_PORT = ${mail_client.port}
USER = ${mail_client.username}
PASSWD = ${mail_client.password}
[openid]
ENABLE_OPENID_SIGNIN = true
@@ -105,4 +105,3 @@ JWT_SECRET = ${server.jwt_secret}
[actions]
ENABLED=true