This commit is contained in:
2025-08-29 09:48:44 +02:00
parent 03bb86bd72
commit ce6cf3aa9c
27 changed files with 129 additions and 144 deletions

View File

@@ -38,7 +38,6 @@ mut client := zinit.new()!
println(client)
println(' Created Zinit RPC client')
// 1. Discover API specification

View File

@@ -2,7 +2,7 @@
import freeflowuniverse.herolib.installers.infra.livekit as livekit_installer
mut livekit := livekit_installer.get(create:true)!
mut livekit := livekit_installer.get(create: true)!
livekit.install()!
livekit.start()!
livekit.destroy()!

View File

@@ -17,7 +17,7 @@ passwd := os.environ()['HETZNER_PASSWORD'] or {
exit(1)
}
hs:='
hs := '
!!hetznermanager.configure
user:"${user}"
whitelist:"2111181, 2392178, 2545053, 2542166, 2550508, 2550378,2550253"
@@ -29,7 +29,6 @@ println(hs)
playcmds.run(heroscript: hs)!
console.print_header('Hetzner Test.')
mut cl := hetznermanager.get()!
@@ -66,5 +65,4 @@ mut cl := hetznermanager.get()!
// cl.ubuntu_install(name: 'kristof20', wait: true, hero_install: true)!
// cl.ubuntu_install(id:2550378, name: 'kristof21', wait: true, hero_install: true)!
// cl.ubuntu_install(id:2550508, name: 'kristof22', wait: true, hero_install: true)!
cl.ubuntu_install(id:2550253, name:'kristof23', wait: true, hero_install: true)!
cl.ubuntu_install(id: 2550253, name: 'kristof23', wait: true, hero_install: true)!

View File

