diff --git a/examples/installers/infra/dify b/examples/installers/infra/dify new file mode 100755 index 00000000..3179e5f9 Binary files /dev/null and b/examples/installers/infra/dify differ diff --git a/examples/installers/infra/dify.vsh b/examples/installers/infra/dify.vsh new file mode 100755 index 00000000..cc298006 --- /dev/null +++ b/examples/installers/infra/dify.vsh @@ -0,0 +1,9 @@ +#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.installers.infra.dify as dify_installer + +mut dify := dify_installer.get()! + + dify.install()! + dify.start()! +// dify.destroy()! diff --git a/lib/installers/infra/dify/.heroscript b/lib/installers/infra/dify/.heroscript new file mode 100644 index 00000000..3c099ae1 --- /dev/null +++ b/lib/installers/infra/dify/.heroscript @@ -0,0 +1,11 @@ +!!hero_code.generate_installer + name: "dify" + classname: "DifyInstaller" + hasconfig: true + singleton: true + default: false + title: "" + templates: true + build: true + startupmanager: true + supported_platforms: "" diff --git a/lib/installers/infra/dify/dify_actions.v b/lib/installers/infra/dify/dify_actions.v new file mode 100644 index 00000000..2f65e498 --- /dev/null +++ b/lib/installers/infra/dify/dify_actions.v @@ -0,0 +1,159 @@ +module dify + +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.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.installers.virt.docker as docker_installer +import os + +fn startupcmd() ![]zinit.ZProcessNewArgs { + mut installer := get()! + mut res := []zinit.ZProcessNewArgs{} + mut cfg := get()! + res << zinit.ZProcessNewArgs{ + name: 'docker' + cmd: 'dockerd' + startuptype: .systemd + } + + cmd := " + echo 'zinit starting dify' + export COMPOSE_PROJECT_NAME=${cfg.project_name} + export SECRET_KEY=${cfg.secret_key} + export INIT_PASSWORD=${cfg.init_password} + cd ${cfg.path}/docker/ + docker compose --env-file ${cfg.path}/docker/.env up + " + res << zinit.ZProcessNewArgs{ + name: 'dify' + cmd: cmd + startuptype: .systemd + } + return res +} + +fn running() !bool { + mut installer := get()! + cfg := get()! + cmd := " + sleep 120 + docker ps | grep dify-web + " + res := os.execute(cmd) + return res.exit_code == 0 +} + +fn start_pre() ! { +} + +fn start_post() ! { +} + +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 { + mut cfg := get()! + mut docker := docker_installer.get()! + docker.install()! + + cmd := "docker ps | grep dify-web" + result := os.execute(cmd) + if result.exit_code != 0 { + return false + } + return true +} + +// 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: 'dify' + // source: '${gitpath}/target/x86_64-unknown-linux-musl/release/dify' + // )! +} + +fn install() ! { + mut docker := docker_installer.get()! + mut cfg := get()! + docker.install()! + cmd := " + [ -d ${cfg.path} ] || git clone https://github.com/langgenius/dify.git -b 1.4.0 ${cfg.path} + cp ${cfg.path}/docker/.env.example ${cfg.path}/docker/.env + + sudo bash -c 'cat > /etc/docker/daemon.json < 0 { + for install_action in install_actions { + heroscript := install_action.heroscript() + mut obj2 := heroscript_loads(heroscript)! + set(obj2)! + } + } + + mut other_actions := plbook.find(filter: 'dify.')! + 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 dify.destroy') + destroy()! + } + if other_action.name == 'install' { + console.print_debug('install action dify.install') + install()! + } + } + if other_action.name in ['start', 'stop', 'restart'] { + mut p := other_action.params + name := p.get('name')! + mut dify_obj := get(name: name)! + console.print_debug('action object:\n${dify_obj}') + if other_action.name == 'start' { + console.print_debug('install action dify.${other_action.name}') + dify_obj.start()! + } + + if other_action.name == 'stop' { + console.print_debug('install action dify.${other_action.name}') + dify_obj.stop()! + } + if other_action.name == 'restart' { + console.print_debug('install action dify.${other_action.name}') + dify_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 DifyInstaller) reload() ! { + switch(self.name) + self = obj_init(self)! +} + +pub fn (mut self DifyInstaller) start() ! { + switch(self.name) + if self.running()! { + return + } + + console.print_header('dify start') + + if !installed()! { + install()! + } + + configure()! + + start_pre()! + + for zprocess in startupcmd()! { + mut sm := startupmanager_get(zprocess.startuptype)! + + console.print_debug('starting dify 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('dify did not install properly.') +} + +pub fn (mut self DifyInstaller) install_start(args InstallArgs) ! { + switch(self.name) + self.install(args)! + self.start()! +} + +pub fn (mut self DifyInstaller) 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 DifyInstaller) restart() ! { + switch(self.name) + self.stop()! + self.start()! +} + +pub fn (mut self DifyInstaller) 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 DifyInstaller) install(args InstallArgs) ! { + switch(self.name) + if args.reset || (!installed()!) { + install()! + } +} + +pub fn (mut self DifyInstaller) build() ! { + switch(self.name) + build()! +} + +pub fn (mut self DifyInstaller) destroy() ! { + switch(self.name) + self.stop() or {} + destroy()! +} + +// switch instance to be used for dify +pub fn switch(name string) { + dify_default = name +} + +// helpers + +@[params] +pub struct DefaultConfigArgs { + instance string = 'default' +} diff --git a/lib/installers/infra/dify/dify_model.v b/lib/installers/infra/dify/dify_model.v new file mode 100644 index 00000000..34d3ff10 --- /dev/null +++ b/lib/installers/infra/dify/dify_model.v @@ -0,0 +1,68 @@ +module dify + +import freeflowuniverse.herolib.data.paramsparser +import freeflowuniverse.herolib.data.encoderhero +import os +import rand + +pub const version = '0.0.0' +const singleton = true +const default = false + +// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED +@[heap] +pub struct DifyInstaller { +pub mut: + name string = 'default' + path string = '/opt/dify' + init_password string + secret_key string + project_name string = 'dify' + compose_file string = '/opt/dify/docker/docker-compose.yaml' +} + +// your checking & initialization code if needed +fn obj_init(mycfg_ DifyInstaller) !DifyInstaller { + mut mycfg := mycfg_ + if mycfg.path == '' { + mycfg.path = '/opt/dify' + } + + if mycfg.secret_key == '' { + mycfg.secret_key = rand.hex(42) + } + + if mycfg.init_password == '' { + mycfg.init_password = 'slfjbv9NaflKsgjv' + } + + if mycfg.project_name == '' { + mycfg.project_name = 'dify' + } + + if mycfg.compose_file == '' { + mycfg.compose_file = '/opt/dify/docker/docker-compose.yaml' + } + + return mycfg +} + +// 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) +} + +/////////////NORMALLY NO NEED TO TOUCH + +pub fn heroscript_dumps(obj DifyInstaller) !string { + return encoderhero.encode[DifyInstaller](obj)! +} + +pub fn heroscript_loads(heroscript string) !DifyInstaller { + mut obj := encoderhero.decode[DifyInstaller](heroscript)! + return obj +} diff --git a/lib/installers/infra/dify/readme.md b/lib/installers/infra/dify/readme.md new file mode 100644 index 00000000..e1cd7691 --- /dev/null +++ b/lib/installers/infra/dify/readme.md @@ -0,0 +1,44 @@ +# dify + +dify + +To get started + +```vlang + + +import freeflowuniverse.herolib.installers.something.dify as dify_installer + +heroscript:=" +!!dify.configure name:'test' + password: '1234' + port: 7701 + +!!dify.start name:'test' reset:1 +" + +dify_installer.play(heroscript=heroscript)! + +//or we can call the default and do a start with reset +//mut installer:= dify_installer.get()! +//installer.start(reset:true)! + + + + +``` + +## example heroscript + +```hero +!!dify.configure + homedir: '/home/user/dify' + username: 'admin' + password: 'secretpassword' + title: 'Some Title' + host: 'localhost' + port: 8888 + +``` + + diff --git a/lib/installers/infra/dify/templates/atemplate.yaml b/lib/installers/infra/dify/templates/atemplate.yaml new file mode 100644 index 00000000..a4c386dd --- /dev/null +++ b/lib/installers/infra/dify/templates/atemplate.yaml @@ -0,0 +1,5 @@ + + +name: ${cfg.configpath} + +