#!/usr/bin/env nu 
# Info: Prepare for kubernetes default installation
# Author: JesusPerezLorenzo 
# Release: 1.0.2
# Date: 30-12-2023

use lib_provisioning/cmd/env.nu * 
use lib_provisioning/cmd/lib.nu *

use lib_provisioning/utils/ui.nu *
use lib_provisioning/plugins_defs.nu port_scan

print $"(_ansi green_bold)OS(_ansi reset) with ($env.PROVISIONING_VARS) " 

let settings = load_defs

if $env.PROVISIONING_RESOURCES == null { 
  print $"🛑 PROVISIONING_RESOURCES not found"  
  exit 1
}
let resources_path = $env.PROVISIONING_RESOURCES
if not ($resources_path | path exists) {  ^mkdir -p $resources_path  }

def main [] { 
  let cp_hostname = ($settings.taskserv | get -i cp_hostname | default "")
  if ($cp_hostname | is-empty) { 
    print $"🛑 Error (_ansi red_bold)prepare ($settings.taskserv.name) (_ansi reset) (_ansi green_bold) no cp_hostname(_ansi reset)" 
    exit 
  }
  let target_server = ($settings.defs.servers | filter {|srv| $srv.hostname == $cp_hostname } | get -i 0)
  let cp_pub_ip = ($target_server | get -i network_public_ip | default "127.0.0.1")
  if ($target_server | get -i hostname | is-empty) { 
    print $"🛑 Error (_ansi red_bold)prepare(_ansi reset) server (_ansi green_bold)($cp_hostname)(_ansi reset)" 
    exit 1
  }
  let cp_pub_ip = ($target_server | get -i network_public_ip | default "127.0.0.1")
  if ($cp_pub_ip | is-empty) {
    print $"🛑 Error (_ansi red_bold)cp_public_ip(_ansi reset) for server (_ansi green_bold)($cp_hostname)(_ansi reset)" 
    exit 1
  }
  let src_target_path =  ($settings.taskserv | get -i target_path | default "") 
  let target_path =  if ($src_target_path | str starts-with "/")  { $src_target_path } else { ($env.PROVISIONING_WK_ENV_PATH | path join $src_target_path) } 
  let save_target_path = ($settings.defs.created_taskservs_dirpath | path join ($target_path | path basename))
  if ($save_target_path | path exists) { 
    cp $save_target_path  $target_path 
    print $"(_ansi blue_bold)($save_target_path)(_ansi reset) already exists, copied into (_ansi blue_bold)($target_path)(_ansi reset)"
    exit 
  }
  let str_target_host = ($settings.taskserv | get -i admin_host | default $cp_pub_ip)
  let target_port = ($settings.taskserv | get -i admin_port | default 22)
  let target_host = (open /etc/hosts | grep $str_target_host | lines  | get -i 0 | default "" | split row " " | get -i 0)
  if ($env.PROVISIONING_ARGS? | default "" | str contains "--check ") or ($env.PROVISIONING_ARGS? | default "" | str contains "-c ") { 
    print (
      $"\n(_ansi red)Check mode no connection(_ansi reset) to (_ansi blue)($target_host)(_ansi reset) " + 
      $"(_ansi blue_bold)($target_port)(_ansi reset) (_ansi red_bold)failed(_ansi reset) "
    )
    exit 
  }
  if not (port_scan $target_host $target_port 1) {
    print (
      $"\n🛑 (_ansi red)Error connection(_ansi reset) to (_ansi blue)($target_host)(_ansi reset) " + 
      $"(_ansi blue_bold)($target_port)(_ansi reset) (_ansi red_bold)(_ansi reset) "
    )
    exit 1
  } 
  let ssh_loglevel = if $env.PROVISIONING_DEBUG {
    "-o LogLevel=info"
  } else { 
    "-o LogLevel=quiet"
  }
  let ssh_ops  = [StrictHostKeyChecking=accept-new UserKnownHostsFile=/dev/null]
  let k8s_nodes = "kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{\"\\n\"}{end}'"
  let res = (^ssh "-o" ($ssh_ops | get -i 0) "-o" ($ssh_ops | get -i 1) "-o" IdentitiesOnly=yes $ssh_loglevel
    "-i" ($settings.taskserv.ssh_key_path | str replace ".pub" "")
    $"($settings.taskserv | get -i admin_user)@($target_host)" ($k8s_nodes) | complete) 
  if $res.exit_code != 0 {
    print $"❗ run ($k8s_nodes) in ($settings.taskserv | get -i admin_host) errors ($res.stdout ) "
    exit 1
  } 
  if ($res.stdout | find $target_host | get -i 0 | default  "" | is-not-empty)  { 
    print $"node ($target_host) already in cluster "
    exit
  } 
  let remote_cmd = ($settings | get -i taskserv | get -i source_cmd | default "")
  if $env.PROVISIONING_DEBUG {
    print $"Run ($remote_cmd) in ($settings.taskserv | get -i admin_user)@($target_host)"
  }
  let res = (^ssh "-o" ($ssh_ops | get -i 0) "-o" ($ssh_ops | get -i 1) "-o" IdentitiesOnly=yes $ssh_loglevel
    "-i" ($settings.taskserv.ssh_key_path | str replace ".pub" "")
    $"($settings.taskserv | get -i admin_user)@($target_host)" ($remote_cmd) | complete) 
  if $res.exit_code != 0 {
      print $"❗ run ($remote_cmd) in ($settings.taskserv | get -i admin_host) errors ($res.stdout ) "
      exit 1
  }
  let source_path =  ($settings.taskserv | get -i source_path | default "") 
  let res = (^scp "-o" ($ssh_ops | get -i 0) "-o" ($ssh_ops | get -i 1) "-o" IdentitiesOnly=yes $ssh_loglevel
    "-i" ($settings.taskserv.ssh_key_path | str replace ".pub" "")
    $"($settings.taskserv | get -i admin_user)@($target_host):($source_path)" $target_path | complete) 
  if $res.exit_code != 0 {
      print $"❗ run scp ($source_path) in ($settings.taskserv | get -i admin_host) errors ($res.stdout ) "
      exit 1
  }
  if $env.PROVISIONING_DEBUG { print $res.stdout }
}