@@ -12,10 +12,10 @@ pub fn play(mut plbook playbook.PlayBook) ! {
for action in actions {
mut p := action.params
mut n := b.node_new(
name: p.get_default('name', '')!
name: p.get_default('name', '')!
ipaddr: p.get_default('ipaddr', '')!
user: p.get_default('user', 'root')!
debug: p.get_default_false('debug')
user: p.get_default('user', 'root')!
debug: p.get_default_false('debug')
reload: p.get_default_false('reload')
)!
console.print_header('Created node: ${n.name}')
@@ -31,16 +31,18 @@ pub fn play(mut plbook playbook.PlayBook) ! {
// a bit ugly but we don't have node management in a central place yet
// this will get the node created previously
// we need a better way to get the nodes, maybe from a global scope
mut found_node := &Node{factory: &b}
mut found_node := &Node{
factory: &b
}
mut found := false
nodes_to_find := plbook.find(filter: 'node.new')!
for node_action in nodes_to_find {
mut node_p := node_action.params
if node_p.get_default('name', '')! == node_name {
found_node = b.node_new(
name: node_p.get_default('name', '')!
name: node_p.get_default('name', '')!
ipaddr: node_p.get_default('ipaddr', '')!
user: node_p.get_default('user', 'root')!
user: node_p.get_default('user', 'root')!
)!
found = true
break
@@ -55,4 +57,4 @@ pub fn play(mut plbook playbook.PlayBook) ! {
result := found_node.exec_cmd(cmd: cmd)!
console.print_debug('Result:\n${result}')
}
}
}

View File

@@ -18,7 +18,7 @@ pub fn (mut c ZinitRPC) rpc_discover() !openrpc.OpenRPC {
println(1)
request := jsonrpc.new_request_generic('rpc.discover', []string{})
println(2)
mut r:= client.send[[]string, openrpc.OpenRPC](request)!
mut r := client.send[[]string, openrpc.OpenRPC](request)!
// dump(r)
$dbg;
return r

View File

@@ -10,12 +10,10 @@ import freeflowuniverse.herolib.web.docusaurus
import freeflowuniverse.herolib.clients.openai
import freeflowuniverse.herolib.clients.giteaclient
import freeflowuniverse.herolib.osal.tmux
import freeflowuniverse.herolib.installers.base
import freeflowuniverse.herolib.installers.lang.vlang
import freeflowuniverse.herolib.installers.lang.herolib
// -------------------------------------------------------------------
// run entry point for all HeroScript playcommands
// -------------------------------------------------------------------

View File

@@ -57,7 +57,7 @@ fn decode_struct[T](_ T, data string) !T {
if attr.contains('skipdecode') {
should_skip = true
break
}
}
}
if !should_skip {
$if field.is_struct {
@@ -99,8 +99,8 @@ pub fn decode_array[T](_ []T, data string) ![]T {
// for i in 0 .. val.len {
value := T{}
$if T is $struct {
//arr << decode_struct(value, data)!
}$else{
// arr << decode_struct(value, data)!
} $else {
arr << decode[T](data)!
}
// }

View File

@@ -9,7 +9,7 @@ pub fn play(mut plbook playbook.PlayBook) ! {
for mut action in plbook.find(filter: 'base.install')! {
mut p := action.params
install(
reset: p.get_default_false('reset')
reset: p.get_default_false('reset')
develop: p.get_default_false('develop')
)!
action.done = true
@@ -30,10 +30,10 @@ pub fn play(mut plbook playbook.PlayBook) ! {
for action in plbook.find(filter: 'base.redis_install')! {
mut p := action.params
redis_install(
port: p.get_int_default('port', 6379)!
port: p.get_int_default('port', 6379)!
ipaddr: p.get_default('ipaddr', 'localhost')!
reset: p.get_default_false('reset')
start: p.get_default_true('start')
reset: p.get_default_false('reset')
start: p.get_default_true('start')
)!
}
}
@@ -46,4 +46,4 @@ pub fn play(mut plbook playbook.PlayBook) ! {
// )!
// }
// }
}
}

View File

@@ -104,7 +104,7 @@ pub fn install_multi(args_ InstallArgs) ! {
}
'hero' {
herolib.install(
reset: args.reset
reset: args.reset
)!
}
// 'hero' {

View File

@@ -80,11 +80,11 @@ pub fn install(args InstallArgs) ! {
console.print_header('install hero')
base.install()!
cmd := "
cmd := '
cd /tmp
export TERM=xterm
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh | bash
"
'
osal.execute_stdout(cmd) or { return error('Cannot install hero.\n${err}') }
osal.done_set('install_hero', 'OK')!
return

View File

@@ -4,7 +4,7 @@ import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.ui.console
pub fn play(mut plbook playbook.PlayBook) ! {
if ! plbook.exists(filter: 'herolib.') {
if !plbook.exists(filter: 'herolib.') {
return
}
if plbook.exists(filter: 'herolib.uninstall') {
@@ -14,7 +14,6 @@ pub fn play(mut plbook playbook.PlayBook) ! {
action.done = true
break
}
}
if plbook.exists(filter: 'herolib.install') {
console.print_header('play herolib.install')
@@ -22,7 +21,6 @@ pub fn play(mut plbook playbook.PlayBook) ! {
mut p := action.params
install(
reset: p.get_default_false('reset')
)!
action.done = true
break
@@ -33,12 +31,12 @@ pub fn play(mut plbook playbook.PlayBook) ! {
for mut action in plbook.find(filter: 'herolib.compile')! {
mut p := action.params
compile(
reset: p.get_default_false('reset')
git_pull: p.get_default_false('git_pull')
reset: p.get_default_false('reset')
git_pull: p.get_default_false('git_pull')
git_reset: p.get_default_false('git_reset')
)!
action.done = true
break
}
}
}
}

View File

@@ -24,4 +24,4 @@ pub fn play(mut plbook playbook.PlayBook) ! {
action.done = true
}
}
}
}

View File

@@ -38,7 +38,8 @@ pub fn install(args_ InstallArgs) ! {
base.develop()!
osal.exec(cmd:'
osal.exec(
cmd: '
V_DIR="${os.home_dir()}/_code/v"
mkdir -p "${os.home_dir()}/_code"
@@ -58,7 +59,8 @@ pub fn install(args_ InstallArgs) ! {
fi
cd "\${V_DIR}"
make
')!
'
)!
mut extra := 'cd ${os.home_dir()}/_code/v'
if core.is_linux()! {
@@ -67,7 +69,7 @@ pub fn install(args_ InstallArgs) ! {
extra = '${extra}\ncp v ${os.home_dir()}/hero/bin/'
}
osal.exec(cmd: extra, stdout: true)!
console.print_header('compile done')
osal.done_set('install_vlang', 'OK')!

View File

@@ -42,7 +42,7 @@ pub fn ping(args PingArgs) !bool {
if res.exit_code > 0 {
nrerrors += 1
}
console.print_debug("${cmd} ${res.exit_code} ${nrerrors}")
console.print_debug('${cmd} ${res.exit_code} ${nrerrors}')
}
successes := args.nr_ping - nrerrors
if successes >= args.nr_ok {
@@ -233,7 +233,7 @@ fn ssh_testrun_internal(args TcpPortTestArgs) !(string, SSHResult) {
fi
echo "ERROR: Host unreachable, over ping and ssh"
exit 3
'
'
res := exec(cmd: cmd, ignore_error: true, stdout: false, debug: false)!
// console.print_debug('ssh test ${res.exit_code}: ===== cmd:\n${cmd}\n=====\n${res.output}')

View File

@@ -56,7 +56,7 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
mut scr := screen.new(reset: false)!
console.print_debug('screen startup manager ${args.name} cmd:${args.cmd}')
_ = scr.add(name: args.name, cmd: args.cmd, reset: args.restart)!
//because of how screen works the start is immediate
// because of how screen works the start is immediate
}
.systemd {
// console.print_debug('systemd start ${args.name}')
@@ -74,7 +74,7 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
// Get the Zinit RPC client instance.
// We assume it's properly configured (e.g., socket_path) via its factory setup.
mut zinit_client := zinit.get(create: true)!
// Map ZProcessNewArgs to zinit.ServiceConfig
mut service_config := zinit.ServiceConfig{
exec: args.cmd
@@ -90,16 +90,16 @@ pub fn (mut sm StartupManager) new(args ZProcessNewArgs) ! {
// Create the service configuration file in zinit
zinit_client.service_create(args.name, service_config) or {
return error('startupmanager: failed to create zinit service ${args.name}: ${err}')
}
} else {
}
}
else {
panic('to implement, startup manager only support screen & systemd for now: ${mycat}')
}
}
// If 'start' is true, also monitor and start the service
if args.start {
sm.start(args.name)!
}
}
}
pub fn (mut sm StartupManager) start(name string) ! {
@@ -129,7 +129,6 @@ pub fn (mut sm StartupManager) start(name string) ! {
zinit_client.service_monitor(name) or {
return error('startupmanager: Failed to monitor zinit service ${name}: ${err}')
}
}
else {
panic('to implement, startup manager only support screen, systemd and zinit for now')
@@ -355,7 +354,7 @@ pub fn (mut sm StartupManager) exists(name string) !bool {
}
.zinit {
console.print_debug('zinit exists ${name} using clients.zinit')
mut zinit_client := zinit.get(create:true)!
mut zinit_client := zinit.get(create: true)!
zinit_client.service_status(name) or { return false }
return true
}

View File

@@ -6,49 +6,49 @@ import freeflowuniverse.herolib.osal.core as osal
@[params]
pub struct JournalArgs {
pub:
service string // name of service for which logs will be retrieved
limit int = 100 // number of last log lines to be shown
since string // time since when to show logs (e.g., "1 hour ago", "2024-01-01")
follow bool // follow logs in real-time
priority string // log priority (emerg, alert, crit, err, warning, notice, info, debug)
grep string // filter logs containing this text
service string // name of service for which logs will be retrieved
limit int = 100 // number of last log lines to be shown
since string // time since when to show logs (e.g., "1 hour ago", "2024-01-01")
follow bool // follow logs in real-time
priority string // log priority (emerg, alert, crit, err, warning, notice, info, debug)
grep string // filter logs containing this text
}
pub fn journalctl(args JournalArgs) !string {
mut cmd_parts := ['journalctl', '--no-pager']
if args.limit > 0 {
cmd_parts << ['-n', args.limit.str()]
}
if args.service != '' {
cmd_parts << ['-u', name_fix(args.service)]
}
if args.since != '' {
cmd_parts << ['--since', '"${args.since}"']
}
if args.follow {
cmd_parts << ['-f']
}
if args.priority != '' {
cmd_parts << ['-p', args.priority]
}
cmd := cmd_parts.join(' ')
mut response := osal.execute_silent(cmd) or {
return error('Failed to get journal logs for ${args.service}: ${err}')
}
if args.grep != '' {
lines := response.split('\n')
filtered_lines := lines.filter(it.contains(args.grep))
response = filtered_lines.join('\n')
}
return response
}

View File

@@ -179,7 +179,7 @@ pub fn (mut systemd Systemd) destroy(name_ string) ! {
pub fn (mut systemd Systemd) validate_service(name string) !bool {
service := systemd.get(name)!
status := service.status()!
match status {
.active {
console.print_item(' Service ${name} is running')
@@ -200,14 +200,14 @@ pub fn (mut systemd Systemd) validate_service(name string) !bool {
// Add method to check all services
pub fn (mut systemd Systemd) health_check() !map[string]bool {
mut results := map[string]bool{}
for process in systemd.processes {
if process.name.ends_with('_test') || process.name.ends_with('testservice') {
continue // Skip test services
}
results[process.name] = systemd.validate_service(process.name) or { false }
}
return results
}

View File

@@ -43,24 +43,24 @@ pub fn (mut self SystemdProcess) write() ! {
pub fn (mut self SystemdProcess) start() ! {
console.print_header('starting systemd process: ${self.name}')
cmd := '
systemctl daemon-reload
systemctl enable ${self.name}
systemctl start ${self.name}
'
job := osal.exec(cmd: cmd, stdout: false)!
// Wait for service to start with timeout
mut attempts := 0
max_attempts := 10
wait_interval := 500 // milliseconds
for attempts < max_attempts {
time.sleep(wait_interval * time.millisecond)
status := self.status()!
match status {
.active {
console.print_header(' systemd process started successfully: ${self.name}')
@@ -81,11 +81,10 @@ pub fn (mut self SystemdProcess) start() ! {
}
}
}
// If we get here, service didn't start in time
logs := self.get_logs(50)!
return error('Service ${self.name} did not start within expected time. Status: ${self.status()!}. Recent logs:\n${logs}')
}
// get status from system
@@ -109,30 +108,30 @@ pub fn (mut self SystemdProcess) delete() ! {
pub fn (mut self SystemdProcess) stop() ! {
console.print_header('stopping systemd process: ${self.name}')
cmd := '
systemctl stop ${self.name}
systemctl disable ${self.name}
systemctl daemon-reload
'
_ = osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
// Wait for service to stop
mut attempts := 0
max_attempts := 10
for attempts < max_attempts {
time.sleep(500 * time.millisecond)
status := self.status()!
if status == .inactive {
console.print_header(' systemd process stopped: ${self.name}')
return
}
attempts++
}
console.print_header(' systemd process may still be running: ${self.name}')
}
@@ -161,11 +160,11 @@ pub fn (self SystemdProcess) get_logs(lines int) !string {
// Improve status method with better error handling
pub fn (self SystemdProcess) status() !SystemdStatus {
cmd := 'systemctl is-active ${name_fix(self.name)}'
job := osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
// console.print_debug("${cmd} \n***\n${job.output}\n***")
match job.output.trim_space() {
'active' { return .active }
'inactive' { return .inactive }
@@ -182,4 +181,3 @@ pub fn (self SystemdProcess) status_detailed() !string {
job := osal.exec(cmd: cmd, stdout: false, ignore_error: true)!
return job.output
}

View File

@@ -32,8 +32,8 @@ pub fn testsuite_end() ! {
pub fn test_systemd_process_start_stop() ! {
mut systemdfactory := new()!
mut process := systemdfactory.new(
cmd: 'redis-server'
name: 'testservice'
cmd: 'redis-server'
name: 'testservice'
start: false
)!

View File

@@ -14,7 +14,7 @@ mut:
// Returns:
// - The response string or an error if the send operation fails
send(request string, params SendParams) !string
url()string
url() string
}
// SendParams defines configuration options for sending JSON-RPC requests.
@@ -68,8 +68,8 @@ pub fn (mut c Client) send[T, D](request RequestGeneric[T], params SendParams) !
// Send the encoded request through the transport layer
console.print_debug('Sending request: \n*****\n${request.encode()}\n*****\n')
response_json := c.transport.send(request.encode(), params) or {
if err.msg().contains("net: op timed out"){
console.print_debug("time out")
if err.msg().contains('net: op timed out') {
console.print_debug('time out')
}
// print_backtrace()
// println(err)
@@ -91,15 +91,16 @@ pub fn (mut c Client) send[T, D](request RequestGeneric[T], params SendParams) !
// Return the result or propagate any error from the response
return response.result() or {
myerror := response.error_ or { return error('Failed to get error from response:\nRequest: ${request.encode()}\nResponse: ${response_json}\n${err}') }
myerror := response.error_ or {
return error('Failed to get error from response:\nRequest: ${request.encode()}\nResponse: ${response_json}\n${err}')
}
// print_backtrace()
mut myreq:=request.encode()
mut myreq := request.encode()
if c.transport is UnixSocketTransport {
myreq="To Test:\n**********\necho '\n${myreq}\n' | nc -U ${c.transport.url()}\n**********"
myreq = "To Test:\n**********\necho '\n${myreq}\n' | nc -U ${c.transport.url()}\n**********"
} else {
myreq="Path:${c.transport.url()}\nRequest:\n${myreq}"
myreq = 'Path:${c.transport.url()}\nRequest:\n${myreq}'
}
return error('\nRPC Request Failed.\n${myreq}\n${myerror}')
}
}

View File

@@ -120,13 +120,12 @@ pub fn (resp Response) encode() string {
pub fn (resp Response) validate() ! {
if resp.error_ != none && resp.result != none {
return error('Response contains both error and result.\n- Error: ${resp.error_.str()}\n- Result: ${resp.result}')
}
}
if resp.error_ == none && resp.result == none {
return error('Response contains neither error nor result.')
}
}
// is_error checks if the response contains an error.
//
// Returns:
@@ -237,10 +236,10 @@ pub fn decode_response_generic[D](data string) !ResponseGeneric[D] {
// Handle successful responses
resp := json.decode(ResponseGeneric[D], data)!
return ResponseGeneric[D]{
id: raw_map['id'] or {
print_backtrace()
return error('Invalid JSONRPC response, no ID Field found')
}.int()
id: raw_map['id'] or {
print_backtrace()
return error('Invalid JSONRPC response, no ID Field found')
}.int()
jsonrpc: jsonrpc_version
result: resp.result
}

View File

@@ -58,16 +58,16 @@ pub fn (mut t UnixSocketTransport) send(request string, params SendParams) !stri
// Read up to 64000 bytes
mut res := []u8{len: 64000, cap: 64000}
n := socket.read(mut res) or {
//can be timeout
// can be timeout
if err.code() == 11 { // Resource temporarily unavailable (EWOULDBLOCK)
console.print_debug('Resource temporarily unavailable, retrying...')
time.sleep(100 * time.millisecond)
continue
}
if err.code() == 9 {
if err.code() == 9 {
console.print_debug('Timeout...')
break
}
}
return err
}
// console.print_debug('Read ${n} bytes from socket')
@@ -79,12 +79,12 @@ pub fn (mut t UnixSocketTransport) send(request string, params SendParams) !stri
res_total << res[..n]
if n < 8192 {
// console.print_debug('No more data to read, breaking loop after ${n} bytes')
//TODO: this seems weird
// TODO: this seems weird
break
}
}
unix.shutdown(socket.sock.handle)
socket.close() or {}
socket.close() or {}
// println(res_total.bytestr().trim_space())

View File

@@ -17,19 +17,18 @@ pub mut:
whitelist []int // comma separated list of servers we whitelist to work on
user string
password string
sshkey string
nodes []HetznerNode
sshkey string
nodes []HetznerNode
}
@[heap]
pub struct HetznerNode {
pub mut:
id string
id string
name string = 'default'
description string
}
pub fn (mut h HetznerManager) connection() !&httpconnection.HTTPConnection {
mut c2 := httpconnection.new(
name: 'hetzner_${h.name}'

View File

@@ -6,8 +6,6 @@ import freeflowuniverse.herolib.core.playbook { PlayBook }
// play processes playbook actions for the hetznermanager module.
// It allows configuring and managing Hetzner servers through heroscript.
pub fn play2(mut plbook PlayBook) ! {
// Handle rescue actions
for mut action in plbook.find(filter: 'hetznermanager.server_rescue')! {
mut p := action.params
@@ -25,12 +23,12 @@ pub fn play2(mut plbook PlayBook) ! {
}
cl.server_rescue(
id: id,
name: server_name,
wait: wait,
hero_install: hero_install,
reset: reset,
retry: retry
id: id
name: server_name
wait: wait
hero_install: hero_install
reset: reset
retry: retry
)!
action.done = true
@@ -53,12 +51,12 @@ pub fn play2(mut plbook PlayBook) ! {
}
cl.ubuntu_install(
id: id,
name: server_name,
wait: wait,
hero_install: hero_install,
hero_install_compile: hero_install_compile,
raid: raid
id: id
name: server_name
wait: wait
hero_install: hero_install
hero_install_compile: hero_install_compile
raid: raid
)!
action.done = true
@@ -78,10 +76,10 @@ pub fn play2(mut plbook PlayBook) ! {
}
cl.server_reset(
id: id,
name: server_name,
wait: wait,
msg: msg
id: id
name: server_name
wait: wait
msg: msg
)!
action.done = true
@@ -107,8 +105,8 @@ pub fn play2(mut plbook PlayBook) ! {
key_name := p.get('key_name')!
cl.key_delete( key_name)!
cl.key_delete(key_name)!
action.done = true
}
}
}

View File

@@ -1,17 +1,13 @@
module hetznermanager
pub fn (mut h HetznerManager) check_whitelist(args_ ServerRescueArgs)! {
pub fn (mut h HetznerManager) check_whitelist(args_ ServerRescueArgs) ! {
if h.whitelist.len == 0 {
return
}
mut serverinfo := h.server_info_get(id: args_.id, name: args_.name)!
if ! h.whitelist.contains(serverinfo.server_number) {
if !h.whitelist.contains(serverinfo.server_number) {
return error('Server ${serverinfo}\nis not whitelisted')
}
}

View File

@@ -69,9 +69,8 @@ fn (mut h HetznerManager) server_rescue_internal(args_ ServerRescueArgs) !Server
if serverinfo.rescue == false || args.reset {
console.print_header('server ${serverinfo.server_name} goes into rescue mode')
mykey:=h.key_get(h.sshkey)!
mykeyfp:=mykey.fingerprint
mykey := h.key_get(h.sshkey)!
mykeyfp := mykey.fingerprint
// println("Using SSH key fingerprint: ${mykey} ${mykeyfp}")
@@ -117,7 +116,6 @@ fn (mut h HetznerManager) server_rescue_internal(args_ ServerRescueArgs) !Server
}
pub fn (mut h HetznerManager) server_rescue_node(args ServerRescueArgs) !&builder.Node {
mut serverinfo := h.server_rescue(args)!
mut b := builder.new()!
@@ -137,11 +135,11 @@ pub mut:
}
pub fn (mut h HetznerManager) ubuntu_install(args ServerInstallArgs) !&builder.Node {
h.check_whitelist(name:args.name,id:args.id)!
h.check_whitelist(name: args.name, id: args.id)!
mut serverinfo := h.server_rescue(
id: args.id
name: args.name
wait: true
id: args.id
name: args.name
wait: true
)!
mut b := builder.new()!
@@ -153,7 +151,7 @@ pub fn (mut h HetznerManager) ubuntu_install(args ServerInstallArgs) !&builder.N
mut rstr := '-r no '
if args.raid {
panic("should not use RAID for now")
panic('should not use RAID for now')
rstr = '-r yes -l 1 '
}
@@ -189,7 +187,7 @@ pub fn (mut h HetznerManager) ubuntu_install(args ServerInstallArgs) !&builder.N
console.print_debug('server ${serverinfo.server_name} is reacheable over ping, lets now try ssh.')
//wait 20 sec to make sure ssh is there
// wait 20 sec to make sure ssh is there
osal.ssh_wait(address: serverinfo.server_ip, timeout: 20)!
console.print_debug('server ${serverinfo.server_name} is reacheable over ssh, lets now install hero if asked for.')

View File

@@ -77,7 +77,7 @@ pub fn (mut h HetznerManager) server_info_get(args_ ServerGetArgs) !ServerInfoDe
continue
}
server_name := texttools.name_fix(item.server_name)
//if id specified then we always use that one
// if id specified then we always use that one
if args.id == 0 && args.name.len > 0 && server_name != args.name {
continue
}