chore: add current provisioning state before migration
This commit is contained in:
parent
a9703b4748
commit
50745b0f22
660 changed files with 88126 additions and 0 deletions
282
core/nulib/servers/create.nu
Normal file
282
core/nulib/servers/create.nu
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
use std
|
||||
use lib_provisioning *
|
||||
use utils.nu *
|
||||
#use utils.nu on_server_template
|
||||
use ssh.nu *
|
||||
use ../lib_provisioning/utils/ssh.nu *
|
||||
# Provider middleware now available through lib_provisioning
|
||||
|
||||
# > Server create
|
||||
export def "main create" [
|
||||
name?: string # Server hostname in settings
|
||||
...args # Args for create command
|
||||
--infra (-i): string # Infra directory
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--select: string # Select with task as option
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "servers create" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
if $name != null and $name != "h" and $name != "help" {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
if ($curr_settings.data.servers | find $name| length) == 0 {
|
||||
_print $"🛑 invalid name ($name)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "create " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $" ($task) " "" | str trim
|
||||
let run_create = {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
$env.WK_CNPROV = $curr_settings.wk_path
|
||||
let match_name = if $name == null or $name == "" { "" } else { $name}
|
||||
on_create_servers $curr_settings $check $wait $outfile $match_name $serverpos
|
||||
}
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create help --notitles
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create --help
|
||||
_print (provisioning_options "create")
|
||||
},
|
||||
"" | "c" | "create" => {
|
||||
let result = desktop_run_notify $"($env.PROVISIONING_NAME) servers create" "-> " $run_create --timeout 11sec
|
||||
if not ($result | get -o status | default true) { exit 1 }
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers create" $task --end
|
||||
}
|
||||
}
|
||||
if not $notitles and not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
export def on_create_servers [
|
||||
settings: record # Settings record
|
||||
check: bool # Only check mode no servers will be created
|
||||
wait: bool # Wait for creation
|
||||
outfile?: string # Out file for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
--notitles # not tittles
|
||||
]: nothing -> record {
|
||||
let match_hostname = if $hostname != null {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == -1 {
|
||||
_print $"Use number form 0 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 0
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_create" --span (metadata $serverpos).span)
|
||||
exit 0
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
#use ../../../providers/prov_lib/middleware.nu mw_create_server
|
||||
# Check servers ... reload settings if are changes
|
||||
for server in $settings.data.servers {
|
||||
if $match_hostname == null or $match_hostname == "" or $server.hostname == $match_hostname {
|
||||
if (mw_create_server $settings $server $check false) == false {
|
||||
return { status: false, error: $"mw_create_sever ($server.hostname) error" }
|
||||
}
|
||||
}
|
||||
}
|
||||
let ok_settings = if ($"($settings.wk_path)/changes" | path exists) {
|
||||
if $env.PROVISIONING_DEBUG == false {
|
||||
_print $"(_ansi blue_bold)Reloading settings(_ansi reset) for (_ansi cyan_bold)($settings.infra)(_ansi reset) (_ansi purple)($settings.src)(_ansi reset)"
|
||||
cleanup $settings.wk_path
|
||||
} else {
|
||||
_print $"(_ansi blue_bold)Review (_ansi green)($settings.wk_path)/changes(_ansi reset) for (_ansi cyan_bold)($settings.infra)(_ansi reset) (_ansi purple)($settings.src)(_ansi reset)"
|
||||
_print $"(_ansi green)($settings.wk_path)(_ansi reset) (_ansi red)not deleted(_ansi reset) for debug"
|
||||
}
|
||||
#use utils/settings.nu [ load_settings ]
|
||||
(load_settings --infra $settings.infra --settings $settings.src)
|
||||
} else {
|
||||
$settings
|
||||
}
|
||||
let out_file = if $outfile == null { "" } else { $outfile }
|
||||
let target_servers = ($ok_settings.data.servers | where {|it|
|
||||
$match_hostname == null or $match_hostname == "" or $it.hostname == $match_hostname
|
||||
})
|
||||
if $check {
|
||||
$target_servers | enumerate | each {|it|
|
||||
if not (create_server $it.item $it.index true $wait $ok_settings $out_file) { return false }
|
||||
_print $"\n(_ansi blue_reverse)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)\n"
|
||||
}
|
||||
} else {
|
||||
_print $"Create (_ansi blue_bold)($target_servers | length)(_ansi reset) servers in parallel (_ansi blue_bold)>>> 🌥 >>> (_ansi reset)\n"
|
||||
$target_servers | enumerate | par-each {|it|
|
||||
if not (create_server $it.item $it.index false $wait $ok_settings $out_file) {
|
||||
return { status: false, error: $"creation ($it.item.hostname) error" }
|
||||
} else {
|
||||
let known_hosts_path = (("~" | path join ".ssh" | path join "known_hosts") | path expand)
|
||||
^ssh-keygen -f $known_hosts_path -R $it.item.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })
|
||||
if ($it.item | get -o network_public_ip | is-not-empty) {
|
||||
^ssh-keygen -f $known_hosts_path -R ($it.item | get -o network_public_ip) err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })
|
||||
}
|
||||
}
|
||||
_print $"\n(_ansi blue_reverse)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)\n"
|
||||
}
|
||||
}
|
||||
if not $check {
|
||||
# Running this in 'par-each' does not work
|
||||
$target_servers | enumerate | each { |it|
|
||||
mw_create_cache $ok_settings $it.item false
|
||||
}
|
||||
}
|
||||
servers_walk_by_costs $ok_settings $match_hostname $check true
|
||||
server_ssh $ok_settings "" "pub" false
|
||||
{ status: true, error: "" }
|
||||
}
|
||||
export def create_server [
|
||||
server: record
|
||||
index: int
|
||||
check: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
outfile?: string
|
||||
]: nothing -> bool {
|
||||
## Provider middleware now available through lib_provisioning
|
||||
#use utils.nu *
|
||||
let server_info = (mw_server_info $server true)
|
||||
let already_created = ($server_info | get -o hostname | is-not-empty)
|
||||
if ($already_created) {
|
||||
_print $"Server (_ansi green_bold)($server.hostname)(_ansi reset) already created "
|
||||
check_server $settings $server $index $server_info $check $wait $settings $outfile
|
||||
#mw_server_info $server false
|
||||
if not $check { return true }
|
||||
}
|
||||
let server_template = ($env.PROVISIONING | path join "providers" | path join $server.provider | path join templates |
|
||||
path join $"($server.provider)_servers.j2"
|
||||
)
|
||||
let create_result = on_server_template $server_template $server $index $check false $wait $settings $outfile
|
||||
if $check { return true }
|
||||
if not $create_result { return false }
|
||||
check_server $settings $server $index $server_info $check $wait $settings $outfile
|
||||
true
|
||||
}
|
||||
|
||||
export def verify_server_info [
|
||||
settings: record
|
||||
server: record
|
||||
info: record
|
||||
]: nothing -> nothing {
|
||||
_print $"Checking server (_ansi green_bold)($server.hostname)(_ansi reset) info "
|
||||
let server_plan = ($server | get -o plan | default "")
|
||||
let curr_plan = ($info | get -o plan | default "")
|
||||
if ($server_plan | is-not-empty) {
|
||||
if $server_plan != $curr_plan {
|
||||
mw_modify_server $settings $server [{plan: $server_plan}] false
|
||||
}
|
||||
}
|
||||
}
|
||||
export def check_server [
|
||||
settings: record
|
||||
server: record
|
||||
index: int
|
||||
info: record
|
||||
check: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
outfile?: string
|
||||
]: nothing -> bool {
|
||||
## Provider middleware now available through lib_provisioning
|
||||
#use utils.nu *
|
||||
let server_info = if ($info | is-empty) {
|
||||
(mw_server_info $server true)
|
||||
} else {
|
||||
$info
|
||||
}
|
||||
let already_created = ($server_info | is-not-empty)
|
||||
if not $already_created {
|
||||
_print $"🛑 server (_ansi green_bold)($server.hostname)(_ansi reset) not exists"
|
||||
return false
|
||||
}
|
||||
if not $check {
|
||||
^ssh-keygen -f $"($env.HOME)/.ssh/known_hosts" -R $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })
|
||||
let ip = (mw_get_ip $settings $server $server.liveness_ip false )
|
||||
if $ip == "" {
|
||||
_print "🛑 No liveness ip found for state checking "
|
||||
return false
|
||||
}
|
||||
verify_server_info $settings $server $server_info
|
||||
_print $"liveness (_ansi purple)($ip):($server.liveness_port)(_ansi reset)"
|
||||
if (wait_for_server $index $server $settings $ip) {
|
||||
on_server_ssh $settings $server "pub" "create" false
|
||||
# collect fingerprint
|
||||
let res = (^ssh-keyscan "-H" $ip err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })| complete)
|
||||
if $res.exit_code == 0 {
|
||||
let known_hosts_path = (("~" | path join ".ssh" | path join "known_hosts") | path expand)
|
||||
let markup = $"# ($ip) keyscan"
|
||||
let lines_found = (open $known_hosts_path --raw | lines | find $markup | length)
|
||||
if $lines_found == 0 {
|
||||
( $"($markup)\n" | save --append $known_hosts_path)
|
||||
($res.stdout | save --append $known_hosts_path)
|
||||
_print $"(_ansi green_bold)($ip)(_ansi reset) (_ansi yellow)ssh-keyscan(_ansi reset) added to ($known_hosts_path)"
|
||||
}
|
||||
#} else {
|
||||
# _print $"🛑 Error (_ansi yellow)ssh-keyscan(_ansi reset) from ($ip)"
|
||||
# _print $"($res.stdout)"
|
||||
}
|
||||
if $already_created {
|
||||
let res = (mw_post_create_server $settings $server $check)
|
||||
match $res {
|
||||
"error" | "-1" => { exit 1},
|
||||
"storage" | "" => {
|
||||
let storage_sh = ($settings.wk_path | path join $"($server.hostname)-storage.sh")
|
||||
let result = (on_server_template ($env.PROVISIONING_TEMPLATES_PATH | path join "storage.j2") $server 0 true true true $settings $storage_sh)
|
||||
if $result and ($storage_sh | path exists) and (wait_for_server $index $server $settings $ip) {
|
||||
let target_cmd = "/tmp/storage.sh"
|
||||
#use ssh.nu scp_to ssh_cmd
|
||||
if not (scp_to $settings $server [$storage_sh] $target_cmd $ip) { return false }
|
||||
_print $"Running (_ansi blue_italic)($target_cmd | path basename)(_ansi reset) in (_ansi green_bold)($server.hostname)(_ansi reset)"
|
||||
if not (ssh_cmd $settings $server true $target_cmd $ip) { return false }
|
||||
if $env.PROVISIONING_SSH_DEBUG? != null and $env.PROVISIONING_SSH_DEBUG { return true }
|
||||
if not $env.PROVISIONING_DEBUG {
|
||||
(ssh_cmd $settings $server false $"rm -f ($target_cmd)" $ip)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return true
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
170
core/nulib/servers/delete.nu
Normal file
170
core/nulib/servers/delete.nu
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
use lib_provisioning *
|
||||
|
||||
# > Delete Server
|
||||
export def "main delete" [
|
||||
name?: string # Server hostname in settings
|
||||
...args # Args for create command
|
||||
--infra (-i): string # Infra directory
|
||||
--keepstorage # keep storage
|
||||
--settings (-s): string # Settings path
|
||||
--yes (-y) # confirm delete
|
||||
--outfile (-o): string # Output file
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--select: string # Select with task as option
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "servers delete" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
if $name != null and $name != "h" and $name != "help" and not ($name | str contains "storage") {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
if ($curr_settings.data.servers | find $name| length) == 0 {
|
||||
_print $"🛑 invalid name ($name)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "delete " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $"($task) " "" | str trim
|
||||
let run_delete = {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
$env.WK_CNPROV = $curr_settings.wk_path
|
||||
on_delete_servers $curr_settings $keepstorage $wait $name $serverpos
|
||||
}
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server delete --help --notitles
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server delete --help
|
||||
_print (provisioning_options "delete")
|
||||
},
|
||||
"" if ($name | default "" | str contains "storage") => {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
on_delete_server_storage $curr_settings $wait "" $serverpos
|
||||
},
|
||||
"" | "d"| "delete" => {
|
||||
if not $yes or not (($env.PROVISIONING_ARGS? | default "") | str contains "--yes") {
|
||||
_print $"Run (_ansi red_bold)delete servers(_ansi reset) (_ansi green_bold)($name)(_ansi reset) type (_ansi green_bold)yes(_ansi reset) ? "
|
||||
let user_input = (input --numchar 3)
|
||||
if $user_input != "yes" and $user_input != "YES" {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
let result = desktop_run_notify $"($env.PROVISIONING_NAME) servers delete" "-> " $run_delete --timeout 11sec
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers delete" $task --end
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
export def on_delete_server_storage [
|
||||
settings: record # Settings record
|
||||
wait: bool # Wait for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
]: nothing -> list {
|
||||
#use lib_provisioning *
|
||||
#use utils.nu *
|
||||
let match_hostname = if $hostname != null and $hostname != "" {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == 0 {
|
||||
_print $"Use number form 1 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 1
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_create" --span (metadata $serverpos).span)
|
||||
exit 1
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
_print $"Delete storage (_ansi blue_bold)($settings.data.servers | length)(_ansi reset) server\(s\) in parallel (_ansi blue_bold)>>> 🌥 >>> (_ansi reset)\n"
|
||||
$settings.data.servers | enumerate | par-each { |it|
|
||||
if ($match_hostname == null or $match_hostname == "" or $it.item.hostname == $match_hostname) {
|
||||
if not (mw_delete_server_storage $settings $it.item false) {
|
||||
return false
|
||||
}
|
||||
_print $"\n(_ansi blue_reverse)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def on_delete_servers [
|
||||
settings: record # Settings record
|
||||
keep_storage: bool # keep storage
|
||||
wait: bool # Wait for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
]: nothing -> record {
|
||||
#use lib_provisioning *
|
||||
#use utils.nu *
|
||||
let match_hostname = if $hostname != null and $hostname != "" {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == 0 {
|
||||
_print $"Use number form 1 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 1
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_create" --span (metadata $serverpos).span)
|
||||
exit 1
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
_print $"Delete (_ansi blue_bold)($match_hostname | length)(_ansi reset) server\(s\) in parallel (_ansi blue_bold)>>> 🌥 >>> (_ansi reset)\n"
|
||||
$settings.data.servers | enumerate | par-each { |it|
|
||||
if ( $match_hostname == null or $match_hostname == "" or $it.item.hostname == $match_hostname) {
|
||||
if ($it.item | get -o lock | default false) {
|
||||
_print ($"(_ansi green)($it.item.hostname)(_ansi reset) is set to (_ansi purple)lock state(_ansi reset).\n" +
|
||||
$"Set (_ansi red)lock(_ansi reset) to False to allow delete. ")
|
||||
} else {
|
||||
if (mw_delete_server $settings $it.item $keep_storage false) {
|
||||
if $env.PROVISIONING_DEBUG { _print $"\n(_ansi red) error ($it.item.hostname)(_ansi reset)\n" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_print $"\n(_ansi blue_reverse)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)\n"
|
||||
for server in $settings.data.servers {
|
||||
if ($server | get -o lock | default false) { continue }
|
||||
let already_created = (mw_server_exists $server false)
|
||||
if ($already_created) {
|
||||
if $env.PROVISIONING_DEBUG { _print $"\n(_ansi red) error ($server.hostname)(_ansi reset)\n" }
|
||||
} else {
|
||||
mw_clean_cache $settings $server false
|
||||
}
|
||||
}
|
||||
{ status: true, error: "" }
|
||||
}
|
||||
312
core/nulib/servers/generate.nu
Normal file
312
core/nulib/servers/generate.nu
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
use std
|
||||
use lib_provisioning *
|
||||
use utils.nu *
|
||||
#use utils.nu on_server_template
|
||||
use ssh.nu *
|
||||
use ../lib_provisioning/utils/ssh.nu *
|
||||
use ../lib_provisioning/utils/generate.nu *
|
||||
# Provider middleware now available through lib_provisioning
|
||||
|
||||
# > Server generate
|
||||
export def "main generate" [
|
||||
name?: string # Server hostname in settings
|
||||
...args # Args for generate command
|
||||
--infra (-i): string # Infra directory
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be generated
|
||||
--wait (-w) # Wait servers to be generated
|
||||
--select: string # Select with task as option
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
--inputfile: string # Input file
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "servers generate" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
# if $name != null and $name != "h" and $name != "help" {
|
||||
# let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
# if ($curr_settings.data.servers | find $name| length) == 0 {
|
||||
# _print $"🛑 invalid name ($name)"
|
||||
# exit 1
|
||||
# }
|
||||
# }
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "generate " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $" ($task) " "" | str trim
|
||||
let run_generate = {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings false true)
|
||||
$env.WK_CNPROV = $curr_settings.wk_path
|
||||
let match_name = if $name == null or $name == "" { "" } else { $name}
|
||||
on_generate_servers $curr_settings $check $wait $outfile $match_name $serverpos --inputfile $inputfile --select $select
|
||||
}
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server generate help --notitles
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server generate --help
|
||||
_print (provisioning_options "generate")
|
||||
},
|
||||
"" | "g" | "generate" => {
|
||||
let result = desktop_run_notify $"($env.PROVISIONING_NAME) servers generate" "-> " $run_generate --timeout 11sec
|
||||
if not ($result | get -o status | default true) { exit 1 }
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers generate" $task --end
|
||||
}
|
||||
}
|
||||
if not $notitles and not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
export def on_generate_servers [
|
||||
settings: record # Settings record
|
||||
check: bool # Only check mode no servers will be generated
|
||||
wait: bool # Wait for creation
|
||||
outfile?: string # Out file for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
--notitles # not tittles
|
||||
--select: string # Provider selection
|
||||
--inputfile: string # input file with data for no interctive input mode
|
||||
]: nothing -> nothing {
|
||||
let match_hostname = if $hostname != null {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == -1 {
|
||||
_print $"Use number form 0 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 0
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_generate" --span (metadata $serverpos).span)
|
||||
exit 0
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
let providers_list = (providers_list "selection")
|
||||
if ($providers_list | length) == 0 {
|
||||
_print $"🛑 no providers found for (_ansi cyan)providers list(_ansi reset)"
|
||||
return
|
||||
}
|
||||
# let servers_path_0 = if ($settings.data.servers_paths | length) > 1 { #TODO }
|
||||
let servers_path_0 = ($settings.data.servers_paths | get -o 0)
|
||||
let servers_path = if ($servers_path_0 | str ends-with ".k") { $servers_path_0 } else { $"($servers_path_0).k"}
|
||||
#if not ($servers_path | path exists) {
|
||||
#(throw-error $"🛑 servers path" $"($servers_path) not found in ($settings.infra)"
|
||||
# "on_generate" --span (metadata $servers_path).span)
|
||||
# exit 0
|
||||
#}
|
||||
#open -r $servers_path | str replace --multiline --regex '^]' '' |
|
||||
# save -f ($settings.wk_path | path join $"_($servers_path | path basename)")
|
||||
_print $"\n(_ansi green)PROVIDERS(_ansi reset) list: \n"
|
||||
let full_servers_path = if ($servers_path | str starts-with "/") {
|
||||
$servers_path
|
||||
} else {
|
||||
($settings.src_path | path join $servers_path)
|
||||
}
|
||||
let target_path = ($full_servers_path | path dirname)
|
||||
mut $servers_length = ($settings.data.servers | length)
|
||||
while true {
|
||||
_print $"(_ansi yellow)($servers_length)(_ansi reset) servers "
|
||||
let servers_kcl = (open -r $full_servers_path | str replace --multiline --regex '^]' '')
|
||||
# TODO SAVE A COPY
|
||||
let item_select = if ($select | is-empty) {
|
||||
let selection_pos = ($providers_list | each {|it|
|
||||
match ($it.name | str length) {
|
||||
2..5 => $"($it.name)\t\t ($it.info) \tversion: ($it.vers)",
|
||||
_ => $"($it.name)\t ($it.info) \tversion: ($it.vers)",
|
||||
}
|
||||
} | input list --index (
|
||||
$"(_ansi default_dimmed)Select one provider for (_ansi cyan_bold)new server(_ansi reset)" +
|
||||
$" \(use arrow keys and press [enter] or [escape] to exit\)( _ansi reset)"
|
||||
)
|
||||
)
|
||||
if ($selection_pos | is-empty) { break }
|
||||
($providers_list | get -o $selection_pos)
|
||||
} else {
|
||||
($providers_list | where {|it| $it.name == $select} | get -o 0 | default {})
|
||||
}
|
||||
if ($item_select | is-not-empty) {
|
||||
let item_path = ($env.PROVISIONING_PROVIDERS_PATH | path join $item_select.name)
|
||||
if not ($item_path | path join $env.PROVISIONING_GENERATE_DIRPATH | path exists) {
|
||||
_print $"Path ($item_path | path join $env.PROVISIONING_GENERATE_DIRPATH) not found\n"
|
||||
continue
|
||||
}
|
||||
let template_path = ($item_path | path join $env.PROVISIONING_GENERATE_DIRPATH)
|
||||
let new_created = if not ($target_path | path join $"($item_select.name)_defaults.k" | path exists) {
|
||||
^cp -pr ($template_path | path join $"($item_select.name)_defaults.k.j2") ($target_path)
|
||||
_print $"copy (_ansi green)($item_select.name)_defaults.k.j2(_ansi reset) to (_ansi green)($settings.infra)(_ansi reset)"
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if not ($full_servers_path | path exists) or ($servers_kcl | is-empty) or $servers_length == 0 {
|
||||
($"import ($item_select.name)_prov\nservers = [\n" + (open -r ($template_path | path join "servers.k.j2")) + "\n]" )
|
||||
| save -f $"($full_servers_path).j2"
|
||||
_print $"create (_ansi green)($item_select.name) servers.k.j2(_ansi reset) to (_ansi green)($settings.infra)(_ansi reset)"
|
||||
} else {
|
||||
let head_text = if not ($servers_kcl | str contains $"import ($item_select.name)") {
|
||||
$"import ($item_select.name)_prov\n"
|
||||
} else {"" }
|
||||
print $"import ($item_select.name)"
|
||||
print $head_text
|
||||
($head_text + $servers_kcl + (open -r ($template_path | path join "servers.k.j2")) + "\n]" )
|
||||
| save -f $"($full_servers_path).j2"
|
||||
_print $"add (_ansi green)($item_select.name) servers.k.j2(_ansi reset) to (_ansi green)($settings.infra)(_ansi reset)"
|
||||
}
|
||||
generate_data_def $item_path $settings.infra ($settings.src_path | path join ($full_servers_path | path dirname)) $new_created $inputfile
|
||||
# TODO CHECK if compiles KCL OR RECOVERY
|
||||
# TODO ADD tasks for server
|
||||
if ($inputfile | is-not-empty) { break }
|
||||
$servers_length += 1
|
||||
} else {
|
||||
#(open -r $servers_path) + "\n]" | save -f $servers_path
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
export def generate_server [
|
||||
server: record
|
||||
index: int
|
||||
check: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
outfile?: string
|
||||
]: nothing -> bool {
|
||||
## Provider middleware now available through lib_provisioning
|
||||
#use utils.nu *
|
||||
let server_info = (mw_server_info $server true)
|
||||
let already_generated = ($server_info | get -o hostname | is-not-empty)
|
||||
if ($already_generated) {
|
||||
_print $"Server (_ansi green_bold)($server.hostname)(_ansi reset) already generated "
|
||||
check_server $settings $server $index $server_info $check $wait $settings $outfile
|
||||
#mw_server_info $server false
|
||||
if not $check { return true }
|
||||
}
|
||||
let server_template = ($env.PROVISIONING | path join "providers" | path join $server.provider | path join templates |
|
||||
path join $"($server.provider)_servers.j2"
|
||||
)
|
||||
let generate_result = on_server_template $server_template $server $index $check false $wait $settings $outfile
|
||||
if $check { return true }
|
||||
if not $generate_result { return false }
|
||||
check_server $settings $server $index $server_info $check $wait $settings $outfile
|
||||
true
|
||||
}
|
||||
|
||||
export def verify_server_info [
|
||||
settings: record
|
||||
server: record
|
||||
info: record
|
||||
]: nothing -> nothing {
|
||||
_print $"Checking server (_ansi green_bold)($server.hostname)(_ansi reset) info "
|
||||
let server_plan = ($server | get -o plan | default "")
|
||||
let curr_plan = ($info | get -o plan | default "")
|
||||
if ($server_plan | is-not-empty) {
|
||||
if $server_plan != $curr_plan {
|
||||
mw_modify_server $settings $server [{plan: $server_plan}] false
|
||||
}
|
||||
}
|
||||
}
|
||||
export def check_server [
|
||||
settings: record
|
||||
server: record
|
||||
index: int
|
||||
info: record
|
||||
check: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
outfile?: string
|
||||
]: nothing -> bool {
|
||||
## Provider middleware now available through lib_provisioning
|
||||
#use utils.nu *
|
||||
let server_info = if ($info | is-empty) {
|
||||
(mw_server_info $server true)
|
||||
} else {
|
||||
$info
|
||||
}
|
||||
let already_generated = ($server_info | is-not-empty)
|
||||
if not $already_generated {
|
||||
_print $"🛑 server (_ansi green_bold)($server.hostname)(_ansi reset) not exists"
|
||||
return false
|
||||
}
|
||||
if not $check {
|
||||
^ssh-keygen -f $"($env.HOME)/.ssh/known_hosts" -R $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })
|
||||
let ip = (mw_get_ip $settings $server $server.liveness_ip false )
|
||||
if $ip == "" {
|
||||
_print "🛑 No liveness ip found for state checking "
|
||||
return false
|
||||
}
|
||||
verify_server_info $settings $server $server_info
|
||||
_print $"liveness (_ansi purple)($ip):($server.liveness_port)(_ansi reset)"
|
||||
if (wait_for_server $index $server $settings $ip) {
|
||||
on_server_ssh $settings $server "pub" "generate" false
|
||||
# collect fingerprint
|
||||
let res = (^ssh-keyscan "-H" $ip err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })| complete)
|
||||
if $res.exit_code == 0 {
|
||||
let known_hosts_path = (("~" | path join ".ssh" | path join "known_hosts") | path expand)
|
||||
let markup = $"# ($ip) keyscan"
|
||||
let lines_found = (open $known_hosts_path --raw | lines | find $markup | length)
|
||||
if $lines_found == 0 {
|
||||
( $"($markup)\n" | save --append $known_hosts_path)
|
||||
($res.stdout | save --append $known_hosts_path)
|
||||
_print $"(_ansi green_bold)($ip)(_ansi reset) (_ansi yellow)ssh-keyscan(_ansi reset) added to ($known_hosts_path)"
|
||||
}
|
||||
#} else {
|
||||
# _print $"🛑 Error (_ansi yellow)ssh-keyscan(_ansi reset) from ($ip)"
|
||||
# _print $"($res.stdout)"
|
||||
}
|
||||
if $already_generated {
|
||||
let res = (mw_post_generate_server $settings $server $check)
|
||||
match $res {
|
||||
"error" | "-1" => { exit 1},
|
||||
"storage" | "" => {
|
||||
let storage_sh = ($settings.wk_path | path join $"($server.hostname)-storage.sh")
|
||||
let result = (on_server_template ($env.PROVISIONING_TEMPLATES_PATH | path join "storage.j2") $server 0 true true true $settings $storage_sh)
|
||||
if $result and ($storage_sh | path exists) and (wait_for_server $index $server $settings $ip) {
|
||||
let target_cmd = "/tmp/storage.sh"
|
||||
#use ssh.nu scp_to ssh_cmd
|
||||
if not (scp_to $settings $server [$storage_sh] $target_cmd $ip) { return false }
|
||||
_print $"Running (_ansi blue_italic)($target_cmd | path basename)(_ansi reset) in (_ansi green_bold)($server.hostname)(_ansi reset)"
|
||||
if not (ssh_cmd $settings $server true $target_cmd $ip) { return false }
|
||||
if $env.PROVISIONING_SSH_DEBUG? != null and $env.PROVISIONING_SSH_DEBUG { return true }
|
||||
if not $env.PROVISIONING_DEBUG {
|
||||
(ssh_cmd $settings $server false $"rm -f ($target_cmd)" $ip)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return true
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
9
core/nulib/servers/mod.nu
Normal file
9
core/nulib/servers/mod.nu
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export use ops.nu *
|
||||
|
||||
export use create.nu *
|
||||
export use delete.nu *
|
||||
export use generate.nu *
|
||||
export use status.nu *
|
||||
export use state.nu *
|
||||
export use ssh.nu *
|
||||
export use utils.nu *
|
||||
15
core/nulib/servers/ops.nu
Normal file
15
core/nulib/servers/ops.nu
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export def provisioning_options [
|
||||
source: string
|
||||
]: nothing -> string {
|
||||
(
|
||||
$"(_ansi blue_bold)($env.PROVISIONING_NAME) server ($source)(_ansi reset) options:\n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) sed - to edit content from a SOPS file\n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) sed - to edit content from a SOPS file\n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) cache - to view with PROVISIONING_FILEVIEWER server provider settings cache \n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) list [items] - to list items: " +
|
||||
$"[ (_ansi green)providers(_ansi reset) p | (_ansi green)tasks(_ansi reset) t | (_ansi green)services(_ansi reset) s ]\n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) cost [host] - Get [cost | price] for [all | host] servers \n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) nu - to run a nushell in ($env.PROVISIONING) path\n" +
|
||||
$"(_ansi blue)($env.PROVISIONING_NAME)(_ansi reset) qr - to get ($env.PROVISIONING_URL) QR code"
|
||||
)
|
||||
}
|
||||
192
core/nulib/servers/ssh.nu
Normal file
192
core/nulib/servers/ssh.nu
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
use std
|
||||
use ops.nu *
|
||||
use ../../../providers/prov_lib/middleware.nu mw_get_ip
|
||||
# --check (-c) # Only check mode no servers will be created
|
||||
# --wait (-w) # Wait servers to be created
|
||||
# --select: string # Select with task as option
|
||||
# --xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
# --xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
|
||||
# - -> SSH for server connections
|
||||
export def "main ssh" [
|
||||
name?: string # Server hostname in settings
|
||||
iptype: string = "public" # Ip type to connect
|
||||
...args # Args for create command
|
||||
--run # Run ssh on 'name'
|
||||
--infra (-i): string # Infra directory
|
||||
--settings (-s): string # Settings path
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "server ssh" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
if $name != null and $name != "h" and $name != "help" {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
if ($curr_settings.data.servers | find $name| length) == 0 {
|
||||
_print $"🛑 invalid name ($name)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "ssh " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $"($task) " "" | str trim
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server ssh help --notitles
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server ssh --help
|
||||
print (provisioning_options "create")
|
||||
},
|
||||
"" | "ssh" => {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
#let match_name = if $name == null or $name == "" { "" } else { $name}
|
||||
server_ssh $curr_settings "" $iptype $run $name
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers ssh" $task --end
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
|
||||
export def server_ssh_addr [
|
||||
settings: record
|
||||
server: record
|
||||
]: nothing -> string {
|
||||
#use (prov-middleware) mw_get_ip
|
||||
let connect_ip = (mw_get_ip $settings $server $server.liveness_ip false )
|
||||
if $connect_ip == "" { return "" }
|
||||
$"($server.installer_user)@($connect_ip)"
|
||||
}
|
||||
export def server_ssh_id [
|
||||
server: record
|
||||
]: nothing -> string {
|
||||
($server.ssh_key_path | str replace ".pub" "")
|
||||
}
|
||||
export def server_ssh [
|
||||
settings: record
|
||||
request_from: string
|
||||
ip_type: string
|
||||
run: bool
|
||||
text_match?: string
|
||||
]: nothing -> nothing {
|
||||
let default_port = 22
|
||||
$settings.data.servers | each { | server |
|
||||
if $text_match == null or $server.hostname == $text_match {
|
||||
on_server_ssh $settings $server $ip_type $request_from $run
|
||||
}
|
||||
}
|
||||
}
|
||||
def ssh_config_entry [
|
||||
server: record
|
||||
ssh_key_path: string
|
||||
]: nothing -> string {
|
||||
$"
|
||||
Host ($server.hostname)
|
||||
User ($server.installer_user | default "root")
|
||||
HostName ($server.hostname)
|
||||
IdentityFile ($ssh_key_path)
|
||||
ServerAliveInterval 239
|
||||
StrictHostKeyChecking accept-new
|
||||
Port ($server.user_ssh_port)
|
||||
"
|
||||
}
|
||||
export def on_server_ssh [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type: string
|
||||
request_from: string
|
||||
run: bool
|
||||
]: nothing -> bool {
|
||||
#use (prov-middleware) mw_get_ip
|
||||
let connect_ip = (mw_get_ip $settings $server $server.liveness_ip false )
|
||||
if $connect_ip == "" {
|
||||
_print ($"\n🛑 (_ansi red)Error(_ansi reset) no (_ansi red)($server.liveness_ip | str replace '$' '')(_ansi reset) " +
|
||||
$"found for (_ansi green)($server.hostname)(_ansi reset)"
|
||||
)
|
||||
return false
|
||||
}
|
||||
let hosts_path = "/etc/hosts"
|
||||
let ssh_key_path = ($server.ssh_key_path | str replace ".pub" "")
|
||||
if $server.fix_local_hosts {
|
||||
let ips = (^grep $server.hostname /etc/hosts | ^grep -v "^#" | ^awk '{print $1}' | str trim | split row "\n")
|
||||
for ip in $ips {
|
||||
if ($ip | is-not-empty) and $ip != $connect_ip {
|
||||
^sudo sed -ie $"/^($ip)/d" $hosts_path
|
||||
_print $"Delete ($ip) entry in ($hosts_path)"
|
||||
}
|
||||
}
|
||||
}
|
||||
if $server.fix_local_hosts and (^grep $connect_ip /etc/hosts | ^grep -v "^#" | ^awk '{print $1}' | is-empty) {
|
||||
if ($server.hostname | is-not-empty) { ^sudo sed -i $"/($server.hostname)/d" $hosts_path }
|
||||
let extra_hostnames = ($server.extra_hostnames | default [] | str join " ")
|
||||
($"($connect_ip) ($server.hostname) ($extra_hostnames)\n" | ^sudo tee -a $hosts_path)
|
||||
^ssh-keygen -f $"($env.HOME)/.ssh/known_hosts" -R $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })
|
||||
_print $"(_ansi green)($server.hostname)(_ansi reset) entry in ($hosts_path) added"
|
||||
}
|
||||
if $server.fix_local_hosts and (^grep $"HostName ($server.hostname)" $"($env.HOME)/.ssh/config" | ^grep -v "^#" | is-empty) {
|
||||
(ssh_config_entry $server $ssh_key_path) | save -a $"($env.HOME)/.ssh/config"
|
||||
_print $"(_ansi green)($server.hostname)(_ansi reset) entry in ($env.HOME)/.ssh/config for added"
|
||||
}
|
||||
let hosts_entry = (^grep ($connect_ip) /etc/hosts | ^grep -v "^#")
|
||||
let ssh_config_entry = (^grep $"HostName ($server.hostname)" $"($env.HOME)/.ssh/config" | ^grep -v "^#")
|
||||
if $run {
|
||||
print $"(_ansi default_dimmed)Connecting to server(_ansi reset) (_ansi green_bold)($server.hostname)(_ansi reset)\n"
|
||||
^ssh -i (server_ssh_id $server) (server_ssh_addr $settings $server)
|
||||
return true
|
||||
}
|
||||
match $request_from {
|
||||
"error" | "end" => {
|
||||
_print $"(_ansi default_dimmed)To connect server ($server.hostname) use:(_ansi reset)\n"
|
||||
if $ssh_config_entry != "" and $hosts_entry != "" { print $"ssh ($server.hostname) or " }
|
||||
show_clip_to $"ssh -i (server_ssh_id $server) (server_ssh_addr $settings $server) " true
|
||||
},
|
||||
"create" => {
|
||||
_print (
|
||||
(if $ssh_config_entry != "" and $hosts_entry != "" { $"ssh ($server.hostname) or " } else { "" }) +
|
||||
$"ssh -i (server_ssh_id $server) (server_ssh_addr $settings $server)"
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
_print $"\n✅ To connect server (_ansi green_bold)($server.hostname)(_ansi reset) use:"
|
||||
if $hosts_entry == "" {
|
||||
_print $"(_ansi default_dimmed)\nAdd to /etc/hosts or DNS:(_ansi reset) ($connect_ip) ($server.hostname)"
|
||||
} else if $env.PROVISIONING_DEBUG {
|
||||
_print $"Entry for ($server.hostname) via ($connect_ip) is in ($hosts_path)"
|
||||
}
|
||||
if $ssh_config_entry == "" {
|
||||
_print $"\nVia (_ansi blue).ssh/config(_ansi reset) add entry:\n (ssh_config_entry $server $ssh_key_path)"
|
||||
} else if $env.PROVISIONING_DEBUG {
|
||||
_print $"ssh config entry for ($server.hostname) via ($connect_ip) is in ($env.HOME)/.ssh/config"
|
||||
}
|
||||
if $ssh_config_entry != "" and $hosts_entry != "" { _print $"ssh ($server.hostname) " }
|
||||
if ($env.PROVISIONING_OUT | is-empty) {
|
||||
show_clip_to $"ssh -i (server_ssh_id $server) (server_ssh_addr $settings $server) " true
|
||||
}
|
||||
},
|
||||
}
|
||||
true
|
||||
}
|
||||
124
core/nulib/servers/state.nu
Normal file
124
core/nulib/servers/state.nu
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
use lib_provisioning *
|
||||
use utils.nu *
|
||||
use ssh.nu *
|
||||
# Provider middleware now available through lib_provisioning
|
||||
|
||||
# > Servers state
|
||||
export def "main state" [
|
||||
new_state?: string # Server new state
|
||||
name?: string # Server hostname in settings
|
||||
...args # Args for create command
|
||||
--infra (-i): string # Infra directory
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--select: string # Select with task as option
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "servers state" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
if ($new_state | is-empty) {
|
||||
(throw-error $"🛑 no new state found " $"for servers "
|
||||
"in main state" --span (metadata $serverpos).span)
|
||||
exit 0
|
||||
}
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "create " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $" ($task) " "" | str trim
|
||||
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create help --notitles
|
||||
exit 0
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create --help
|
||||
_print (provisioning_options "create")
|
||||
},
|
||||
"state" => {
|
||||
let the_new_state = if $new_state == "restart" or $new_state == "rs" {
|
||||
"restart"
|
||||
} else { $new_state }
|
||||
let run_state = {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
$env.WK_CNPROV = $curr_settings.wk_path
|
||||
let match_name = if $name == null or $name == "" { "" } else { $name}
|
||||
on_state_servers $curr_settings $the_new_state $wait $match_name $serverpos
|
||||
}
|
||||
let result = desktop_run_notify $"($env.PROVISIONING_NAME) servers state to ($new_state)" "-> " $run_state --timeout 11sec
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers status" $"($task) ($name)" --end
|
||||
}
|
||||
}
|
||||
# "" | "create"
|
||||
if not $notitles and not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
export def on_state_servers [
|
||||
settings: record # Settings record
|
||||
new_state: string
|
||||
wait: bool # Wait for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
--notitles # not tittles
|
||||
]: nothing -> list {
|
||||
let match_hostname = if $hostname != null {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == -1 {
|
||||
_print $"Use number form 0 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 0
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_state" --span (metadata $serverpos).span)
|
||||
exit 0
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
#use ../../../providers/prov_lib/middleware.nu mw_server_state
|
||||
$settings.data.servers | enumerate | par-each { |it|
|
||||
if $match_hostname == null or $match_hostname == "" or $it.item.hostname == $match_hostname {
|
||||
(mw_server_state $it.item $new_state true $wait $settings)
|
||||
if $new_state != "stop" and $wait {
|
||||
let ip = (mw_get_ip $settings $it.item $it.item.liveness_ip false )
|
||||
_print $it.item.liveness_ip
|
||||
if ($ip | is-not-empty) {
|
||||
_print $"liveness (_ansi purple)($ip):($it.item.liveness_port)(_ansi reset)"
|
||||
if (wait_for_server $it.index $it.item $settings $ip) {
|
||||
_print $"✅ server (_ansi blue)($it.item.hostname)(_ansi reset) (_ansi green_bold)completed(_ansi reset)"
|
||||
}
|
||||
}
|
||||
}
|
||||
_print $"\n(_ansi blue_reverse)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
79
core/nulib/servers/status.nu
Normal file
79
core/nulib/servers/status.nu
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use lib_provisioning *
|
||||
use utils.nu *
|
||||
use ssh.nu *
|
||||
# Provider middleware now available through lib_provisioning
|
||||
|
||||
# > Servers status
|
||||
export def "main status" [
|
||||
name?: string # Server hostname in settings
|
||||
...args # Args for create command
|
||||
--infra (-i): string # Infra directory
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--select: string # Select with task as option
|
||||
--debug (-x) # Use Debug mode
|
||||
--xm # Debug with PROVISIONING_METADATA
|
||||
--xc # Debuc for task and services locally PROVISIONING_DEBUG_CHECK
|
||||
--xr # Debug for remote servers PROVISIONING_DEBUG_REMOTE
|
||||
--xld # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
|
||||
--metadata # Error with metadata (-xm)
|
||||
--notitles # not tittles
|
||||
--helpinfo (-h) # For more details use options "help" (no dashes)
|
||||
--out: string # Print Output format: json, yaml, text (default)
|
||||
]: nothing -> nothing {
|
||||
if ($out | is-not-empty) {
|
||||
$env.PROVISIONING_OUT = $out
|
||||
$env.PROVISIONING_NO_TERMINAL = true
|
||||
}
|
||||
provisioning_init $helpinfo "servers status" $args
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
if $metadata { $env.PROVISIONING_METADATA = true }
|
||||
if $name != null and $name != "h" and $name != "help" {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
if ($curr_settings.data.servers | find $name| length) == 0 {
|
||||
_print $"🛑 invalid name ($name)"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
let task = if ($args | length) > 0 {
|
||||
($args| get 0)
|
||||
} else {
|
||||
let str_task = (($env.PROVISIONING_ARGS? | default "") | str replace "create " " " )
|
||||
let str_task = if $name != null {
|
||||
($str_task | str replace $name "")
|
||||
} else {
|
||||
$str_task
|
||||
}
|
||||
($str_task | str trim | split row " " | get -o 0 | default "" |
|
||||
split row "-" | get -o 0 | default "" | str trim )
|
||||
}
|
||||
let other = if ($args | length) > 0 { ($args| skip 1) } else { "" }
|
||||
let ops = $"($env.PROVISIONING_ARGS? | default "") " | str replace $" ($task) " "" | str trim
|
||||
|
||||
match $task {
|
||||
"" if $name == "h" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create help --notitles
|
||||
exit 0
|
||||
},
|
||||
"" if $name == "help" => {
|
||||
^$"($env.PROVISIONING_NAME)" -mod server create --help
|
||||
_print (provisioning_options "create")
|
||||
},
|
||||
"" | "s" | "status" => {
|
||||
let curr_settings = (find_get_settings --infra $infra --settings $settings)
|
||||
if ($out | is-empty ) {
|
||||
mw_servers_info $curr_settings
|
||||
} else {
|
||||
_print (mw_servers_info $curr_settings | to json) "json" "result" "table"
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
invalid_task "servers status" $task --end
|
||||
}
|
||||
}
|
||||
# "" | "create"
|
||||
if not $notitles and not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
}
|
||||
612
core/nulib/servers/utils.nu
Normal file
612
core/nulib/servers/utils.nu
Normal file
|
|
@ -0,0 +1,612 @@
|
|||
# Provider middleware now available through lib_provisioning
|
||||
use lib_provisioning *
|
||||
use ssh.nu *
|
||||
use ../lib_provisioning/utils/ssh.nu ssh_cmd
|
||||
use ../lib_provisioning/utils/settings.nu get_file_format
|
||||
use ../lib_provisioning/secrets/lib.nu encrypt_secret
|
||||
|
||||
export def on_server [
|
||||
settings: record # Settings record
|
||||
check: bool # Only check mode no servers will be created
|
||||
wait: bool # Wait for creation
|
||||
outfile?: string # Out file for creation
|
||||
hostname?: string # Server hostname in settings
|
||||
serverpos?: int # Server position in settings
|
||||
]: nothing -> list {
|
||||
# _check_settings
|
||||
let match_hostname = if $hostname != null {
|
||||
$hostname
|
||||
} else if $serverpos != null {
|
||||
let total = $settings.data.servers | length
|
||||
let pos = if $serverpos == 0 {
|
||||
_print $"Use number form 1 to ($total)"
|
||||
$serverpos
|
||||
} else if $serverpos <= $total {
|
||||
$serverpos - 1
|
||||
} else {
|
||||
(throw-error $"🛑 server pos" $"($serverpos) from ($total) servers"
|
||||
"on_create" --span (metadata $serverpos).span)
|
||||
exit 1
|
||||
}
|
||||
($settings.data.servers | get $pos).hostname
|
||||
}
|
||||
if $check {
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
if $match_hostname == null or $it.item.hostname == $match_hostname {
|
||||
on_create_server $it.item $it.index true $outfile
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$settings.data.servers | enumerate | par-each { |it|
|
||||
if $match_hostname == null or $it.item.hostname == $match_hostname {
|
||||
on_create_server $it.item $it.index false $outfile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def wait_for_server [
|
||||
server_pos: int
|
||||
server: record
|
||||
settings: record
|
||||
ip: string
|
||||
]: nothing -> bool {
|
||||
if $ip == "" { return false }
|
||||
mut num = 0
|
||||
let liveness_port = (if $server.liveness_port? != null { $server.liveness_port } else { 22 } | into int)
|
||||
let val_timeout = if $server.running_timeout? != null { $server.running_timeout } else { 0 }
|
||||
let wait = if $server.running_wait? != null { $server.running_wait } else { 10 }
|
||||
let wait_duration = ($"($wait)sec"| into duration)
|
||||
_print (
|
||||
$"wait for server (_ansi blue_bold)($server.hostname)(_ansi reset) state " +
|
||||
$"(_ansi yellow_bold)started(_ansi reset) (_ansi default_dimmed)until ($val_timeout)secs check every ($wait)sec(_ansi reset)"
|
||||
)
|
||||
while true {
|
||||
let status = (mw_server_is_running $server false)
|
||||
#let res = (run-external --redirect-combine "nc" "-zv" "-w" 1 $ip $liveness_port | complete)
|
||||
#if $res.exit_code == 0 {
|
||||
if $status and (port_scan $ip $server.liveness_port 1) and (ssh_cmd $settings $server false "ls" $ip) {
|
||||
_print $"done in ($num)secs "
|
||||
break
|
||||
} else if $val_timeout > 0 and $num > $val_timeout {
|
||||
_print ($"\n🛑 (_ansi red)Timeout(_ansi reset) ($val_timeout) (_ansi blue)($server.hostname)(_ansi reset)" +
|
||||
$"(_ansi blue_bold)($ip)(_ansi reset) at ($liveness_port) (_ansi red_bold)failed(_ansi reset) "
|
||||
)
|
||||
#print $"\n($res.stdout)"
|
||||
return false
|
||||
} else {
|
||||
$num = $num + $wait
|
||||
#print -n $"($nupm) "
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
sleep $wait_duration
|
||||
}
|
||||
}
|
||||
_print (
|
||||
$"(_ansi blue)($server.hostname)(_ansi reset) at (_ansi blue_bold)($ip)(_ansi reset) " +
|
||||
$"port ($liveness_port) (_ansi green_bold)ready(_ansi reset) "
|
||||
)
|
||||
true
|
||||
}
|
||||
export def on_server_template [
|
||||
server_template: string
|
||||
server: record
|
||||
index: int
|
||||
check: bool
|
||||
only_make: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
outfile?: string
|
||||
]: nothing -> bool {
|
||||
if $server.provider == local { return true }
|
||||
if not ( $server_template | path exists ) {
|
||||
_print $"($server_template) not found for ($server.hostname) [($index)]"
|
||||
return false
|
||||
}
|
||||
let suffix = if ($server_template | str contains "storage") {
|
||||
"storage"
|
||||
} else {
|
||||
"server"
|
||||
}
|
||||
#use utils/templates.nu run_from_template
|
||||
#mut create_result = false
|
||||
let duration = timeit {
|
||||
let wk_file = $"($settings.wk_path)/($server.hostname)_($suffix)_cmd"
|
||||
let wk_vars = $"($settings.wk_path)/($server.hostname)_($suffix)_vars.($env.PROVISIONING_WK_FORMAT)"
|
||||
let run_file = $"($settings.wk_path)/on_($server.hostname)_($suffix)_run.sh"
|
||||
rm --force $wk_file $wk_vars $run_file
|
||||
let data_settings = if $suffix == "storage" {
|
||||
($settings.data | merge { wk_file: $wk_file, now: $env.NOW, server_pos: $index, storage_pos: 0, provisioning_vers: ($env.PROVISIONING_VERS? | str replace "null" ""),
|
||||
wait: $wait, server: $server })
|
||||
} else {
|
||||
($settings.data | merge { wk_file: $wk_file, now: $env.NOW, serverpos: $index, provisioning_vers: ($env.PROVISIONING_VERS? | str replace "null" ""),
|
||||
wait: $wait, provider: ($settings.providers | where {|it| $it.provider == $server.provider} | get -o 0 | get -o settings | default {}),
|
||||
server: $server })
|
||||
}
|
||||
if $env.PROVISIONING_WK_FORMAT == "json" {
|
||||
$data_settings | to json | save --force $wk_vars
|
||||
} else {
|
||||
$data_settings | to yaml | save --force $wk_vars
|
||||
}
|
||||
let res = if $only_make and $check {
|
||||
(run_from_template $server_template $wk_vars $run_file $outfile --only_make --check_mode)
|
||||
} else if $only_make {
|
||||
(run_from_template $server_template $wk_vars $run_file $outfile --only_make)
|
||||
} else if $check {
|
||||
(run_from_template $server_template $wk_vars $run_file $outfile --check_mode)
|
||||
} else {
|
||||
(run_from_template $server_template $wk_vars $run_file $outfile)
|
||||
}
|
||||
if $res {
|
||||
if $env.PROVISIONING_DEBUG == false { rm --force $wk_file $wk_vars $run_file }
|
||||
_print $"(_ansi green_bold)($server.hostname)(_ansi reset) (_ansi green)successfully(_ansi reset)"
|
||||
} else {
|
||||
_print $"(_ansi red)Failed(_ansi reset) (_ansi green_bold)($server.hostname)(_ansi reset)"
|
||||
}
|
||||
}
|
||||
let text_duration = if not $check { $"in (_ansi blue_bold)($duration)(_ansi reset)" } else { "" }
|
||||
_print $"Done run template (_ansi blue_italic)($server_template | path basename | str replace ".j2" "" )(_ansi reset) for (_ansi green_bold)($server.hostname)(_ansi reset) ($text_duration)"
|
||||
true # $create_result
|
||||
}
|
||||
export def servers_selector [
|
||||
settings: record
|
||||
ip_type: string
|
||||
is_for_task: bool
|
||||
]: nothing -> string {
|
||||
if ($env | get -o PROVISIONING_OUT | default "" | is-not-empty) or $env.PROVISIONING_NO_TERMINAL { return ""}
|
||||
mut servers_pick_lists = []
|
||||
if not $env.PROVISIONING_DEBUG_CHECK {
|
||||
#use ssh.nu *
|
||||
for server in $settings.data.servers {
|
||||
let ip = (mw_get_ip $settings $server $ip_type false | default "")
|
||||
if $ip == "" {
|
||||
_print $"🛑 No IP ($ip_type) found for (_ansi green_bold)($server.hostname)(_ansi reset) "
|
||||
continue
|
||||
}
|
||||
let ssh_id = (server_ssh_id $server)
|
||||
let ssh_addr = (server_ssh_addr $settings $server)
|
||||
$servers_pick_lists = ($servers_pick_lists | append { name: $server.hostname,
|
||||
id: $ssh_id, addr: $ssh_addr
|
||||
})
|
||||
}
|
||||
}
|
||||
let msg_sel = if $is_for_task {
|
||||
"Select one server"
|
||||
} else {
|
||||
"To connect to a server select one"
|
||||
}
|
||||
if ($servers_pick_lists | length) == 0 { return "" }
|
||||
let selection = if ($servers_pick_lists | length) > 1 {
|
||||
_print $"(_ansi default_dimmed)($msg_sel) \(use arrows and press [enter] or [esc] to cancel\):(_ansi reset)"
|
||||
($servers_pick_lists | each {|it| _print $"($it.name) -> ($it.addr)"})
|
||||
let pos_select = ($servers_pick_lists | each {|it| $"($it.name) -> ($it.addr)"} |input list --index)
|
||||
if $pos_select == null { return null }
|
||||
let selection = ($servers_pick_lists | get -o $pos_select)
|
||||
if not $is_for_task {
|
||||
_print $"\nFor (_ansi green_bold)($selection.name)(_ansi reset) server use:"
|
||||
}
|
||||
$selection
|
||||
} else {
|
||||
let selection = ($servers_pick_lists | get -o 0)
|
||||
if not $is_for_task {
|
||||
_print $"\n(_ansi default_dimmed)To connect to server (_ansi reset)(_ansi green_bold)($selection.name)(_ansi reset) use:"
|
||||
}
|
||||
$selection
|
||||
}
|
||||
if not $is_for_task {
|
||||
let id = ($selection | get -o id | default "")
|
||||
if ($id | is-not-empty) {
|
||||
show_clip_to $"ssh -i($id) ($selection.addr)" true
|
||||
}
|
||||
}
|
||||
$selection
|
||||
}
|
||||
def add_item_price [
|
||||
server: record
|
||||
already_created: bool
|
||||
resource: string
|
||||
item: string
|
||||
price: record
|
||||
host_color: string
|
||||
]: nothing -> record {
|
||||
let str_price_monthly = if $price.month < 10 { $" ($price.month)" } else { $"($price.month)" }
|
||||
let price_monthly = if ($str_price_monthly | str contains ".") { $str_price_monthly } else { $"($str_price_monthly).0"}
|
||||
if ($env.PROVISIONING_OUT | is-empty) {
|
||||
{
|
||||
host: $"(_ansi $host_color)($server.hostname)(_ansi reset)",
|
||||
item: $"(_ansi default_bold)($item)(_ansi reset)",
|
||||
resource: $"(_ansi blue_bold)($resource)(_ansi reset)",
|
||||
prov: $"(_ansi default_bold)($server.provider)(_ansi reset)",
|
||||
zone: $"(_ansi default_bold)($server.zone)(_ansi reset)",
|
||||
unit: ($price.unit_info | default "")
|
||||
hour: $"(_ansi default_bold) ($price.hour | fill -a left -c '0' -w 7 | str replace '.' ',') € (_ansi reset)",
|
||||
day: $"(_ansi default_bold) ($price.day | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') € (_ansi reset)",
|
||||
month: $"(_ansi default_bold) ($price_monthly | fill -a left -c '0' -w 7 | str replace '.' ',' | str replace ',0000' '') € (_ansi reset)",
|
||||
created: $already_created,
|
||||
}
|
||||
} else {
|
||||
{
|
||||
host: $server.hostname,
|
||||
item: $item,
|
||||
resource: $resource,
|
||||
prov: $server.provider,
|
||||
zone: $server.zone,
|
||||
unit: ($price.unit_info | default ""),
|
||||
hour: $"($price.hour | fill -a left -c '0' -w 7 | str replace '.' ',') €",
|
||||
day: $"($price.day | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') €",
|
||||
month: $"($price_monthly | fill -a left -c '0' -w 7 | str replace '.' ',' | str replace ',0000' '') €",
|
||||
created: $already_created,
|
||||
}
|
||||
}
|
||||
}
|
||||
export def servers_walk_by_costs [
|
||||
settings: record # Settings record
|
||||
match_hostname: string
|
||||
check: bool # Only check mode no servers will be created
|
||||
return_no_exists: bool
|
||||
outfile?: string
|
||||
]: nothing -> nothing {
|
||||
if $outfile != null { $env.PROVISIONING_NO_TERMINAL = true }
|
||||
if $outfile == null {
|
||||
_print $"\n (_ansi cyan)($settings.data | get -o main_title | default "")(_ansi reset) prices ($outfile)"
|
||||
}
|
||||
mut infra_servers = {}
|
||||
mut total_month = 0
|
||||
mut total_hour = 0
|
||||
mut total_day = 0
|
||||
mut table_items = []
|
||||
let total_color = { fg: '#ffff00' bg: '#0000ff' attr: b }
|
||||
|
||||
for server in $settings.data.servers {
|
||||
if $match_hostname != null and $match_hostname != "" and $server.hostname != $match_hostname { continue }
|
||||
if ($infra_servers | is-empty) or ($infra_servers | get -o $server.provider
|
||||
| if ($in | describe | str starts-with "record") { [$in] } else { $in } | default []
|
||||
| where {|it| $it.zone? != null and $it.zone == $server.zone and $it.plan? == null and $it.plan == $server.plan} | length) == 0 {
|
||||
$infra_servers = ($infra_servers | merge { $server.provider: (mw_load_infra_servers_info $settings $server false)} )
|
||||
}
|
||||
if ($infra_servers | get -o $server.provider
|
||||
| if ($in | describe | str starts-with "record") { [$in] } else { $in } | default []
|
||||
| where {|it| $it.zone? != null and $it.zone == $server.zone and $it.store? != null and ($it.store | is-not-empty) } | length) == 0 {
|
||||
let store_data = (mw_load_infra_storages_info $settings $server false)
|
||||
if ($store_data |is-not-empty ) {
|
||||
$infra_servers = ($infra_servers | merge { $server.provider: (mw_load_infra_storages_info $settings $server false)} )
|
||||
}
|
||||
}
|
||||
if ($infra_servers | is-empty) or ($infra_servers | get -o $server.provider | is-empty) { continue }
|
||||
let item = { item: (mw_get_infra_item $server $settings $infra_servers false), target: "server" }
|
||||
if ($item | get -o item | is-empty) { continue }
|
||||
#if $env.PROVISIONING_DEBUG_CHECK { _print ($item | table -e)}
|
||||
|
||||
let already_created = (mw_server_exists $server false)
|
||||
let host_color = if $already_created { "green_bold" } else { "red" }
|
||||
|
||||
let price_hour = (mw_get_infra_price $server $item "hour" false)
|
||||
let price = {
|
||||
hour: $price_hour,
|
||||
month: ((mw_get_infra_price $server $item "month" false) | math round -p 4)
|
||||
day : (($price_hour * 24) | math round -p 4)
|
||||
unit_info: (mw_get_infra_price $server $item "unit" false)
|
||||
}
|
||||
let str_server_plan = if ($server.reqplan? != null ) {
|
||||
$"($server.reqplan.cores | default 1)xCPU-(($server.reqplan.memory | default 1024) / 1024)GB ($server.plan)"
|
||||
} else { $server.plan }
|
||||
if ($price.hour > 0 or $price.month > 0) {
|
||||
$total_month += $price.month
|
||||
$total_hour += $price.hour
|
||||
$total_day += ($price.day)
|
||||
$table_items = ($table_items | append (add_item_price $server $already_created $str_server_plan "server" $price $host_color))
|
||||
}
|
||||
for it in ($server | get -o storages | default [] | enumerate) {
|
||||
let storage = $it.item
|
||||
let storage_item = { item: (mw_get_infra_storage $server $settings $infra_servers false), target: "storage", src: $it }
|
||||
if ($storage_item | get -o item | is-empty) { continue }
|
||||
#if $env.PROVISIONING_DEBUG_CHECK { _print ($storage_item | table -e)}
|
||||
let storage_size = if ($storage | get -o parts | length) > 0 {
|
||||
($storage | get -o parts | each {|part| $part | get -o size | default 0} | math sum)
|
||||
} else {
|
||||
($storage | get -o size | default 0)
|
||||
}
|
||||
if $storage_size > 0 {
|
||||
let storage_targets = if ($storage | get -o parts | length) > 0 {
|
||||
($storage | get -o parts | each {|part| $part | get -o mount_path | default ""} | str join " - ")
|
||||
} else {
|
||||
($storage | get -o mount_path | default "")
|
||||
}
|
||||
let store_price_month = ((mw_get_infra_price $server $storage_item "month" false) * $storage_size | math round -p 4 )
|
||||
let store_price_day = ((mw_get_infra_price $server $storage_item "day" false) * $storage_size | math round -p 4 )
|
||||
let store_price_hour = ((mw_get_infra_price $server $storage_item "hour" false) * $storage_size | math round -p 4 )
|
||||
let store_price = {
|
||||
month : $store_price_month,
|
||||
day : $store_price_day,
|
||||
hour : $store_price_hour
|
||||
unit_info: (mw_get_infra_price $server $storage_item "unit" false)
|
||||
}
|
||||
if ($store_price.hour > 0 or $store_price.month > 0) {
|
||||
$total_month += $store_price.month
|
||||
$total_hour += $store_price.hour
|
||||
$total_day += ($store_price.day)
|
||||
$table_items = ($table_items | append (add_item_price $server $already_created $"($storage_size) Gb ($storage_targets)" "store" $store_price $host_color))
|
||||
}
|
||||
}
|
||||
}
|
||||
if not $check {
|
||||
let already_created = (mw_server_exists $server false)
|
||||
if not ($already_created) {
|
||||
if $return_no_exists {
|
||||
return { status: false, error: $"($server.hostname) not created" }
|
||||
# _print $"(_ansi red_bold)($server.hostname)(_ansi reset) not created"
|
||||
}
|
||||
}
|
||||
}
|
||||
#{ status: true, error: "" }
|
||||
}
|
||||
if ($env.PROVISIONING_OUT | is-empty) {
|
||||
$table_items = ($table_items | append { host: "", item: "", resource: "", prov: "", zone: "", unit: "", month: "", day: "", hour: "", created: ""})
|
||||
}
|
||||
let str_total_month = if ($"($total_month)" | str contains ".") {
|
||||
($total_month | math round -p 4 | fill -a left -c '0' -w 7 | str replace ',0000' '')
|
||||
} else {
|
||||
($"($total_month).0" | fill -a left -c '0' -w 7 | str replace ',0000' '')
|
||||
}
|
||||
if ($env.PROVISIONING_OUT | is-empty) {
|
||||
$table_items = ($table_items | append {
|
||||
host: $"(_ansi --escape $total_color) TOTAL (_ansi reset)",
|
||||
item: $"(_ansi default_bold) (_ansi reset)",
|
||||
resource: $"(_ansi default_bold) (_ansi reset)",
|
||||
prov: $"(_ansi default_bold) (_ansi reset)",
|
||||
zone: $"(_ansi default_bold) (_ansi reset)",
|
||||
unit: $"(_ansi default_bold) (_ansi reset)",
|
||||
hour: $"(_ansi --escape $total_color) ($total_hour | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') € (_ansi reset)",
|
||||
day: $"(_ansi --escape $total_color) ($total_day | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') € (_ansi reset)",
|
||||
month:$"(_ansi --escape $total_color) ($str_total_month | str replace '.' ',' | str replace ',0000' '') € (_ansi reset)"
|
||||
created: $"(_ansi default_bold) (_ansi reset)",
|
||||
})
|
||||
} else {
|
||||
$table_items = ($table_items | append {
|
||||
host: "TOTAL",
|
||||
item: "",
|
||||
resource: "",
|
||||
prov: "",
|
||||
zone: "",
|
||||
unit: "",
|
||||
hour: $"(_ansi --escape $total_color)($total_hour | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') €(_ansi reset)",
|
||||
day: $"(_ansi --escape $total_color)($total_day | math round -p 4 | fill -a left -c '0' -w 7 | str replace '.' ',') €(_ansi reset)",
|
||||
month:$"(_ansi --escape $total_color)($str_total_month | str replace '.' ',' | str replace ',0000' '') €(_ansi reset)"
|
||||
created: false,
|
||||
})
|
||||
}
|
||||
if $outfile != null {
|
||||
if ($outfile == "stdout") {
|
||||
return $table_items
|
||||
} else if ($outfile | str ends-with ".json") {
|
||||
$table_items | to json | save --force $outfile
|
||||
} else if ($outfile | str ends-with ".yaml") {
|
||||
$table_items | to yaml | save --force $outfile
|
||||
} else if ($outfile | str ends-with ".csv") {
|
||||
$table_items | to csv | save --force $outfile
|
||||
} else if ($outfile | str ends-with ".table") {
|
||||
$table_items | table -e | save --force $outfile
|
||||
} else {
|
||||
$table_items | to text | save --force $outfile
|
||||
}
|
||||
$env.PROVISIONING_NO_TERMINAL = false
|
||||
_print $"Prices saved in (_ansi cyan_bold)($outfile)(_ansi reset) "
|
||||
} else {
|
||||
$env.PROVISIONING_NO_TERMINAL = false
|
||||
match $env.PROVISIONING_OUT {
|
||||
"json" => { _print ($table_items | to json) "json" "result" "table" },
|
||||
"yaml" => { _print ($table_items | to yaml) "yaml" "result" "table" },
|
||||
_ => { _print ($table_items | table -i false) },
|
||||
}
|
||||
}
|
||||
}
|
||||
export def wait_for_servers [
|
||||
settings: record
|
||||
check: bool
|
||||
ip_type: string = "public"
|
||||
]: nothing -> bool {
|
||||
mut server_pos = 0
|
||||
mut has_errors = false
|
||||
for srvr in $settings.data.servers {
|
||||
$server_pos += 1
|
||||
let ip = if $env.PROVISIONING_DEBUG_CHECK or $check {
|
||||
"127.0.0.1"
|
||||
} else {
|
||||
let curr_ip = (mw_get_ip $settings $srvr $ip_type false | default "")
|
||||
if $curr_ip == "" {
|
||||
_print $"🛑 No IP ($ip_type) found for (_ansi green_bold)($srvr.hostname)(_ansi reset) ($server_pos) "
|
||||
$has_errors = true
|
||||
continue
|
||||
}
|
||||
#use utils.nu wait_for_server
|
||||
if not (wait_for_server $server_pos $srvr $settings $curr_ip) {
|
||||
_print $"🛑 server ($srvr.hostname) ($curr_ip) (_ansi red_bold)not in running state(_ansi reset)"
|
||||
$has_errors = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
_print $"on (_ansi green_bold)($srvr.hostname)(_ansi reset) ($ip)"
|
||||
}
|
||||
$has_errors
|
||||
}
|
||||
export def provider_data_cache [
|
||||
settings: record
|
||||
--outfile (-o): string # Output file
|
||||
]: nothing -> nothing {
|
||||
mut cache_already_loaded = []
|
||||
for server in ($settings.data.servers? | default []) {
|
||||
_print $"server (_ansi green)($server.hostname)(_ansi reset) on (_ansi blue)($server.provider)(_ansi reset)"
|
||||
if ($cache_already_loaded | where {|it| $it == $server.provider} |length) > 0 { continue } else { $cache_already_loaded = ($cache_already_loaded | append $server.provider)}
|
||||
let provider_path = (get_provider_data_path $settings $server)
|
||||
#use ../lib_provisioning/utils/settings.nu load_provider_env
|
||||
let data = (load_provider_env $settings $server $provider_path)
|
||||
if ($data | is-empty) {
|
||||
_print $"❗server ($server.hostname) no data in cache path found ($provider_path | path basename)"
|
||||
exit
|
||||
}
|
||||
let outfile_path = if ($outfile | is-not-empty) { ($outfile | path dirname | path join $"($server.provider)_($outfile | path basename)") } else { "" }
|
||||
if ($outfile_path | is-not-empty ) {
|
||||
let out_extension = (get_file_format $outfile_path)
|
||||
if $out_extension == "json" {
|
||||
($data | to json | save --force $outfile_path)
|
||||
} else {
|
||||
($data | to yaml | save --force $outfile_path)
|
||||
}
|
||||
if ($outfile_path | path exists) {
|
||||
_print $"✅ (_ansi green_bold)($server.provider)(_ansi reset) (_ansi cyan_bold)cache settings(_ansi reset) saved in (_ansi yellow_bold)($outfile_path)(_ansi reset)"
|
||||
_print $"To create a (_ansi purple)kcl(_ansi reset) for (_ansi cyan)defs(_ansi reset) file use:"
|
||||
let k_file_path = $"($outfile_path | str replace $'.($out_extension)' '').k"
|
||||
^kcl import ($outfile_path) -o ($k_file_path) --force
|
||||
^sed -i '1,4d;s/^{/_data = {/' $k_file_path
|
||||
'{ main = _data.main, priv = _data.priv }' | tee {save -a $k_file_path} | ignore
|
||||
let res = ( ^kcl $k_file_path | complete)
|
||||
if $res.exit_code == 0 {
|
||||
$res.stdout | save $"($k_file_path).yaml" --force
|
||||
^kcl import $"($k_file_path).yaml" -o ($k_file_path) --force
|
||||
^sed -i '1,4d;s/^{/_data = {/' $k_file_path
|
||||
let content = (open $k_file_path --raw)
|
||||
let comment = $"# ($server.provider)" + " environment settings, if not set will be autogenerated in 'provider_path' (data/" + $server.provider + "_cache.yaml)"
|
||||
let from_scratch = (mw_start_cache_info $settings $server)
|
||||
($"# Info: KCL Settings created by ($env.PROVISIONING_NAME)\n# Date: (date now | format date '%Y-%m-%d %H:%M:%S')\n\n" +
|
||||
$"($comment)\n($from_scratch)" +
|
||||
$"# Use a command like: '($env.PROVISIONING_NAME) server cache -o /tmp/data.yaml' to genereate '/tmp/($server.provider)_data.k' for 'defs' settings\n" +
|
||||
$"# then you can move genereated '/tmp/($server.provider)_data.k' to '/defs/($server.provider)_data.k' \n\n" +
|
||||
$"import ($server.provider)_prov\n" +
|
||||
($content | str replace '_data = {' $"($server.provider)_prov.Provision_($server.provider) {") | save $k_file_path --force
|
||||
)
|
||||
let result = (encrypt_secret $k_file_path --quiet)
|
||||
if ($result | is-not-empty) { ($result | save --force $k_file_path) }
|
||||
_print $"(_ansi purple)kcl(_ansi reset) for (_ansi cyan)defs(_ansi reset) file has been created at (_ansi green)($k_file_path)(_ansi reset)"
|
||||
}
|
||||
#show_clip_to $"kcl import ($outfile_path) -o ($k_file_path) --force ; sed -i '1,4d;s/^{/_data = {/' ($k_file_path) ; echo '{ main = _data.main, priv = _data.priv }' >> ($k_file_path)" true
|
||||
}
|
||||
} else {
|
||||
let cmd = ($env| get -o PROVISIONING_FILEVIEWER | default (if (^bash -c "type -P bat" | is-not-empty) { "bat" } else { "cat" }))
|
||||
if $cmd != "bat" { _print $"(_ansi magenta_bold)----------------------------------------------------------------------------------------------------------------(_ansi reset)"}
|
||||
if $env.PROVISIONING_WK_FORMAT == "json" {
|
||||
($data | to json | run-external $cmd -)
|
||||
} else {
|
||||
($data | to yaml | run-external $cmd -)
|
||||
}
|
||||
if $cmd != "bat" { _print $"(_ansi magenta_bold)----------------------------------------------------------------------------------------------------------------(_ansi reset)"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def find_server [
|
||||
item: string
|
||||
servers: list,
|
||||
out: string,
|
||||
]: nothing -> record {
|
||||
if ($item | parse --regex '^[0-9]' | length) > 0 {
|
||||
let pos = ($item | into int)
|
||||
if ($pos >= ($servers | length)) {
|
||||
if ($out | is-empty) { _print $"No server index ($pos) found "}
|
||||
{}
|
||||
} else {
|
||||
($servers | get -o ($item | into int) | default {})
|
||||
}
|
||||
} else {
|
||||
($servers | where {|s| ( $s | get -o hostname | default "") == $item} | get -o 0 | default {})
|
||||
}
|
||||
}
|
||||
export def find_serversdefs [
|
||||
settings: record
|
||||
]: nothing -> record {
|
||||
let src_path = ($settings | get -o src_path | default "")
|
||||
mut defs = []
|
||||
for it in ($settings | get -o data | get -o servers_paths | default []) {
|
||||
let name = ($it| str replace "/" "_")
|
||||
let it_path = if ($it | str ends-with ".k") { $it } else { $"($it).k" }
|
||||
let path_def = ($src_path | path join $it_path )
|
||||
let defs_srvs = if ($path_def | path exists ) {
|
||||
(open -r $path_def)
|
||||
} else { "" }
|
||||
$defs = ($defs | append {
|
||||
name: $name, path_def: $it_path, def: $defs_srvs, defaults: ""
|
||||
}
|
||||
)
|
||||
}
|
||||
let defaults_path = ($env.PROVISIONING | path join "kcl" | path join "defaults.k")
|
||||
let defaults = if ($defaults_path | path exists) {
|
||||
(open -r $defaults_path | default "")
|
||||
} else { "" }
|
||||
let path_main = ($env.PROVISIONING | path join "kcl" | path join "server.k")
|
||||
let main = if ($path_main | path exists) {
|
||||
(open -r $path_main | default "")
|
||||
} else { "" }
|
||||
let prov_defs = if ($env.PROVISIONING_PROVIDERS_PATH? == null) {
|
||||
{
|
||||
defs_providers: [],
|
||||
providers: [],
|
||||
}
|
||||
} else {
|
||||
let providers_list = (ls -s $env.PROVISIONING_PROVIDERS_PATH | where {|it| (
|
||||
($it.name | str starts-with "_") == false
|
||||
and ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name | path type) == "dir"
|
||||
and ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name | path join "templates" | path exists)
|
||||
)
|
||||
})
|
||||
let defs_providers = ($providers_list | each {|it|
|
||||
let it_path = ($src_path| path join "defs")
|
||||
let defaults = if ($it_path | path join $"($it.name)_defaults.k" | path exists) {
|
||||
(open -r ($it_path | path join $"($it.name)_defaults.k"))
|
||||
} else { "" }
|
||||
let def = if ($it_path | path join "servers.k" | path exists) {
|
||||
(open -r ($it_path | path join "servers.k"))
|
||||
} else { "" }
|
||||
{
|
||||
name: $it.name, path_def: $it_path, def: $def, defaults: $defaults
|
||||
}
|
||||
} | default [])
|
||||
let providers = ($providers_list | each {|it|
|
||||
let it_path = ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name | path join "kcl")
|
||||
let defaults = if ($it_path | path join $"defaults_($it.name).k" | path exists) {
|
||||
(open -r ($it_path | path join $"defaults_($it.name).k"))
|
||||
} else { "" }
|
||||
let def = if ($it_path | path join $"server_($it.name).k" | path exists) {
|
||||
(open -r ($it_path | path join $"server_($it.name).k"))
|
||||
} else { "" }
|
||||
{
|
||||
name: $it.name, path_def: $it_path, def: $def, defaults: $defaults
|
||||
}
|
||||
} | default [])
|
||||
{
|
||||
defs_providers: $defs_providers,
|
||||
providers: $providers,
|
||||
}
|
||||
}
|
||||
{
|
||||
defaults: $defaults,
|
||||
path_main: $path_main,
|
||||
main: $main,
|
||||
providers: $prov_defs.providers,
|
||||
defs_providers: $prov_defs.defs_providers,
|
||||
defs: $defs
|
||||
}
|
||||
}
|
||||
export def find_provgendefs [
|
||||
]: nothing -> record {
|
||||
let prov_defs = if ($env.PROVISIONING_PROVIDERS_PATH? == null) {
|
||||
{
|
||||
defs_providers: [],
|
||||
}
|
||||
} else {
|
||||
let providers_list = (ls -s $env.PROVISIONING_PROVIDERS_PATH | where {|it| (
|
||||
($it.name | str starts-with "_") == false
|
||||
and ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name | path type) == "dir"
|
||||
and ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name | path join "templates" | path exists)
|
||||
)
|
||||
})
|
||||
mut provdefs = []
|
||||
for it in $providers_list {
|
||||
let it_defs_path = ($env.PROVISIONING_PROVIDERS_PATH | path join $it.name
|
||||
| path join $env.PROVISIONING_GENERATE_DIRPATH
|
||||
| path join $env.PROVISIONING_GENERATE_DEFSFILE)
|
||||
if ($it_defs_path | path exists) {
|
||||
$provdefs = ($provdefs | append { name: $it.name, defs: (open $it_defs_path) })
|
||||
}
|
||||
}
|
||||
$provdefs
|
||||
}
|
||||
$prov_defs
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue