This commit is contained in:
2025-02-09 13:32:34 +01:00
parent e20d1bdcc5
commit 7a6660ebd8
21 changed files with 1548 additions and 930 deletions

View File

@@ -1,42 +1,73 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.clients.mycelium
import freeflowuniverse.herolib.installers.net.mycelium as mycelium_installer
import freeflowuniverse.herolib.osal
import time
import os
// Check if not installed install it.
mut installer := mycelium_installer.get()!
installer.install()!
mycelium.delete()!
mut r := mycelium.inspect()!
println('My pub key: ${r.public_key}')
res := os.execute('mkdir -p /tmp/mycelium_server1 && cd /tmp/mycelium_server1 && mycelium --peers tcp://188.40.132.242:9651 quic://[2a01:4f8:212:fa6::2]:9651 tcp://185.69.166.7:9651 quic://[2a02:1802:5e:0:ec4:7aff:fe51:e36b]:9651 tcp://65.21.231.58:9651 quic://[2a01:4f9:5a:1042::2]:9651 tcp://[2604:a00:50:17b:9e6b:ff:fe1f:e054]:9651 quic://5.78.122.16:9651 tcp://[2a01:4ff:2f0:3621::1]:9651 quic://142.93.217.194:9651 --tun-name tun2 --tcp-listen-port 9652 --quic-listen-port 9653 --api-addr 127.0.0.1:9001')
println('res: ${res}')
// spawn fn () {
// res := os.execute('mkdir -p /tmp/mycelium_server1 && cd /tmp/mycelium_server1 && mycelium --peers tcp://188.40.132.242:9651 quic://[2a01:4f8:212:fa6::2]:9651 tcp://185.69.166.7:9651 quic://[2a02:1802:5e:0:ec4:7aff:fe51:e36b]:9651 tcp://65.21.231.58:9651 quic://[2a01:4f9:5a:1042::2]:9651 tcp://[2604:a00:50:17b:9e6b:ff:fe1f:e054]:9651 quic://5.78.122.16:9651 tcp://[2a01:4ff:2f0:3621::1]:9651 quic://142.93.217.194:9651 --tun-name tun2 --tcp-listen-port 9652 --quic-listen-port 9653 --api-addr 127.0.0.1:9001')
// println('res: ${res}')
// }()
mut client := mycelium.get()!
println(client)
spawn fn () {
os.execute('mkdir -p /tmp/mycelium_server2 && cd /tmp/mycelium_server2 && mycelium --peers tcp://188.40.132.242:9651 quic://[2a01:4f8:212:fa6::2]:9651 tcp://185.69.166.7:9651 quic://[2a02:1802:5e:0:ec4:7aff:fe51:e36b]:9651 tcp://65.21.231.58:9651 quic://[2a01:4f9:5a:1042::2]:9651 tcp://[2604:a00:50:17b:9e6b:ff:fe1f:e054]:9651 quic://5.78.122.16:9651 tcp://[2a01:4ff:2f0:3621::1]:9651 quic://142.93.217.194:9651 --tun-name tun3 --tcp-listen-port 9654 --quic-listen-port 9655 --api-addr 127.0.0.1:9002')
}()
// Send a message to a node by public key
// Parameters: public_key, payload, topic, wait_for_reply
msg := client.send_msg(
public_key: '0569a9c54da7a52b2ab3a2fb03f2b9be2c1c11d65d14a4888182bd12ed1dbf38' // destination public key
payload: 'Hello World' // message payload
topic: 'greetings' // optional topic
)!
time.sleep(2 * time.second)
println('Sent message ID: ${msg.id}')
println('send succeeded')
mut client1 := mycelium.get()!
client1.server_url = 'http://localhost:9001'
client1.name = 'client1'
println(client1)
// Receive messages
// Parameters: wait_for_message, peek_only, topic_filter
received := client.receive_msg(wait: true, peek: false, topic: 'greetings')!
println('Received message from: ${received.src_pk}')
println('Message payload: ${received.payload}')
mut client2 := mycelium.get()!
client2.server_url = 'http://localhost:9002'
client2.name = 'client2'
println(client2)
// Reply to a message
client.reply_msg(
id: received.id
public_key: received.src_pk
payload: 'Got your message!'
topic: 'greetings'
)!
inspect1 := mycelium.inspect(key_file_path: '/tmp/mycelium_server1/priv_key.bin')!
inspect2 := mycelium.inspect(key_file_path: '/tmp/mycelium_server2/priv_key.bin')!
// Check message status
status := client.get_msg_status(msg.id)!
println('Message status: ${status.state}')
println('Created at: ${status.created}')
println('Expires at: ${status.deadline}')
println('Server 1 public key: ${inspect1.public_key}')
println('Server 2 public key: ${inspect2.public_key}')
// // Send a message to a node by public key
// // Parameters: public_key, payload, topic, wait_for_reply
// msg := client.send_msg(
// public_key: '0569a9c54da7a52b2ab3a2fb03f2b9be2c1c11d65d14a4888182bd12ed1dbf38' // destination public key
// payload: 'Hello World' // message payload
// topic: 'greetings' // optional topic
// )!
// println('Sent message ID: ${msg.id}')
// println('send succeeded')
// // Receive messages
// // Parameters: wait_for_message, peek_only, topic_filter
// received := client.receive_msg(wait: true, peek: false, topic: 'greetings')!
// println('Received message from: ${received.src_pk}')
// println('Message payload: ${received.payload}')
// // Reply to a message
// client.reply_msg(
// id: received.id
// public_key: received.src_pk
// payload: 'Got your message!'
// topic: 'greetings'
// )!
// // Check message status
// status := client.get_msg_status(msg.id)!
// println('Message status: ${status.state}')
// println('Created at: ${status.created}')
// println('Expires at: ${status.deadline}')

View File

@@ -4,6 +4,5 @@ import freeflowuniverse.herolib.installers.infra.coredns as coredns_installer
import freeflowuniverse.herolib.osal
// coredns_installer.delete()!
mut installer:= coredns_installer.get()!
mut installer := coredns_installer.get()!
installer.build()!

View File

@@ -1,13 +1,12 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import os
import os
import freeflowuniverse.herolib.installers.web.traefik as traefik_installer
traefik_installer.delete()!
mut installer:= traefik_installer.get()!
mut installer := traefik_installer.get()!
installer.password = "planet"
installer.password = 'planet'
traefik_installer.set(installer)!
installer.start()!

View File

@@ -43,15 +43,24 @@ pub:
address string
}
pub fn inspect() !MyceliumInspectResult {
command := 'mycelium inspect --key-file /root/hero/cfg/priv_key.bin --json'
@[params]
pub struct MyceliumInspectArgs {
pub:
key_file_path string = '/root/hero/cfg/priv_key.bin'
}
pub fn inspect(args MyceliumInspectArgs) !MyceliumInspectResult {
command := 'mycelium inspect --key-file ${args.key_file_path} --json'
result := os.execute(command)
if result.exit_code != 0 {
return error('Command failed: ${result.output}')
}
inspect_result := json.decode(MyceliumInspectResult, result.output) or {
return error('Failed to parse JSON: ${err}')
}
return inspect_result
}

View File

@@ -10,11 +10,9 @@ import freeflowuniverse.herolib.osal.zinit
import freeflowuniverse.herolib.installers.ulist
import freeflowuniverse.herolib.core.httpconnection
import freeflowuniverse.herolib.installers.lang.golang
import os
fn startupcmd () ![]zinit.ZProcessNewArgs{
fn startupcmd() ![]zinit.ZProcessNewArgs {
mut args := get()!
mut res := []zinit.ZProcessNewArgs{}
cmd := "coredns -conf '${args.config_path}'"
@@ -23,7 +21,6 @@ fn startupcmd () ![]zinit.ZProcessNewArgs{
cmd: cmd
}
return res
}
fn running() !bool {
@@ -34,26 +31,22 @@ fn running() !bool {
return true
}
return false
}
fn start_pre()!{
fn start_pre() ! {
fix()!
}
fn start_post()!{
fn start_post() ! {
set_local_dns()
}
fn stop_pre()!{
fn stop_pre() ! {
}
fn stop_post()!{
fn stop_post() ! {
}
//////////////////// following actions are not specific to instance of the object
// checks if a certain version or above is installed
@@ -72,47 +65,47 @@ fn installed() !bool {
return false
}
//get the Upload List of the files
// 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
// 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
// uploads to S3 server if configured
fn upload() ! {
// installers.upload(
// cmdname: 'coredns'
// source: '${gitpath}/target/x86_64-unknown-linux-musl/release/coredns'
// )!
}
fn install() ! {
console.print_header('install coredns')
mut url := ''
if core.is_linux_arm()! {
url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_linux_arm64.tgz'
} else if core.is_linux_intel()! {
url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_linux_amd64.tgz'
} else if core.is_osx_arm()! {
url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_darwin_arm64.tgz'
} else if core.is_osx_intel()! {
url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_darwin_amd64.tgz'
} else {
return error('unsported platform')
}
build()! // because we need the plugins
// mut url := ''
// if core.is_linux_arm()! {
// url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_linux_arm64.tgz'
// } else if core.is_linux_intel()! {
// url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_linux_amd64.tgz'
// } else if core.is_osx_arm()! {
// url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_darwin_arm64.tgz'
// } else if core.is_osx_intel()! {
// url = 'https://github.com/coredns/coredns/releases/download/v${version}/coredns_${version}_darwin_amd64.tgz'
// } else {
// return error('unsported platform')
// }
mut dest := osal.download(
url: url
minsize_kb: 13000
expand_dir: '/tmp/coredns'
)!
// mut dest := osal.download(
// url: url
// minsize_kb: 13000
// expand_dir: '/tmp/coredns'
// )!
mut binpath := dest.file_get('coredns')!
osal.cmd_add(
cmdname: 'coredns'
source: binpath.path
)!
// mut binpath := dest.file_get('coredns')!
// osal.cmd_add(
// cmdname: 'coredns'
// source: binpath.path
// )!
}
fn build() ! {
@@ -121,14 +114,23 @@ fn build() ! {
if core.platform()! != .ubuntu {
return error('only support ubuntu for now')
}
mut g:=golang.get()!
mut g := golang.get()!
g.install()!
console.print_header('build coredns')
mut gs := gittools.new(coderoot: '~/code')!
mut gs := gittools.new()!
gitpath := gs.get_repo(url: url, reset: true, pull: true)!
gitpath := gs.get_path(
pull: true
reset: true
url: url
)!
// set the plugins file on right location
pluginsfile := $tmpl('templates/plugin.cfg')
mut path := pathlib.get_file(path: '${gitpath}/plugin.cfg', create: true)!
path.write(pluginsfile)!
cmd := '
cd ${gitpath}
@@ -136,18 +138,16 @@ fn build() ! {
'
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
// )!
// now copy to the default bin path
mut codedir := pathlib.get_dir(path: '${gitpath}', create: false)!
mut binpath := codedir.file_get('coredns')!
osal.cmd_add(
cmdname: 'coredns'
source: binpath.path
)!
}
fn destroy() ! {
// mut systemdfactory := systemd.new()!
// systemdfactory.destroy("zinit")!
@@ -177,7 +177,4 @@ fn destroy() ! {
// /tmp/podman
// /tmp/conmon
// ")!
}

View File

@@ -12,7 +12,6 @@ pub fn configure() ! {
set_global_dns()
if args.config_url.len > 0 {
mut repo := gs.get_repo(
url: args.config_url
@@ -42,17 +41,15 @@ pub fn configure() ! {
mut path := pathlib.get_file(path: args.config_path, create: true)!
path.write(mycorefile)!
if args.example{
example_configure() !
if args.example {
example_configure()!
}
}
pub fn example_configure() ! {
mut args := get()!
myipaddr:=osal.ipaddr_pub_get()!
myipaddr := osal.ipaddr_pub_get_check()!
exampledbfile := $tmpl('templates/ourexample.org')

View File

@@ -4,7 +4,6 @@ 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 time
@@ -17,135 +16,128 @@ __global (
/////////FACTORY
@[params]
pub struct ArgsGet{
pub struct ArgsGet {
pub mut:
name string
}
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = "default"
fn args_get(args_ ArgsGet) ArgsGet {
mut args := args_
if args.name == '' {
args.name = 'default'
}
return args
}
pub fn get(args_ ArgsGet) !&CoreDNS {
mut context:=base.context()!
mut context := base.context()!
mut args := args_get(args_)
mut obj := CoreDNS{}
if !(args.name in coredns_global) {
if ! exists(args)!{
if args.name !in coredns_global {
if !exists(args)! {
set(obj)!
}else{
heroscript := context.hero_config_get("coredns",args.name)!
mut obj_:=heroscript_loads(heroscript)!
} else {
heroscript := context.hero_config_get('coredns', args.name)!
mut obj_ := heroscript_loads(heroscript)!
set_in_mem(obj_)!
}
}
return coredns_global[args.name] or {
println(coredns_global)
//bug if we get here because should be in globals
panic("could not get config for coredns with name, is bug:${args.name}")
// bug if we get here because should be in globals
panic('could not get config for coredns with name, is bug:${args.name}')
}
}
//register the config for the future
pub fn set(o CoreDNS)! {
// register the config for the future
pub fn set(o CoreDNS) ! {
set_in_mem(o)!
mut context := base.context()!
heroscript := heroscript_dumps(o)!
context.hero_config_set("coredns", o.name, heroscript)!
context.hero_config_set('coredns', o.name, heroscript)!
}
//does the config exists?
pub fn exists(args_ ArgsGet)! bool {
// does the config exists?
pub fn exists(args_ ArgsGet) !bool {
mut context := base.context()!
mut args := args_get(args_)
return context.hero_config_exists("coredns", args.name)
return context.hero_config_exists('coredns', args.name)
}
pub fn delete(args_ ArgsGet)! {
pub fn delete(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("coredns",args.name)!
mut context := base.context()!
context.hero_config_delete('coredns', args.name)!
if args.name in coredns_global {
//del coredns_global[args.name]
// del coredns_global[args.name]
}
}
//only sets in mem, does not set as config
fn set_in_mem(o CoreDNS)! {
mut o2:=obj_init(o)!
// only sets in mem, does not set as config
fn set_in_mem(o CoreDNS) ! {
mut o2 := obj_init(o)!
coredns_global[o.name] = &o2
coredns_default = o.name
}
@[params]
pub struct PlayArgs {
pub mut:
heroscript string //if filled in then plbook will be made out of it
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_
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: 'coredns.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
heroscript:=install_action.heroscript()
mut obj2:=heroscript_loads(heroscript)!
heroscript := install_action.heroscript()
mut obj2 := heroscript_loads(heroscript)!
set(obj2)!
}
}
mut other_actions := plbook.find(filter: 'coredns.')!
for other_action in other_actions {
if other_action.name in ["destroy","install","build"]{
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 coredns.destroy")
reset := p.get_default_false('reset')
if other_action.name == 'destroy' || reset {
console.print_debug('install action coredns.destroy')
destroy()!
}
if other_action.name == "install"{
console.print_debug("install action coredns.install")
if other_action.name == 'install' {
console.print_debug('install action coredns.install')
install()!
}
}
if other_action.name in ["start","stop","restart"]{
if other_action.name in ['start', 'stop', 'restart'] {
mut p := other_action.params
name := p.get('name')!
mut coredns_obj:=get(name:name)!
console.print_debug("action object:\n${coredns_obj}")
if other_action.name == "start"{
console.print_debug("install action coredns.${other_action.name}")
mut coredns_obj := get(name: name)!
console.print_debug('action object:\n${coredns_obj}')
if other_action.name == 'start' {
console.print_debug('install action coredns.${other_action.name}')
coredns_obj.start()!
}
if other_action.name == "stop"{
console.print_debug("install action coredns.${other_action.name}")
if other_action.name == 'stop' {
console.print_debug('install action coredns.${other_action.name}')
coredns_obj.stop()!
}
if other_action.name == "restart"{
console.print_debug("install action coredns.${other_action.name}")
if other_action.name == 'restart' {
console.print_debug('install action coredns.${other_action.name}')
coredns_obj.restart()!
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -156,36 +148,37 @@ fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManag
// zinit
// tmux
// systemd
match cat{
.zinit{
console.print_debug("startupmanager: zinit")
return startupmanager.get(cat:.zinit)!
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")
.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 CoreDNS) reload() ! {
switch(self.name)
self=obj_init(self)!
self = obj_init(self)!
}
pub fn (mut self CoreDNS) start() ! {
switch(self.name)
if self.running()!{
if self.running()! {
return
}
console.print_header('coredns start')
if ! installed()!{
if !installed()! {
install()!
}
@@ -193,8 +186,8 @@ pub fn (mut self CoreDNS) start() ! {
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 coredns with ${zprocess.startuptype}...')
@@ -212,7 +205,6 @@ pub fn (mut self CoreDNS) start() ! {
time.sleep(100 * time.millisecond)
}
return error('coredns did not install properly.')
}
pub fn (mut self CoreDNS) install_start(args InstallArgs) ! {
@@ -224,8 +216,8 @@ pub fn (mut self CoreDNS) install_start(args InstallArgs) ! {
pub fn (mut self CoreDNS) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
@@ -240,11 +232,11 @@ pub fn (mut self CoreDNS) restart() ! {
pub fn (mut self CoreDNS) 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{
// 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
}
}
@@ -252,7 +244,7 @@ pub fn (mut self CoreDNS) running() !bool {
}
@[params]
pub struct InstallArgs{
pub struct InstallArgs {
pub mut:
reset bool
}
@@ -275,17 +267,14 @@ pub fn (mut self CoreDNS) destroy() ! {
destroy()!
}
//switch instance to be used for coredns
// switch instance to be used for coredns
pub fn switch(name string) {
coredns_default = name
}
//helpers
// helpers
@[params]
pub struct DefaultConfigArgs{
pub struct DefaultConfigArgs {
instance string = 'default'
}

View File

@@ -41,7 +41,7 @@ fn set_global_dns() {
console.print_debug('/etc/resolv.conf updated successfully for global.')
}
pub fn fix()! {
pub fn fix() ! {
console.print_debug('Checking if systemd-resolved is active...')
if is_systemd_resolved_active() {
disable_systemd_resolved()

View File

@@ -1,4 +1,5 @@
module coredns
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.data.encoderhero
import os
@@ -7,7 +8,7 @@ pub const version = '1.12.0'
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
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
@[heap]
pub struct CoreDNS {
pub mut:
@@ -20,20 +21,16 @@ pub mut:
example bool = true // if true we will install examples
}
//your checking & initialization code if needed
fn obj_init(mycfg_ CoreDNS)!CoreDNS{
mut mycfg:=mycfg_
// your checking & initialization code if needed
fn obj_init(mycfg_ CoreDNS) !CoreDNS {
mut mycfg := mycfg_
return mycfg
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj CoreDNS) !string {
return encoderhero.encode[CoreDNS ](obj)!
return encoderhero.encode[CoreDNS](obj)!
}
pub fn heroscript_loads(heroscript string) !CoreDNS {

View File

@@ -3,7 +3,11 @@
log
errors
health :3334
auto ${args.dnszones_path} {
reload 30s
redis {
address localhost:6379
connect_timeout 100
read_timeout 100
ttl 360
prefix dns:
}
}

View File

@@ -0,0 +1,68 @@
# Directives are registered in the order they should be executed.
#
# Ordering is VERY important. Every plugin will feel the effects of all other
# plugin below (after) them during a request, but they must not care what plugin
# above them are doing.
# How to rebuild with updated plugin configurations: Modify the list below and
# run `go generate && go build`
# The parser takes the input format of:
#
# <plugin-name>:<package-name>
# Or
# <plugin-name>:<fully-qualified-package-name>
#
# External plugin example:
#
# log:github.com/coredns/coredns/plugin/log
# Local plugin example:
# log:log
#etcd:etcd
root:root
metadata:metadata
geoip:geoip
cancel:cancel
tls:tls
timeouts:timeouts
multisocket:multisocket
reload:reload
nsid:nsid
bufsize:bufsize
bind:bind
debug:debug
trace:trace
ready:ready
health:health
pprof:pprof
prometheus:metrics
errors:errors
log:log
dnstap:dnstap
local:local
dns64:dns64
acl:acl
any:any
chaos:chaos
loadbalance:loadbalance
tsig:tsig
cache:cache
rewrite:rewrite
header:header
dnssec:dnssec
autopath:autopath
minimal:minimal
template:template
transfer:transfer
hosts:hosts
file:file
secondary:secondary
loop:loop
forward:forward
erratic:erratic
whoami:whoami
on:github.com/coredns/caddy/onevent
sign:sign
view:view
redis:github.com/codysnider/coredns-redis

View File

@@ -4,148 +4,140 @@ 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 time
__global (
mycelium_global map[string]&MyceliumInstaller
mycelium_default string
mycelium_installer_global map[string]&MyceliumInstaller
mycelium_installer_default string
)
/////////FACTORY
@[params]
pub struct ArgsGet{
pub struct ArgsGet {
pub mut:
name string
}
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = "default"
fn args_get(args_ ArgsGet) ArgsGet {
mut args := args_
if args.name == '' {
args.name = 'default'
}
return args
}
pub fn get(args_ ArgsGet) !&MyceliumInstaller {
mut context:=base.context()!
mut context := base.context()!
mut args := args_get(args_)
mut obj := MyceliumInstaller{}
if !(args.name in mycelium_global) {
if ! exists(args)!{
if args.name !in mycelium_installer_global {
if !exists(args)! {
set(obj)!
}else{
heroscript := context.hero_config_get("mycelium",args.name)!
mut obj_:=heroscript_loads(heroscript)!
} else {
heroscript := context.hero_config_get('mycelium', args.name)!
mut obj_ := heroscript_loads(heroscript)!
set_in_mem(obj_)!
}
}
return mycelium_global[args.name] or {
println(mycelium_global)
//bug if we get here because should be in globals
panic("could not get config for mycelium with name, is bug:${args.name}")
return mycelium_installer_global[args.name] or {
println(mycelium_installer_global)
// bug if we get here because should be in globals
panic('could not get config for mycelium with name, is bug:${args.name}')
}
}
//register the config for the future
pub fn set(o MyceliumInstaller)! {
// register the config for the future
pub fn set(o MyceliumInstaller) ! {
set_in_mem(o)!
mut context := base.context()!
heroscript := heroscript_dumps(o)!
context.hero_config_set("mycelium", o.name, heroscript)!
context.hero_config_set('mycelium', o.name, heroscript)!
}
//does the config exists?
pub fn exists(args_ ArgsGet)! bool {
// does the config exists?
pub fn exists(args_ ArgsGet) !bool {
mut context := base.context()!
mut args := args_get(args_)
return context.hero_config_exists("mycelium", args.name)
return context.hero_config_exists('mycelium', args.name)
}
pub fn delete(args_ ArgsGet)! {
pub fn delete(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("mycelium",args.name)!
if args.name in mycelium_global {
//del mycelium_global[args.name]
mut context := base.context()!
context.hero_config_delete('mycelium', args.name)!
if args.name in mycelium_installer_global {
// del mycelium_installer_global[args.name]
}
}
//only sets in mem, does not set as config
fn set_in_mem(o MyceliumInstaller)! {
mut o2:=obj_init(o)!
mycelium_global[o.name] = &o2
mycelium_default = o.name
// only sets in mem, does not set as config
fn set_in_mem(o MyceliumInstaller) ! {
mut o2 := obj_init(o)!
mycelium_installer_global[o.name] = &o2
mycelium_installer_default = o.name
}
@[params]
pub struct PlayArgs {
pub mut:
heroscript string //if filled in then plbook will be made out of it
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_
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: 'mycelium.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
heroscript:=install_action.heroscript()
mut obj2:=heroscript_loads(heroscript)!
heroscript := install_action.heroscript()
mut obj2 := heroscript_loads(heroscript)!
set(obj2)!
}
}
mut other_actions := plbook.find(filter: 'mycelium.')!
for other_action in other_actions {
if other_action.name in ["destroy","install","build"]{
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 mycelium.destroy")
reset := p.get_default_false('reset')
if other_action.name == 'destroy' || reset {
console.print_debug('install action mycelium.destroy')
destroy()!
}
if other_action.name == "install"{
console.print_debug("install action mycelium.install")
if other_action.name == 'install' {
console.print_debug('install action mycelium.install')
install()!
}
}
if other_action.name in ["start","stop","restart"]{
if other_action.name in ['start', 'stop', 'restart'] {
mut p := other_action.params
name := p.get('name')!
mut mycelium_obj:=get(name:name)!
console.print_debug("action object:\n${mycelium_obj}")
if other_action.name == "start"{
console.print_debug("install action mycelium.${other_action.name}")
mut mycelium_obj := get(name: name)!
console.print_debug('action object:\n${mycelium_obj}')
if other_action.name == 'start' {
console.print_debug('install action mycelium.${other_action.name}')
mycelium_obj.start()!
}
if other_action.name == "stop"{
console.print_debug("install action mycelium.${other_action.name}")
if other_action.name == 'stop' {
console.print_debug('install action mycelium.${other_action.name}')
mycelium_obj.stop()!
}
if other_action.name == "restart"{
console.print_debug("install action mycelium.${other_action.name}")
if other_action.name == 'restart' {
console.print_debug('install action mycelium.${other_action.name}')
mycelium_obj.restart()!
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -156,36 +148,37 @@ fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManag
// zinit
// tmux
// systemd
match cat{
.zinit{
console.print_debug("startupmanager: zinit")
return startupmanager.get(cat:.zinit)!
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")
.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 MyceliumInstaller) reload() ! {
switch(self.name)
self=obj_init(self)!
self = obj_init(self)!
}
pub fn (mut self MyceliumInstaller) start() ! {
switch(self.name)
if self.running()!{
if self.running()! {
return
}
console.print_header('mycelium start')
if ! installed()!{
if !installed()! {
install()!
}
@@ -193,8 +186,8 @@ pub fn (mut self MyceliumInstaller) start() ! {
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 mycelium with ${zprocess.startuptype}...')
@@ -212,7 +205,6 @@ pub fn (mut self MyceliumInstaller) start() ! {
time.sleep(100 * time.millisecond)
}
return error('mycelium did not install properly.')
}
pub fn (mut self MyceliumInstaller) install_start(args InstallArgs) ! {
@@ -224,8 +216,8 @@ pub fn (mut self MyceliumInstaller) install_start(args InstallArgs) ! {
pub fn (mut self MyceliumInstaller) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
@@ -240,11 +232,11 @@ pub fn (mut self MyceliumInstaller) restart() ! {
pub fn (mut self MyceliumInstaller) 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{
// 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
}
}
@@ -252,7 +244,7 @@ pub fn (mut self MyceliumInstaller) running() !bool {
}
@[params]
pub struct InstallArgs{
pub struct InstallArgs {
pub mut:
reset bool
}
@@ -275,17 +267,14 @@ pub fn (mut self MyceliumInstaller) destroy() ! {
destroy()!
}
//switch instance to be used for mycelium
// switch instance to be used for mycelium
pub fn switch(name string) {
mycelium_default = name
mycelium_installer_default = name
}
//helpers
// helpers
@[params]
pub struct DefaultConfigArgs{
pub struct DefaultConfigArgs {
instance string = 'default'
}

View File

@@ -5,8 +5,6 @@ import crypto.bcrypt
// generate_htpasswd creates an Apache-style htpasswd entry for the given user and password
// using bcrypt hashing with configurable cost (default 12)
fn generate_htpasswd(user string, password string) !string {
// Generate bcrypt hash
hashed_password := bcrypt.generate_from_password(password.bytes(), 12) or {
return error('Failed to hash password: ${err}')

View File

@@ -3,15 +3,12 @@ module traefik
import freeflowuniverse.herolib.osal
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core
import freeflowuniverse.herolib.osal.zinit
import freeflowuniverse.herolib.installers.ulist
import os
fn startupcmd () ![]zinit.ZProcessNewArgs{
fn startupcmd() ![]zinit.ZProcessNewArgs {
mut installer := get()!
mut res := []zinit.ZProcessNewArgs{}
res << zinit.ZProcessNewArgs{
@@ -20,11 +17,10 @@ fn startupcmd () ![]zinit.ZProcessNewArgs{
}
return res
}
fn running() !bool {
cmd:="traefik healthcheck"
cmd := 'traefik healthcheck'
res := os.execute(cmd)
if res.exit_code != 0 {
return false
@@ -32,23 +28,18 @@ fn running() !bool {
return true
}
fn start_pre()!{
fn start_pre() ! {
}
fn start_post()!{
fn start_post() ! {
}
fn stop_pre()!{
fn stop_pre() ! {
}
fn stop_post()!{
fn stop_post() ! {
}
//////////////////// following actions are not specific to instance of the object
// checks if a certain version or above is installed
@@ -57,17 +48,17 @@ fn installed() !bool {
if res.exit_code != 0 {
return false
}
r := res.output.split_into_lines().filter(it.contains("Version"))
r := res.output.split_into_lines().filter(it.contains('Version'))
if r.len != 1 {
return error("couldn't parse traefik version.\n${res.output}")
}
if texttools.version(version) == texttools.version(r[0].all_after("Version:")) {
if texttools.version(version) == texttools.version(r[0].all_after('Version:')) {
return true
}
return false
}
//get the Upload List of the files
// get the Upload List of the files
fn ulist_get() !ulist.UList {
return ulist.UList{}
}
@@ -77,7 +68,6 @@ fn upload() ! {
// cmdname: 'traefik'
// source: '${gitpath}/target/x86_64-unknown-linux-musl/release/traefik'
// )!
}
fn install() ! {
@@ -108,20 +98,15 @@ fn install() ! {
)!
}
fn destroy() ! {
osal.process_kill_recursive(name:'traefik')!
osal.process_kill_recursive(name: 'traefik')!
osal.cmd_delete('traefik')!
osal.package_remove('
traefik
')!
osal.rm("
osal.rm('
traefik
")!
')!
}

View File

@@ -4,7 +4,6 @@ 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 time
@@ -17,135 +16,128 @@ __global (
/////////FACTORY
@[params]
pub struct ArgsGet{
pub struct ArgsGet {
pub mut:
name string
}
fn args_get (args_ ArgsGet) ArgsGet {
mut args:=args_
if args.name == ""{
args.name = "default"
fn args_get(args_ ArgsGet) ArgsGet {
mut args := args_
if args.name == '' {
args.name = 'default'
}
return args
}
pub fn get(args_ ArgsGet) !&TraefikServer {
mut context:=base.context()!
mut context := base.context()!
mut args := args_get(args_)
mut obj := TraefikServer{}
if !(args.name in traefik_global) {
if ! exists(args)!{
if args.name !in traefik_global {
if !exists(args)! {
set(obj)!
}else{
heroscript := context.hero_config_get("traefik",args.name)!
mut obj_:=heroscript_loads(heroscript)!
} else {
heroscript := context.hero_config_get('traefik', args.name)!
mut obj_ := heroscript_loads(heroscript)!
set_in_mem(obj_)!
}
}
return traefik_global[args.name] or {
println(traefik_global)
//bug if we get here because should be in globals
panic("could not get config for traefik with name, is bug:${args.name}")
// bug if we get here because should be in globals
panic('could not get config for traefik with name, is bug:${args.name}')
}
}
//register the config for the future
pub fn set(o TraefikServer)! {
// register the config for the future
pub fn set(o TraefikServer) ! {
set_in_mem(o)!
mut context := base.context()!
heroscript := heroscript_dumps(o)!
context.hero_config_set("traefik", o.name, heroscript)!
context.hero_config_set('traefik', o.name, heroscript)!
}
//does the config exists?
pub fn exists(args_ ArgsGet)! bool {
// does the config exists?
pub fn exists(args_ ArgsGet) !bool {
mut context := base.context()!
mut args := args_get(args_)
return context.hero_config_exists("traefik", args.name)
return context.hero_config_exists('traefik', args.name)
}
pub fn delete(args_ ArgsGet)! {
pub fn delete(args_ ArgsGet) ! {
mut args := args_get(args_)
mut context:=base.context()!
context.hero_config_delete("traefik",args.name)!
mut context := base.context()!
context.hero_config_delete('traefik', args.name)!
if args.name in traefik_global {
//del traefik_global[args.name]
// del traefik_global[args.name]
}
}
//only sets in mem, does not set as config
fn set_in_mem(o TraefikServer)! {
mut o2:=obj_init(o)!
// only sets in mem, does not set as config
fn set_in_mem(o TraefikServer) ! {
mut o2 := obj_init(o)!
traefik_global[o.name] = &o2
traefik_default = o.name
}
@[params]
pub struct PlayArgs {
pub mut:
heroscript string //if filled in then plbook will be made out of it
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_
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: 'traefik.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
heroscript:=install_action.heroscript()
mut obj2:=heroscript_loads(heroscript)!
heroscript := install_action.heroscript()
mut obj2 := heroscript_loads(heroscript)!
set(obj2)!
}
}
mut other_actions := plbook.find(filter: 'traefik.')!
for other_action in other_actions {
if other_action.name in ["destroy","install","build"]{
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 traefik.destroy")
reset := p.get_default_false('reset')
if other_action.name == 'destroy' || reset {
console.print_debug('install action traefik.destroy')
destroy()!
}
if other_action.name == "install"{
console.print_debug("install action traefik.install")
if other_action.name == 'install' {
console.print_debug('install action traefik.install')
install()!
}
}
if other_action.name in ["start","stop","restart"]{
if other_action.name in ['start', 'stop', 'restart'] {
mut p := other_action.params
name := p.get('name')!
mut traefik_obj:=get(name:name)!
console.print_debug("action object:\n${traefik_obj}")
if other_action.name == "start"{
console.print_debug("install action traefik.${other_action.name}")
mut traefik_obj := get(name: name)!
console.print_debug('action object:\n${traefik_obj}')
if other_action.name == 'start' {
console.print_debug('install action traefik.${other_action.name}')
traefik_obj.start()!
}
if other_action.name == "stop"{
console.print_debug("install action traefik.${other_action.name}")
if other_action.name == 'stop' {
console.print_debug('install action traefik.${other_action.name}')
traefik_obj.stop()!
}
if other_action.name == "restart"{
console.print_debug("install action traefik.${other_action.name}")
if other_action.name == 'restart' {
console.print_debug('install action traefik.${other_action.name}')
traefik_obj.restart()!
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -156,36 +148,37 @@ fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManag
// zinit
// tmux
// systemd
match cat{
.zinit{
console.print_debug("startupmanager: zinit")
return startupmanager.get(cat:.zinit)!
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")
.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 TraefikServer) reload() ! {
switch(self.name)
self=obj_init(self)!
self = obj_init(self)!
}
pub fn (mut self TraefikServer) start() ! {
switch(self.name)
if self.running()!{
if self.running()! {
return
}
console.print_header('traefik start')
if ! installed()!{
if !installed()! {
install()!
}
@@ -193,8 +186,8 @@ pub fn (mut self TraefikServer) start() ! {
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 traefik with ${zprocess.startuptype}...')
@@ -212,7 +205,6 @@ pub fn (mut self TraefikServer) start() ! {
time.sleep(100 * time.millisecond)
}
return error('traefik did not install properly.')
}
pub fn (mut self TraefikServer) install_start(args InstallArgs) ! {
@@ -224,8 +216,8 @@ pub fn (mut self TraefikServer) install_start(args InstallArgs) ! {
pub fn (mut self TraefikServer) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()!{
mut sm:=startupmanager_get(zprocess.startuptype)!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
@@ -240,11 +232,11 @@ pub fn (mut self TraefikServer) restart() ! {
pub fn (mut self TraefikServer) 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{
// 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
}
}
@@ -252,7 +244,7 @@ pub fn (mut self TraefikServer) running() !bool {
}
@[params]
pub struct InstallArgs{
pub struct InstallArgs {
pub mut:
reset bool
}
@@ -264,24 +256,20 @@ pub fn (mut self TraefikServer) install(args InstallArgs) ! {
}
}
pub fn (mut self TraefikServer) destroy() ! {
switch(self.name)
self.stop() or {}
destroy()!
}
//switch instance to be used for traefik
// switch instance to be used for traefik
pub fn switch(name string) {
traefik_default = name
}
//helpers
// helpers
@[params]
pub struct DefaultConfigArgs{
pub struct DefaultConfigArgs {
instance string = 'default'
}

View File

@@ -1,4 +1,5 @@
module traefik
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.data.encoderhero
import os
@@ -9,7 +10,7 @@ pub const version = '3.3.3'
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
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
@[heap]
pub struct TraefikServer {
pub mut:
@@ -23,29 +24,26 @@ pub mut:
// port int
}
//your checking & initialization code if needed
fn obj_init(mycfg_ TraefikServer)!TraefikServer{
mut mycfg:=mycfg_
// your checking & initialization code if needed
fn obj_init(mycfg_ TraefikServer) !TraefikServer {
mut mycfg := mycfg_
return mycfg
}
//called before start if done
// called before start if done
fn configure() ! {
mut installer := get()!
htaccesscode:=generate_htpasswd("admin",installer.password)!
htaccesscode := generate_htpasswd('admin', installer.password)!
mut mycode := $tmpl('templates/traefik.toml')
mut path := pathlib.get_file(path: "/etc/traefik/traefik.toml", create: true)!
mut path := pathlib.get_file(path: '/etc/traefik/traefik.toml', create: true)!
path.write(mycode)!
console.print_debug(mycode)
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_dumps(obj TraefikServer) !string {
return encoderhero.encode[TraefikServer ](obj)!
return encoderhero.encode[TraefikServer](obj)!
}
pub fn heroscript_loads(heroscript string) !TraefikServer {

View File

@@ -0,0 +1,95 @@
# CoreDNS Redis Record Management
This module provides functionality for managing DNS records in Redis for use with CoreDNS. It supports various DNS record types and provides a simple interface for adding and managing DNS records.
```v
import freeflowuniverse.herolib.lib.osal.coredns
// Create a new DNS record set
mut rs := coredns.new_dns_record_set()
// Create and populate DNS records
rs.set_soa(mbox: 'hostmaster.example.net.', ns: 'ns1.example.net.')
rs.add_srv(target: 'tcp.example.com.', port: 123)
rs.add_txt(text: 'this is a wildcard')
rs.add_mx(host: 'host1.example.net.')
rs.add_a(name: 'host1', ip: '5.5.5.5')
rs.add_aaaa(name: 'host1', ip: '2001:db8::1')
rs.add_ns(host: 'ns1.example.net.')
rs.add_ns(host: 'ns2.example.net.')
// Store records in Redis
rs.set('example.com')!
```
## Record Types
The following DNS record types are supported:
### SRV Record
```v
SRVRecord {
target string // Required: Target hostname
port int // Required: Port number
priority int // Default: 10
weight int // Default: 100
ttl int // Default: 300
}
```
### TXT Record
```v
TXTRecord {
text string // Required: Text content
ttl int // Default: 300
}
```
### MX Record
```v
MXRecord {
host string // Required: Mail server hostname
preference int // Default: 10
ttl int // Default: 300
}
```
### A Record
```v
ARecord {
name string // Required: Hostname
ip string // Required: IPv4 address
ttl int // Default: 300
}
```
### AAAA Record
```v
AAAARecord {
name string // Required: Hostname
ip string // Required: IPv6 address
ttl int // Default: 300
}
```
### NS Record
```v
NSRecord {
host string // Required: Nameserver hostname
ttl int // Default: 300
}
```
### SOA Record
```v
SOARecord {
mbox string // Required: Email address of the admin
ns string // Required: Primary nameserver
refresh int // Default: 44
retry int // Default: 55
expire int // Default: 66
minttl int // Default: 100
ttl int // Default: 300
}
```

73
lib/osal/coredns/model.v Normal file
View File

@@ -0,0 +1,73 @@
// Input parameter structs for each record type
@[params]
struct SRVRecord {
pub mut:
target string @[required]
port int @[required]
priority int = 10
weight int = 100
ttl int = 300
}
@[params]
struct TXTRecord {
pub mut:
text string @[required]
ttl int = 300
}
@[params]
struct MXRecord {
pub mut:
host string @[required]
preference int = 10
ttl int = 300
}
@[params]
struct ARecord {
pub mut:
name string @[required]
ip string @[required]
ttl int = 300
}
@[params]
struct AAAARecord {
pub mut:
name string @[required]
ip string @[required]
ttl int = 300
}
@[params]
struct NSRecord {
pub mut:
host string @[required]
ttl int = 300
}
@[params]
struct SOARecord {
pub mut:
mbox string @[required]
ns string @[required]
refresh int = 44
retry int = 55
expire int = 66
minttl int = 100
ttl int = 300
}
// DNSRecordSet represents a set of DNS records
struct DNSRecordSet {
pub mut:
srv []SRVRecord
txt []TXTRecord
mx []MXRecord
a []ARecord
aaaa []AAAARecord
ns []NSRecord
soa ?SOARecord
redis ?&redisclient.Redis
}

119
lib/osal/coredns/play.v Normal file
View File

@@ -0,0 +1,119 @@
module coredns
import freeflowuniverse.herolib.core.playbook
// play_dns processes DNS-related actions from heroscript
pub fn play_dns(mut plbook playbook.PlayBook) !DNSRecordSet {
mut recordset := new_dns_record_set()
// Find all actions starting with dns.
dns_actions := plbook.find(filter: 'dns.')!
for action in dns_actions {
mut p := action.params
match action.name {
'a_record' {
recordset.add_a(
name: p.get('name')!
ip: p.get('ip')!
ttl: p.get_int_default('ttl', 300)!
)
}
'aaaa_record' {
recordset.add_aaaa(
name: p.get('name')!
ip: p.get('ip')!
ttl: p.get_int_default('ttl', 300)!
)
}
'mx_record' {
recordset.add_mx(
host: p.get('host')!
preference: p.get_int_default('preference', 10)!
ttl: p.get_int_default('ttl', 300)!
)
}
'txt_record' {
recordset.add_txt(
text: p.get('text')!
ttl: p.get_int_default('ttl', 300)!
)
}
'srv_record' {
recordset.add_srv(
target: p.get('target')!
port: p.get_int('port')!
priority: p.get_int_default('priority', 10)!
weight: p.get_int_default('weight', 100)!
ttl: p.get_int_default('ttl', 300)!
)
}
'ns_record' {
recordset.add_ns(
host: p.get('host')!
ttl: p.get_int_default('ttl', 300)!
)
}
'soa_record' {
recordset.set_soa(
mbox: p.get('mbox')!
ns: p.get('ns')!
refresh: p.get_int_default('refresh', 44)!
retry: p.get_int_default('retry', 55)!
expire: p.get_int_default('expire', 66)!
minttl: p.get_int_default('minttl', 100)!
ttl: p.get_int_default('ttl', 300)!
)
}
else {
// Unknown action, skip
continue
}
}
}
return recordset
}
// Example usage:
/*
!!dns.a_record
name: 'host1'
ip: '1.2.3.4'
ttl: 300
!!dns.aaaa_record
name: 'host1'
ip: '2001:db8::1'
ttl: 300
!!dns.mx_record
host: 'mail.example.com'
preference: 10
ttl: 300
!!dns.txt_record
text: 'v=spf1 mx ~all'
ttl: 300
!!dns.srv_record
target: 'sip.example.com'
port: 5060
priority: 10
weight: 100
ttl: 300
!!dns.ns_record
host: 'ns1.example.com'
ttl: 300
!!dns.soa_record
mbox: 'hostmaster.example.com'
ns: 'ns1.example.com'
refresh: 44
retry: 55
expire: 66
minttl: 100
ttl: 300
*/

View File

@@ -0,0 +1,279 @@
module coredns
import json
import freeflowuniverse.herolib.core.redisclient
// Input parameter structs for each record type
@[params]
struct SRVRecord {
pub mut:
target string @[required]
port int @[required]
priority int = 10
weight int = 100
ttl int = 300
}
@[params]
struct TXTRecord {
pub mut:
text string @[required]
ttl int = 300
}
@[params]
struct MXRecord {
pub mut:
host string @[required]
preference int = 10
ttl int = 300
}
@[params]
struct ARecord {
pub mut:
name string @[required]
ip string @[required]
ttl int = 300
}
@[params]
struct AAAARecord {
pub mut:
name string @[required]
ip string @[required]
ttl int = 300
}
@[params]
struct NSRecord {
pub mut:
host string @[required]
ttl int = 300
}
@[params]
struct SOARecord {
pub mut:
mbox string @[required]
ns string @[required]
refresh int = 44
retry int = 55
expire int = 66
minttl int = 100
ttl int = 300
}
// DNSRecordSet represents a set of DNS records
struct DNSRecordSet {
pub mut:
srv []SRVRecord
txt []TXTRecord
mx []MXRecord
a []ARecord
aaaa []AAAARecord
ns []NSRecord
soa ?SOARecord
redis ?&redisclient.Redis
}
// new_dns_record_set creates a new DNSRecordSet
pub fn new_dns_record_set() DNSRecordSet {
return DNSRecordSet{
srv: []SRVRecord{}
txt: []TXTRecord{}
mx: []MXRecord{}
a: []ARecord{}
aaaa: []AAAARecord{}
ns: []NSRecord{}
}
}
// add_srv adds an SRV record to the set
pub fn (mut rs DNSRecordSet) add_srv(args SRVRecord) {
rs.srv << SRVRecord{
target: args.target
port: args.port
priority: args.priority
weight: args.weight
ttl: args.ttl
}
}
// add_txt adds a TXT record to the set
pub fn (mut rs DNSRecordSet) add_txt(args TXTRecord) {
rs.txt << TXTRecord{
text: args.text
ttl: args.ttl
}
}
// add_mx adds an MX record to the set
pub fn (mut rs DNSRecordSet) add_mx(args MXRecord) {
rs.mx << MXRecord{
host: args.host
preference: args.preference
ttl: args.ttl
}
}
// add_a adds an A record to the set
pub fn (mut rs DNSRecordSet) add_a(args ARecord) {
rs.a << ARecord{
name: args.name
ip: args.ip
ttl: args.ttl
}
}
// add_aaaa adds an AAAA record to the set
pub fn (mut rs DNSRecordSet) add_aaaa(args AAAARecord) {
rs.aaaa << AAAARecord{
name: args.name
ip: args.ip
ttl: args.ttl
}
}
// add_ns adds an NS record to the set
pub fn (mut rs DNSRecordSet) add_ns(args NSRecord) {
rs.ns << NSRecord{
host: args.host
ttl: args.ttl
}
}
// set_soa sets the SOA record for the set
pub fn (mut rs DNSRecordSet) set_soa(args SOARecord) {
rs.soa = SOARecord{
mbox: args.mbox
ns: args.ns
refresh: args.refresh
retry: args.retry
expire: args.expire
minttl: args.minttl
ttl: args.ttl
}
}
// populate_redis populates Redis with the DNS records
// domain e.g. example.com. (not sure the . is at end)
pub fn (rs DNSRecordSet) set(domain string) ! {
mut redis := rs.redis or { redisclient.core_get()! }
// Store SRV records
for srv in rs.srv {
key := '_ssh._tcp.host1'
value := json.encode({
'srv': {
'ttl': srv.ttl
'target': srv.target
'port': srv.port
'priority': srv.priority
'weight': srv.weight
}
})
redis.hset(domain, key, value)!
}
// Store TXT and MX records for wildcard
if rs.txt.len > 0 || rs.mx.len > 0 {
mut records := map[string]map[string]json.Any{}
if rs.txt.len > 0 {
records['txt'] = {
'text': rs.txt[0].text
'ttl': '${rs.txt[0].ttl}'
}
}
if rs.mx.len > 0 {
records['mx'] = {
'host': rs.mx[0].host
'priority': rs.mx[0].preference
'ttl': rs.mx[0].ttl
}
}
redis.hset(domain, '*', json.encode(records))!
}
// Store A records
for a in rs.a {
value := json.encode({
'a': {
'ip4': a.ip
'ttl': '${a.ttl}'
}
})
redis.hset(domain, a.name, value)!
}
// Store AAAA records
for aaaa in rs.aaaa {
value := json.encode({
'aaaa': {
'ip6': aaaa.ip
'ttl': aaaa.ttl
}
})
redis.hset(domain, aaaa.name, value)!
}
// Store NS records
if rs.ns.len > 0 {
mut ns_records := []map[string]json.Any{}
for ns in rs.ns {
ns_records << {
'host': ns.host
'ttl': ns.ttl
}
}
value := json.encode({
'ns': ns_records
})
redis.hset(domain, 'subdel', value)!
}
// Store SOA and root NS records at @
if soa := rs.soa {
mut root_records := map[string]json.Any{}
root_records['soa'] = {
'ttl': soa.ttl
'minttl': soa.minttl
'mbox': soa.mbox
'ns': soa.ns
'refresh': soa.refresh
'retry': soa.retry
'expire': soa.expire
}
if rs.ns.len > 0 {
mut ns_records := []map[string]json.Any{}
for ns in rs.ns {
ns_records << {
'host': ns.host
'ttl': ns.ttl
}
}
root_records['ns'] = ns_records
}
redis.hset(domain, '@', json.encode(root_records))!
}
}
pub fn (mut rs DNSRecordSet) example() ! {
// Create and populate DNS records
rs.set_soa(mbox: 'hostmaster.example.net.', ns: 'ns1.example.net.')
rs.add_srv(target: 'tcp.example.com.', port: 123)
rs.add_txt(text: 'this is a wildcard')
rs.add_mx(host: 'host1.example.net.')
rs.add_a(name: 'host1', ip: '5.5.5.5')
rs.add_aaaa(name: 'host1', ip: '2001:db8::1')
rs.add_txt(text: 'this is not a wildcard')
rs.add_ns(host: 'ns1.subdel.example.net.')
rs.add_ns(host: 'ns2.subdel.example.net.')
rs.add_ns(host: 'ns1.example.net.')
rs.add_ns(host: 'ns2.example.net.')
// Store records in Redis
rs.set('example.com')!
}

View File

@@ -107,19 +107,23 @@ pub fn ipaddr_pub_get() !string {
cmd := 'dig @resolver4.opendns.com myip.opendns.com +short'
ipaddr := exec(cmd: cmd)!
public_ip := ipaddr.output.trim('\n').trim(' \n')
return public_ip
}
//also check the address is on local interface
pub fn ipaddr_pub_get_check() !string {
// Check if the public IP matches any local interface
if ! is_ip_on_local_interface(public_ip)! {
return error ('Public IP $public_ip is NOT bound to any local interface (possibly behind a NAT firewall).')
public_ip := ipaddr_pub_get_check()!
if !is_ip_on_local_interface(public_ip)! {
return error('Public IP ${public_ip} is NOT bound to any local interface (possibly behind a NAT firewall).')
}
return public_ip
}
// Check if the public IP matches any of the local network interfaces
pub fn is_ip_on_local_interface(public_ip string) !bool {
interfaces := exec(cmd:'ip addr show',stdout:false) or {
return error ('Failed to enumerate network interfaces.')
interfaces := exec(cmd: 'ip addr show', stdout: false) or {
return error('Failed to enumerate network interfaces.')
}
lines := interfaces.output.split('\n')