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
9
providers/aws/bin/create-default-subnet.sh
Executable file
9
providers/aws/bin/create-default-subnet.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
[ -z "$AWS_PROFILE" ] || [ ! -r "$HOME/.aws/credentials" ] && echo "AWS credentials not found" && exit 1
|
||||
|
||||
[ -z "$1" ] && echo "No zone provided (example eu-west-1)" && exit 1
|
||||
|
||||
aws ec2 create-default-subnet --availability-zone ${1}a
|
||||
aws ec2 create-default-subnet --availability-zone ${1}b
|
||||
aws ec2 create-default-subnet --availability-zone ${1}c
|
||||
4
providers/aws/bin/get-image.sh
Executable file
4
providers/aws/bin/get-image.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
match="debian-12-amd64"
|
||||
aws ec2 describe-images --owners --out json | jq '.Images[] | select( .Name | contains("'$match'")) '
|
||||
125
providers/aws/bin/install.sh
Executable file
125
providers/aws/bin/install.sh
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
#!/bin/bash
|
||||
# Info: Script to install aws tools
|
||||
# Author: JesusPerezLorenzo
|
||||
# Release: 1.0
|
||||
# Date: 15-04-2024
|
||||
|
||||
[ "$DEBUG" == "-x" ] && set -x
|
||||
|
||||
USAGE="install-tools [ tool-name: tera k9s, etc | all] [--update]
|
||||
As alternative use environment var TOOL_TO_INSTALL with a list-of-tools (separeted with spaces)
|
||||
Versions are set in ./versions file
|
||||
|
||||
This can be called by directly with an argumet or from an other srcipt
|
||||
"
|
||||
|
||||
ORG=$(pwd)
|
||||
function _info_tools {
|
||||
local match=$1
|
||||
local info_keys
|
||||
info_keys="info version site"
|
||||
|
||||
if [ -z "$match" ] || [ "$match" == "all" ] || [ "$match" == "-" ]; then
|
||||
match="all"
|
||||
fi
|
||||
echo "$PROVIDER_TITLE"
|
||||
[ ! -r "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" ] && return
|
||||
echo "-------------------------------------------------------"
|
||||
case "$match" in
|
||||
"i" | "?" | "info")
|
||||
for key in $info_keys
|
||||
do
|
||||
echo -n "$key:"
|
||||
[ "$key" != "version" ] && echo -ne "\t"
|
||||
echo " $(grep "^$key:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$key: //g")"
|
||||
done
|
||||
;;
|
||||
"all")
|
||||
cat "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml"
|
||||
;;
|
||||
*)
|
||||
echo -e "$match:\t $(grep "^$match:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$match: //g")"
|
||||
esac
|
||||
echo "________________________________________________________"
|
||||
}
|
||||
function _install_tools {
|
||||
local match=$1
|
||||
shift
|
||||
local options
|
||||
options="$*"
|
||||
local has_aws
|
||||
local aws_version
|
||||
|
||||
OS="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
ORG_OS=$(uname)
|
||||
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')"
|
||||
ORG_ARCH="$(uname -m)"
|
||||
|
||||
AWS_VERSION=${AWS_AWS_VERSION:-}
|
||||
if [ -n "$AWS_VERSION" ] && [ "$match" == "all" ] || [ "$match" == "aws" ] ; then
|
||||
[ -r "/usr/bin/aws" ] && mv /usr/bin/aws /usr/bin/_aws
|
||||
has_aws=$(type -P aws)
|
||||
num_version=0
|
||||
[ -n "$has_aws" ] && aws_version=$(aws --version | cut -f1 -d" " | sed 's,aws-cli/,,g') && num_version=${aws_version//\./}
|
||||
[ -z "$num_version" ] && num_version=0
|
||||
expected_version_num=${AWS_VERSION//\./}
|
||||
if [ -z "$CHECK_ONLY" ] && [ "$num_version" -ne "$expected_version_num" ] ; then
|
||||
cd "$ORG" || exit 1
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-${OS}-${ORG_ARCH}.zip" -o "/tmp/awscliv2.zip"
|
||||
cd /tmp
|
||||
unzip awscliv2.zip >/dev/null
|
||||
[ "$1" != "-update" ] && [ -d "/usr/local/aws-cli" ] && sudo rm -rf "/usr/local/aws-cli"
|
||||
sudo ./aws/install && printf "%s\t%s\n" "aws" "installed $AWS_VERSION"
|
||||
#sudo ./aws/install $options && echo "aws cli installed"
|
||||
cd "$ORG" && rm -rf /tmp/awscliv2.zip /tmp/aws
|
||||
elif [ -n "$CHECK_ONLY" ] ; then
|
||||
printf "%s\t%s\t%s\n" "aws" "$aws_version" "expected $AWS_VERSION"
|
||||
else
|
||||
printf "%s\t%s\n" "aws" "already $AWS_VERSION"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
function _on_tools {
|
||||
local tools_list=$1
|
||||
[ -z "$tools_list" ] || [[ "$tools_list" == -* ]] && tools_list=${TOOL_TO_INSTALL:-all}
|
||||
case $tools_list in
|
||||
"all")
|
||||
_install_tools "all" "$@"
|
||||
;;
|
||||
"info" | "i" | "?")
|
||||
shift
|
||||
_info_tools "$@"
|
||||
;;
|
||||
*)
|
||||
for tool in $tools_list
|
||||
do
|
||||
[[ "$tool" == -* ]] && continue
|
||||
_install_tools "$tool" "${*//$tool/}"
|
||||
done
|
||||
esac
|
||||
}
|
||||
|
||||
set -o allexport
|
||||
## shellcheck disable=SC1090
|
||||
[ -n "$PROVISIONING_ENV" ] && [ -r "$PROVISIONING_ENV" ] && source "$PROVISIONING_ENV"
|
||||
[ -r "../env-provisioning" ] && source ../env-provisioning
|
||||
[ -r "env-provisioning" ] && source ./env-provisioning
|
||||
set +o allexport
|
||||
|
||||
export PROVISIONING=${PROVISIONING:-/usr/local/provisioning}
|
||||
|
||||
PROVIDERS_PATH=${PROVIDERS_PATH:-"$PROVISIONING/providers"}
|
||||
|
||||
PROVIDER_NAME="aws"
|
||||
PROVIDER_TITLE="AWS"
|
||||
|
||||
if [ -r "$(dirname "$0")/../versions" ] ; then
|
||||
. "$(dirname "$0")"/../versions
|
||||
elif [ -r "$(dirname "$0")/versions" ] ; then
|
||||
. "$(dirname "$0")"/versions
|
||||
fi
|
||||
|
||||
[ "$1" == "-h" ] && echo "$USAGE" && shift
|
||||
[ "$1" == "check" ] && CHECK_ONLY="yes" && shift
|
||||
[ -n "$1" ] && cd /tmp && _on_tools "$@"
|
||||
[ -z "$1" ] && _on_tools
|
||||
31
providers/aws/bin/on-ssh.sh
Executable file
31
providers/aws/bin/on-ssh.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
USAGE="on-ssh.sh show|describe | create (key-name) | import (pub-key-path) | delete (key-name)
|
||||
reference: https://docs.aws.amazon.com/cli/latest/reference/ec2/import-key-pair.html
|
||||
"
|
||||
[ -z "$AWS_PROFILE" ] || [ ! -r "$HOME/.aws/credentials" ] && echo "AWS credentials not found" && exit 1
|
||||
|
||||
case "$1" in
|
||||
show|describe)
|
||||
aws ec2 describe-key-pairs
|
||||
;;
|
||||
create)
|
||||
[ -z "$2" ] && echo "No name to create ssh found" && exit 1
|
||||
aws ec2 create-key-pair \
|
||||
--key-name "$2" \
|
||||
--key-type ed25519 \
|
||||
--query 'KeyMaterial' --output text
|
||||
;;
|
||||
import)
|
||||
[ -z "$2" ] && echo "No name to reate ssh found" && exit 1
|
||||
[ ! -r "$HOME/.ssh/$2" ] && echo "No public key found in $HOME/.ssh/$2" && exit 1
|
||||
--out json | jq -r '.InstanceStatuses[] | select(.InstanceState.Name == "running")aws ec2 import-key-pair --key-name "$2" --public-key-material fileb://~/.ssh/$2
|
||||
;;
|
||||
delete)
|
||||
[ -z "$2" ] && echo "No name for create ssh found" && exit 1
|
||||
aws ec2 delete-key-pair --key-name "$2"
|
||||
;;
|
||||
-h|help) echo "$USAGE"
|
||||
;;
|
||||
*) echo "Option $1 not defined"
|
||||
;;
|
||||
esac
|
||||
11
providers/aws/bin/public_ip_ec2.sh
Executable file
11
providers/aws/bin/public_ip_ec2.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
[ -z "$AWS_PROFILE" ] || [ ! -r "$HOME/.aws/credentials" ] && echo "AWS credentials not found" && exit 1
|
||||
|
||||
[ -z "$1" ] && echo "No instance id found" && exit 1
|
||||
|
||||
instace_id=$1
|
||||
|
||||
aws ec2 describe-instances --instance-ids $instance_id \
|
||||
--query 'Reservations[*].Instances[*].PublicIpAddress' \
|
||||
--output text
|
||||
91
providers/aws/nulib/aws/cache.nu
Normal file
91
providers/aws/nulib/aws/cache.nu
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/env nu
|
||||
# Info: AWS
|
||||
|
||||
use lib.nu *
|
||||
|
||||
export def aws_start_cache_info [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
( $"# To start from scratch set 'vpc' 'subnet' 'sg.id' to '?' then new AWS settings will be collected. This will create 'sg.perms'.\n" +
|
||||
$"# Removing 'provider_path' and 'defs/aws_data.k' would fallback to defaults with no settings for 'sg.name' and 'sg.perms', etc.\n"
|
||||
)
|
||||
}
|
||||
|
||||
export def aws_create_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
if $env.PROVISIONING_DEBUG { print $"❗ No settings found " }
|
||||
return
|
||||
}
|
||||
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) or ($data | get -o main | get -o vpc) == "?" {
|
||||
aws_scan_settings "create" $provider_path $settings $server false
|
||||
let new_data = (load_provider_env $settings $server $provider_path)
|
||||
if ($new_data | is-empty) or ($new_data | get -o main | get -o vpc) == "?" {
|
||||
print $"❗AWS no valid provider settings for (_ansi red)($server.hostname)(_ansi reset)"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"aws main data already exists in ($provider_path | path basename)"
|
||||
}
|
||||
}
|
||||
aws_scan_servers $provider_path $settings $server
|
||||
if $env.PROVISIONING_DEBUG { print $"Cache for ($server.provider) on ($server.hostname) saved in: ($provider_path | path basename)" }
|
||||
# load_provider_env $settings $server $provider_path
|
||||
}
|
||||
export def aws_read_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
print $"❗ No settings found "
|
||||
return
|
||||
}
|
||||
}
|
||||
export def aws_clean_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
print $"❗ No settings found "
|
||||
return
|
||||
}
|
||||
let provider_path = (get_provider_data_path $settings $server)
|
||||
let data = if ($provider_path | path exists) {
|
||||
open $provider_path
|
||||
} else {
|
||||
{ servers: null }
|
||||
}
|
||||
if ($data.servers? != null) and ($data.servers | where {|it| ($it.hostname? | default "") == $server.hostname} | length) == 0 {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"❗server ($server.hostname) already deleted from ($provider_path | path basename)"
|
||||
}
|
||||
}
|
||||
let all_servers = ( $data.servers? | default [] | where {|it| $it.hostname != $server.hostname})
|
||||
if $env.PROVISIONING_DEBUG { print $"Cache for ($server.provider) delete ($server.hostname) in: ($provider_path | path basename)" }
|
||||
let new_data = if ($all_servers | length) == 0 {
|
||||
aws_delete_settings "all" $provider_path $settings $server
|
||||
{}
|
||||
} else {
|
||||
( $data | merge { servers: $all_servers})
|
||||
}
|
||||
save_provider_env $new_data $settings $provider_path
|
||||
}
|
||||
export def aws_ip_from_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let prov_settings = ($settings.providers | find $server.provider ) #| get -o settings)
|
||||
if ($prov_settings | is-empty) == null { return "" }
|
||||
($prov_settings | flatten | find $server.hostname | select -o ip_addresses | find "public"| get -o address | get -o 0 | default "")
|
||||
}
|
||||
5
providers/aws/nulib/aws/env.nu
Normal file
5
providers/aws/nulib/aws/env.nu
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export-env {
|
||||
$env.AWS_API_URL = ($env | get -o AWS_API_URL | default "")
|
||||
$env.AWS_AUTH = ($env | get -o AWS_AUTH | default "")
|
||||
$env.AWS_INTERFACE = ($env | get -o AWS_INTERFACE | default "CLI") # API or CLI
|
||||
}
|
||||
715
providers/aws/nulib/aws/lib.nu
Normal file
715
providers/aws/nulib/aws/lib.nu
Normal file
|
|
@ -0,0 +1,715 @@
|
|||
#!/usr/bin/env nu
|
||||
# Info: Script to create/delete AWS resources from file settings in bash with template/vars
|
||||
# Author: JesusPerez
|
||||
# Release: 1.0
|
||||
# Date: 26-03-2024
|
||||
|
||||
use ../../../../core/nulib/lib_provisioning/utils/templates.nu run_from_template
|
||||
|
||||
export def aws_review_credentials [
|
||||
] {
|
||||
print $"❗AWS credentials not found for '$PROVIDER_CLI_CMD' command."
|
||||
print $" Use default profile or env AWS_PROFILE from $HOME/.aws/credentials path or environment variables for settings"
|
||||
print $" More info: "
|
||||
print $" Profile mode: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html"
|
||||
print $" Evironment mode: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html"
|
||||
}
|
||||
export def aws_check_region [
|
||||
zone: string
|
||||
] {
|
||||
if ($zone |is-empty) {
|
||||
print $"❗AWS region zone ($env.AWS_DEFAULT_REGION) not found for '$PROVIDER_CLI_CMD' command."
|
||||
print $"Use set default profile or use env AWS_PROFILE with $HOME/.aws/credentials path or environment variables for settings"
|
||||
}
|
||||
(^aws ec2 describe-availability-zones --region $zone | complete).exit_code
|
||||
}
|
||||
export def aws_get_plan_info [
|
||||
var: string
|
||||
server: record
|
||||
] {
|
||||
let plan = ($server | get -o $var | default "")
|
||||
if ($plan | is-mepty) { return }
|
||||
let res = (^aws ec2 describe-instance-types --instance-types $plan
|
||||
--query 'InstanceTypes[].{ type: InstanceType, cores: VCpuInfo.DefaultCores, memory: MemoryInfo.SizeInMiB, arch: ProcessorInfo.SupportedArchitectures, gen: CurrentGeneration, infaces: NetworkInfo.MaximumNetworkInterfaces, ena: NetworkInfo.EnaSupport }'
|
||||
--out=json )
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | get -o 0 | default "")
|
||||
}
|
||||
}
|
||||
export def aws_find_plan [
|
||||
var: string
|
||||
server: record
|
||||
] {
|
||||
let reqplan = ($server | get -o $var | default "")
|
||||
if ($reqplan | is-mepty) {
|
||||
print $"❗No reqplan found in settings for ($var)"
|
||||
return 1
|
||||
}
|
||||
let res = (^ aws ec2 describe-instance-types --filters $"Name=processor-info.supported-architecture,Values=($reqplan.arch | default '')"
|
||||
$"Name=memory-info.size-in-mib,Values=($reqplan.memory | default '')"
|
||||
$"Name=vcpu-info.default-cores,Values=($reqplan.cores | default '')"
|
||||
$"Name=network-info.maximum-network-interfaces,Values=($reqplan.infaces | default '')"
|
||||
$"Name=network-info.ena-support,Values=($reqplan.ena | default '')"
|
||||
--query 'InstanceTypes[].{ type: InstanceType, cores: VCpuInfo.DefaultCores, memory: MemoryInfo.SizeInMiB, arch: ProcessorInfo.SupportedArchitectures, gen: CurrentGeneration, infaces: NetworkInfo.MaximumNetworkInterfaces, ena: NetworkInfo.EnaSupport }'
|
||||
--output json
|
||||
)
|
||||
if ($res.exit_code == 0) {
|
||||
($res.stdout | from json)
|
||||
}
|
||||
}
|
||||
export def aws_compare_plan_reqplan [
|
||||
var_plan: string
|
||||
var_reqplan: string
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let plan = ($server | get -o $var_plan)
|
||||
let check_plan = (aws_get_plan_info $var_plan $server)
|
||||
let reqplan = ($server | get -o $var_reqplan)
|
||||
|
||||
if ($plan | is-empty) or ( $check_plan | is-empty) {
|
||||
print $"❗No valid $plan found for $var_plan in $AWS_DEFAULT_REGION"
|
||||
return 1
|
||||
}
|
||||
if ($reqplan | is-empty) { return }
|
||||
|
||||
let plan_memory = ($check_plan | get -o memory | default "")
|
||||
let reqplan_memory = ($reqplan| get -o memory | default "")
|
||||
if $plan_memory != $reqplan_memory {
|
||||
print $"❗$plan memory does not match plan: $plan_memory expected $reqplan_memory"
|
||||
return 1
|
||||
}
|
||||
let plan_cores = ($check_plan | get -o cores | default "")
|
||||
let reqplan_cores = ($reqplan | get -o cores | default "")
|
||||
if $plan_cores != $reqplan_cores {
|
||||
print $"❗($plan) cores does not match plan: ($plan_cores) expected ($reqplan_cores)"
|
||||
return 1
|
||||
}
|
||||
let plan_archs = ($check_plan | get -o arch | default "")
|
||||
let reqplan_archs = ($reqplan | get -o arch | default "")
|
||||
if not ($plan_archs | str contains $reqplan_archs ) {
|
||||
print $"❗($plan) architectures does not match plan: ($plan_archs) expected ($reqplan_archs)"
|
||||
return 1
|
||||
}
|
||||
let plan_infaces = ($check_plan | get -o infaces | default "")
|
||||
let reqplan_infaces = ($reqplan | get -o infaces | default "")
|
||||
if $plan_infaces < $reqplan_infaces {
|
||||
print $"❗($plan) interfaces number does not match plan: ($plan_infaces) expected ($reqplan_infaces)"
|
||||
return 1
|
||||
}
|
||||
0
|
||||
}
|
||||
export def aws_get_os_image [
|
||||
name: string
|
||||
arch: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-images --owners amazon --filters $"'Name=name,Values=*'($name)'*'" $"'Name=architecture,Values=*'($arch)'*'"
|
||||
--query 'reverse(sort_by(Images,&CreationDate))[:5].{id:ImageId, name: Name, date:CreationDate}[0]' --output json
|
||||
)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json)
|
||||
} else { "" }
|
||||
}
|
||||
export def aws_delete_private_vpcs [
|
||||
aws_priv_cidr_block: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-vpcs --query Vpcs --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
for it in ($res.stdout | from json | where {|it| $it.CidrBlock == $aws_priv_cidr_block } | get -o VpcId | default []) {
|
||||
print $"delete vpc id ($it)"
|
||||
^aws ec2 delete-vpc --vpc-id "$it"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_create_private_vpc [
|
||||
aws_priv_cidr_block: string
|
||||
task: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-vpcs --query Vpcs --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-empty) {
|
||||
print $"❗Error ($task) vpcs ($aws_priv_cidr_block) "
|
||||
exit 1
|
||||
}
|
||||
let aws_priv_vpc = ($res.stdout | from json | where {|it| $it.CidrBlock == $aws_priv_cidr_block } | get -o 0 | get -o VpcId | default "")
|
||||
match $task {
|
||||
"create" => {
|
||||
if ($aws_priv_vpc | is-not-empty) {
|
||||
print $"Clean up VPC ($aws_priv_vpc)..."
|
||||
let res = (^aws ec2 delete-vpc --vpc-id $aws_priv_vpc err> /dev/null | complete )
|
||||
if $res.exit_code != 0 {
|
||||
print $"vpc ($aws_priv_vpc) delete error ($res.exit_code) ($res.stdout)"
|
||||
return $aws_priv_vpc
|
||||
}
|
||||
}
|
||||
let res = (^aws ec2 create-vpc --cidr-block $aws_priv_cidr_block --query Vpc.VpcId --output text | complete)
|
||||
if $res.exit_code == 0 {
|
||||
($res.stdout | str replace '"' '')
|
||||
} else {
|
||||
print $"❗ Error ($task) priv_vpc for ($aws_priv_cidr_block)"
|
||||
exit 1
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
$aws_priv_vpc
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_delete_sgs_by_name [
|
||||
aws_sg_name: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-security-groups --query SecurityGroups --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
let aws_sg_id = ($res.stdout | from json | where {|it| $it.GroupName == $aws_sg_name } | get -o GroupId | default "")
|
||||
if ($aws_sg_id | is-not-empty) {
|
||||
print $"Clean up SGs ($aws_sg_name)"
|
||||
^aws ec2 delete-security-group --group-id $aws_sg_id
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_delete_sgs [
|
||||
aws_vpc: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-security-groups --query SecurityGroups --out json)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
for it in ($res.stdout | from json | where {|it| $it.VpcId == $aws_vpc } | where {|it| $it.GroupName != "default" } | get -o GroupId | default "") {
|
||||
print $"delete security group id ($it)"
|
||||
^aws ec2 delete-security-group --group-id $it
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_create_sg_id [
|
||||
aws_vpc: string
|
||||
aws_sg_name: string
|
||||
task: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-security-groups --query SecurityGroups --out json | complete)
|
||||
if $res.exit_code != 0 or ($res.stdout | is-empty) {
|
||||
print $"❗Error ($task) sg_id for ($aws_sg_name) in ($aws_vpc)"
|
||||
exit 1
|
||||
}
|
||||
let aws_sg_id = ($res.stdout | from json | where {|it| $it.VpcId == $aws_vpc and $it.GroupName == $aws_sg_name } |
|
||||
get -o 0 | get -o GroupId | default "")
|
||||
match $task {
|
||||
"create" => {
|
||||
if ($aws_sg_id | is-not-empty) {
|
||||
print $"Clean up sg ($aws_sg_id) ..."
|
||||
let res = (^aws ec2 delete-security-group --group-id $aws_sg_id | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗Error delete ($aws_sg_id) for ($aws_sg_name) in ($aws_vpc)"
|
||||
return $aws_sg_id
|
||||
}
|
||||
}
|
||||
let res = (^aws ec2 create-security-group --group-name $aws_sg_name --description $"Group ($aws_sg_name)"
|
||||
--tag-specifications $"ResourceType=security-group,Tags=[{Key=Name,Value=($aws_sg_name)}]"
|
||||
--vpc-id ($aws_vpc | str trim) --out json | complete )
|
||||
if $res.exit_code == 0 {
|
||||
($res.stdout | from json | get -o GroupId | default "")
|
||||
} else {
|
||||
print $"❗Error ($task) sg_id for ($aws_sg_name) in ($aws_vpc)"
|
||||
exit 1
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
$aws_sg_id
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_add_sg_perms [
|
||||
sg_data: record
|
||||
server: record
|
||||
check_mode: bool
|
||||
] {
|
||||
let perms = ($sg_data | get -o perms | default [])
|
||||
if ($perms | is-empty) { return }
|
||||
let res = (^aws ec2 describe-security-groups --group-id $sg_data.id --query SecurityGroups[].IpPermissions --out json | complete)
|
||||
let curr_sg_perms = if $res.exit_code == 0 {
|
||||
($res.stdout | from json | get -o 0 | default [])
|
||||
} else { [] }
|
||||
mut curr_perms = []
|
||||
for p in $curr_sg_perms {
|
||||
mut ranges = ""
|
||||
for rng in ($p | get -o IpRanges) {
|
||||
if ($ranges | is-not-empty) { $ranges = $"($ranges),"}
|
||||
$ranges = $"($ranges){CidrIp=($rng.CidrIp)}"
|
||||
}
|
||||
let protocol = ($p | get -o IpProtocol | default "")
|
||||
let from_port = ($p | get -o FromPort | default "")
|
||||
let to_port = ($p | get -o ToPort | default "")
|
||||
for it in $perms {
|
||||
if ($protocol == ($it | get -o protocol ) and $from_port == ($it | get -o fromPort ) and
|
||||
$to_port == ($it | get -o toPort ) and
|
||||
$ranges == ($it | get -o ranges | str replace "[" "" | str replace "]" "" )) {
|
||||
} else {
|
||||
$curr_perms = ($curr_perms | append $p)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($curr_perms == $curr_sg_perms) and ($curr_perms| length) == ($perms | length) { return }
|
||||
if ($perms == $curr_perms) { return }
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"(_ansi green)current sg perms(_ansi reset) ($curr_perms | table -e)"
|
||||
}
|
||||
let wk_format = if $env.PROVISIONING_WK_FORMAT == "json" { "json" } else { "yaml" }
|
||||
let wk_vars = ( "/tmp/" | path join (mktemp --tmpdir-path "/tmp" --suffix $".($wk_format)" | path basename))
|
||||
let data = { sg_name: $sg_data.name, sg_id: $sg_data.id, perms: $perms, curr_perms: $curr_perms }
|
||||
if $wk_format == "json" {
|
||||
$data | to json | save --force $wk_vars
|
||||
} else {
|
||||
$data | to yaml | save --force $wk_vars
|
||||
}
|
||||
let run_file = ("/tmp" | path join $"onaws_run_sg_(mktemp --tmpdir-path "/tmp" --suffix ".sh" | path basename | str replace 'tmp.' '' )")
|
||||
let sg_template = ($env.PROVISIONING | path join "providers" | path join $server.provider | path join templates | path join "aws_sg.j2" )
|
||||
if not ($sg_template | path exists) {
|
||||
print $"❗($sg_template) not found for Security Groups ($sg_data.name)"
|
||||
exit 1
|
||||
}
|
||||
#use ../../../../core/nulib/lib_provisioning/utils/templates.nu run_from_template
|
||||
let res = if $check_mode {
|
||||
run_from_template $sg_template $wk_vars $run_file --check_mode
|
||||
} else {
|
||||
run_from_template $sg_template $wk_vars $run_file
|
||||
}
|
||||
if $res {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"(_ansi green)OK(_ansi reset) (_ansi green_bold)($sg_data.name)(_ansi reset)"
|
||||
} else {
|
||||
rm --force $wk_vars $run_file
|
||||
}
|
||||
} else {
|
||||
print $"(_ansi red)Failed(_ansi reset) (_ansi green_bold)($sg_data.name)(_ansi reset)"
|
||||
}
|
||||
}
|
||||
export def aws_delete_private_subnets [
|
||||
aws_priv_vpc: string
|
||||
aws_priv_cidr_block: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
for it in ($res.stdout | from json | where { |it| $it.VpcId == $aws_priv_vpc and $it.CidrBlock == $aws_priv_cidr_block } | get -o SubnetId | default []) {
|
||||
print $"Clean up subnet ($it) in ($aws_priv_vpc)..."
|
||||
let res = (^aws ec2 delete-subnet --subnet-id $it | complete)
|
||||
if $res.exit_code != 0 { return false }
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def aws_create_private_subnet [
|
||||
aws_priv_cidr_block: string
|
||||
aws_priv_vpc: string
|
||||
aws_avail_zone: string
|
||||
task: string
|
||||
] {
|
||||
match $task {
|
||||
"create" => {
|
||||
if not (aws_delete_private_subnets $aws_priv_vpc $aws_priv_cidr_block) {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets --out json | complete)
|
||||
return ($res.stdout | from json | where { |it| $it.VpcId == $aws_priv_vpc and $it.CidrBlock == $aws_priv_cidr_block } | get -o 0)
|
||||
}
|
||||
let res = (^aws ec2 create-subnet --vpc-id $aws_priv_vpc --cidr-block $aws_priv_cidr_block --availability-zone $aws_avail_zone --query "Subnet" --output json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json)
|
||||
} else {
|
||||
print $"❗aws_priv_subnet not found for ($aws_priv_vpc) - ($aws_priv_cidr_block)"
|
||||
exit 1
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | where { |it| $it.VpcId == $aws_priv_vpc and $it.CidrBlock == $aws_priv_cidr_block } | get -o 0)
|
||||
} else {
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
def aws_vpc_subnet [
|
||||
aws_avail_zone: string
|
||||
aws_priv_subnet: string
|
||||
task: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets --out json | complete)
|
||||
let aws_vpc_subnet_data = if $res.exit_code == 0 {
|
||||
let data = ($res.stdout | from json | where {|it| $it.AvailabilityZone == $aws_avail_zone and $it.SubnetId != $aws_priv_subnet } | get -o 0 )
|
||||
{"vpc": $"($data | get -o VpcId | default '')", "subnet": $"($data | get -o SubnetId | default '')"}
|
||||
} else {
|
||||
{}
|
||||
}
|
||||
if $task == "create" and ($aws_vpc_subnet_data | is-empty) {
|
||||
^aws ec2 create-default-subnet --availability-zone $aws_avail_zone
|
||||
(aws_vpc_subnet $aws_avail_zone $aws_priv_subnet "scan")
|
||||
} else {
|
||||
$aws_vpc_subnet_data
|
||||
}
|
||||
}
|
||||
export def aws_delete_private_interfaces [
|
||||
aws_priv_subnet: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-network-interfaces --query NetworkInterfaces --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
for it in ($res.stdout | from json | where {|it| $it.SubnetId == $aws_priv_subnet } | get -o NetworkInterfaceId | default []) {
|
||||
^aws ec2 delete-network-interface --network-interface-id $it
|
||||
}
|
||||
}
|
||||
}
|
||||
export def aws_delete_private_interface [
|
||||
network_interface_id: string
|
||||
] {
|
||||
^aws ec2 delete-network-interface --network-interface-id "$network_interface_id"
|
||||
}
|
||||
export def aws_get_interface_defs [
|
||||
ip_interface: string
|
||||
aws_priv_subnet: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-network-interfaces --query NetworkInterfaces --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | where {|it| $it.SubnetId == $aws_priv_subnet and $it.PrivateIpAddress == $ip_interface } |
|
||||
get -o 0 | get -o NetworkInterfaceId | default ""
|
||||
)
|
||||
}
|
||||
}
|
||||
export def aws_get_create_private_interface [
|
||||
ip_interface: string
|
||||
aws_priv_subnet: string
|
||||
] {
|
||||
(aws_get_interface_defs $ip_interface $aws_priv_subnet)
|
||||
}
|
||||
export def aws_get_instance_defs [
|
||||
instance: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-instances --instance-ids $instance --out "json" | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | get -o "Reservations" | get -o "Instances" | default "" )
|
||||
}
|
||||
}
|
||||
export def attach_private_interface [
|
||||
interface: string
|
||||
instance: string
|
||||
aws_priv_subnet: string
|
||||
] {
|
||||
if (aws_get_instance_defs $instance | is-not-empty) and (aws_get_interface_defs $interface $aws_priv_subnet | is-not-empty) {
|
||||
(^aws ec2 attach-network-interface --network-interface-id $interface --instance-id $instance --device-index 1)
|
||||
} else { "" }
|
||||
}
|
||||
export def detach_private_interface [
|
||||
interface: string
|
||||
instance: string
|
||||
aws_priv_subnet: string
|
||||
] {
|
||||
if (aws_get_instance_defs $instance | is-not-empty) and (aws_get_interface_defs $interface $aws_priv_subnet | is-not-empty) {
|
||||
(^aws ec2 detach-network-interface --network-interface-id $interface --instance-id $instance)
|
||||
} else { "" }
|
||||
}
|
||||
export def aws_delete_target [
|
||||
target: string
|
||||
target_id: string
|
||||
settings: record
|
||||
] {
|
||||
mut num = 0
|
||||
mut res = ""
|
||||
mut status = ""
|
||||
let val_timeout = if $settings.running_timeout? != null { $settings.running_timeout } else { 60 }
|
||||
let wait = if $settings.running_wait? != null { $settings.running_wait } else { 10 }
|
||||
let wait_duration = ($"($wait)sec"| into duration)
|
||||
if $env.PROVISIONING_DEBUG { print -n $"Delete ($target) -> ($target_id) " }
|
||||
while ($status | is-empty) {
|
||||
let status = match $target {
|
||||
"securityGroup" => (^aws ec2 describe-security-groups --group-id $target_id err> /dev/null),
|
||||
"subnet" => (^aws ec2 describe-subnets --subnet-id $target_id err> /dev/null) ,
|
||||
"vpcs" => (^aws ec2 describe-vpcs --vpc-id $target_id err> /dev/null) ,
|
||||
"interface" => (^aws ec2 describe-network-interfaces --network-interface-id $target_id err> /dev/null),
|
||||
}
|
||||
if ($status | is-empty) {
|
||||
print $" "
|
||||
return
|
||||
}
|
||||
let res = match $target {
|
||||
"securityGroup" => (^aws ec2 delete-security-group --group-id $target_id | complete).exit_code,
|
||||
"subnet" => (^aws ec2 delete-subnet --subnet-id $target_id | complete).exit_code,
|
||||
"vpcs" => (^aws ec2 delete-vpc --vpc-id $target_id | complete).exit_code,
|
||||
"interface" => (^aws ec2 delete-network-interface --network-interface-id $target_id | complete).exit_code,
|
||||
}
|
||||
if ($res == 0) {
|
||||
print $" "
|
||||
return
|
||||
}
|
||||
if ($status | is-not-empty) or ($res != 0 ) {
|
||||
sleep $wait_duration
|
||||
$num += $wait
|
||||
if $val_timeout > 0 and $num > $val_timeout { return 1 }
|
||||
print -n $"($num) "
|
||||
}
|
||||
}
|
||||
print $""
|
||||
}
|
||||
export def aws_delete_settings [
|
||||
target: string
|
||||
provider_path: string
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
if not ($provider_path |path exists) {
|
||||
print $"❗aws_settings not found ($provider_path) no delete settings "
|
||||
return
|
||||
}
|
||||
let prov_settings = (load_provider_env $settings $server $provider_path)
|
||||
let env_settings = (get_provider_env $settings $server)
|
||||
if ($prov_settings | is-empty) or $prov_settings.main? == null or $prov_settings.priv? == null {
|
||||
if $env.PROVISIONING_DEBUG { print $"❗aws_settings (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) no settings main and priv found" }
|
||||
return
|
||||
}
|
||||
let aws_priv_subnet = ($prov_settings.priv.subnet | default "")
|
||||
let aws_priv_cidr_block = ($server.priv_cidr_block | default "")
|
||||
print $"Scanning aws resources to clean from (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) ... ($aws_priv_cidr_block)"
|
||||
if $target == "all" or $target == "interface" {
|
||||
for server_info in ($settings.data.servers) {
|
||||
let server = ($server_info | get -o hostname | default "")
|
||||
let network_private_ip = ($server_info | get -o network_private_ip | default "")
|
||||
let res = (^aws ec2 describe-network-interfaces --query NetworkInterfaces --out "json" | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
let interface = ($res.stdout | from json | where {|it|($it.PrivateIpAddress == $network_private_ip)} | get -o 0 | get -o NetworkInterfaceId | default "")
|
||||
if ($interface | is-not-empty) { aws_delete_target "interface" $interface $settings }
|
||||
}
|
||||
}
|
||||
}
|
||||
if not $server.prov_settings_clean {
|
||||
print $"❗aws provider settings clean ['prov_settings_clean'] set to ($server.prov_settings_clean)"
|
||||
return
|
||||
}
|
||||
if $target == "all" or $target == "pub_sg" {
|
||||
let aws_sg_name = ($prov_settings | get -o main | get -o sg | get -o name | default "")
|
||||
if ($aws_sg_name | is-not-empty) {
|
||||
let res = (^aws ec2 describe-security-groups --query SecurityGroups --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
let aws_sg_id = ($res.stdout | from json | where {|it| ($it.GroupName == $aws_sg_name) } | get -o 0 | get -o GroupId | default "")
|
||||
if ($aws_sg_id | is-not-empty) { aws_delete_target "securityGroup" $aws_sg_id $settings }
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($aws_priv_cidr_block | is-not-empty) {
|
||||
if $target == "all" or $target == "priv_sg" {
|
||||
let aws_priv_sg_name = ($prov_settings | get -o priv | get -o sg | get -o name | default "")
|
||||
if ($aws_priv_sg_name | is-not-empty) {
|
||||
let res = (^aws ec2 describe-security-groups --query SecurityGroups --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
let aws_priv_sg_id = ($res.stdout | from json | where {|it| ($it.GroupName == $aws_priv_sg_name)} | get -o 0 | get -o GroupId | default "")
|
||||
if ($aws_priv_sg_id | is-not-empty) { aws_delete_target "securityGroup" $aws_priv_sg_id $settings }
|
||||
}
|
||||
}
|
||||
}
|
||||
if $target == "all" or $target == "priv_subnet" {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | where { |it| $it.CidrBlock == $aws_priv_cidr_block } | get -o 0 | get -o SubnetId | default [] |
|
||||
each {|it| aws_delete_target "subnet" $it $settings }
|
||||
)
|
||||
}
|
||||
}
|
||||
if $target == "all" or $target == "priv_vpc" {
|
||||
let res = (^aws ec2 describe-vpcs --query Vpcs --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | where { |it| $it.CidrBlock == $aws_priv_cidr_block } | get -o 0 | get -o VpcId | default [] |
|
||||
each {|it| aws_delete_target "vpcs" $it $settings }
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG { print $"❗aws_priv_cidr_block not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) " }
|
||||
}
|
||||
}
|
||||
export def default_vpc [
|
||||
] {
|
||||
let res = (^aws ec2 describe-vpcs --query Vpcs[].VpcId --filters "Name=is-default,Values=true" --out text | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | str trim)
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG { print$"❗Error get (_ansi red)default Vpc(_ansi reset) " }
|
||||
{}
|
||||
}
|
||||
}
|
||||
export def default_subnet [
|
||||
vpc: string
|
||||
] {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets[] --filters "Name=default-for-az,Values=true" "Name=vpc-id,Values=vpc-0ffea05634122f3fa" --out json | complete)
|
||||
if $res.exit_code == 0 and ($res.stdout | is-not-empty) {
|
||||
($res.stdout | from json | default [] | get -o 0 | default "")
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG { print$"❗Error get (_ansi red)default subnet(_ansi reset) VPC (_ansi yellow)($vpc)(_ansi reset)" }
|
||||
""
|
||||
}
|
||||
}
|
||||
export def aws_scan_settings [
|
||||
in_task: string
|
||||
provider_path: string
|
||||
settings: record
|
||||
server: record
|
||||
check_mode: bool
|
||||
] {
|
||||
let prov_settings = (load_provider_env $settings $server $provider_path)
|
||||
let env_settings = (get_provider_env $settings $server)
|
||||
if (($prov_settings | get -o main ) == ($env_settings | get -o main)
|
||||
and ($prov_settings | get -o priv ) == ($env_settings | get -o priv)
|
||||
and ($prov_settings | get -o main | get -o vpc) != "?") { return }
|
||||
let task = if $prov_settings.main? == null or ($prov_settings | get -o main | get -o vpc) == "?" {
|
||||
"create"
|
||||
} else if $in_task == "create" {
|
||||
if $env.PROVISIONING_DEBUG { print $"❗aws_scan_settings task ($in_task) and ($provider_path) has content "}
|
||||
"scan"
|
||||
} else { $in_task }
|
||||
let data_settings = if $prov_settings.main? == null or ($prov_settings | get -o main | get -o vpc) != "?" {
|
||||
$prov_settings
|
||||
} else { $env_settings }
|
||||
print $"Scanning (_ansi green_bold)AWS(_ansi reset) resources to (_ansi purple_bold)($task)(_ansi reset) settings in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) ..."
|
||||
let res = (^aws ec2 describe-availability-zones --query AvailabilityZones| complete)
|
||||
if $res.exit_code != 0 {
|
||||
(throw-error $"🛑 Unable lo load ($server.provider) availability zones" $"($res.exit_code) ($res.stdout)" $"server info ($server.hostname)" --span (metadata $res).span)
|
||||
exit 1
|
||||
}
|
||||
let $aws_vpc = if ($data_settings | get -o main | get -o vpc | length) > 1 { $settings.main.vpc } else { default_vpc }
|
||||
let $aws_subnet_data = if ($data_settings | get -o main | get -o subnet | length) > 1 {
|
||||
let res = (^aws ec2 describe-subnets --query Subnets -SubnetId $settings.main.subnet --out json | complete)
|
||||
if $res.exit_code != 0 {
|
||||
(throw-error $"🛑 Unable lo load ($server.provider) subnet info ($settings.main.subnet)" $"($res.exit_code) ($res.stdout)" $"server info ($server.hostname)" --span (metadata $res).span)
|
||||
exit 1
|
||||
}
|
||||
($res.stdout | from json)
|
||||
} else {
|
||||
default_subnet $aws_vpc
|
||||
}
|
||||
let aws_subnet = ($aws_subnet_data | get -o SubnetId | default "")
|
||||
if ($aws_subnet | is-empty) {
|
||||
(throw-error $"🛑 Unable lo load ($server.provider) subnet id" $"($aws_subnet_data)" $"server info ($server.hostname)" --span (metadata $aws_subnet_data).span)
|
||||
exit 1
|
||||
}
|
||||
let aws_avail_zone = ($aws_subnet_data | get -o AvailabilityZone | default "")
|
||||
if ($aws_avail_zone | is-empty) {
|
||||
(throw-error $"🛑 Unable lo load ($server.provider) subnet availability zone" $"($aws_subnet_data)" $"server info ($server.hostname)" --span (metadata $aws_avail_zone).span)
|
||||
exit 1
|
||||
}
|
||||
let aws_priv_cidr_block = ($server.priv_cidr_block | default "")
|
||||
let priv = if ($aws_priv_cidr_block | is-not-empty) {
|
||||
let aws_priv_vpc = (aws_create_private_vpc $aws_priv_cidr_block $task)
|
||||
if ($aws_priv_vpc | is-empty) {
|
||||
print $"❗ aws_priv_vpc not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) "
|
||||
exit 1
|
||||
}
|
||||
let aws_priv_subnet_data = (aws_create_private_subnet $aws_priv_cidr_block $aws_priv_vpc $aws_avail_zone $task)
|
||||
if $env.PROVISIONING_DEBUG { print $aws_priv_subnet_data }
|
||||
let aws_priv_subnet = ($aws_priv_subnet_data | get -o SubnetId | default "")
|
||||
if ($aws_priv_subnet | is-empty) {
|
||||
print $"❗aws_priv_subnet not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) "
|
||||
exit 1
|
||||
}
|
||||
let aws_priv_avail_zone = ($aws_priv_subnet_data | get -o AvailabilityZone | default "")
|
||||
let aws_priv_sg_name = ($data_settings | get -o priv | get -o sg | get -o name | default "sg_priv")
|
||||
if ($aws_priv_sg_name | is-empty) {
|
||||
print $"❗aws_priv_sg.name not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset)"
|
||||
exit 1
|
||||
}
|
||||
let aws_priv_sg_id = (aws_create_sg_id $aws_priv_vpc $aws_priv_sg_name $task)
|
||||
let aws_priv_sg_data = {
|
||||
id: $aws_priv_sg_id,
|
||||
name: $aws_priv_sg_name,
|
||||
perms: ($env_settings | get -o priv | get -o sg | get -o perms | default [])
|
||||
}
|
||||
if $task == "create" or $task == "scan" { aws_add_sg_perms $aws_priv_sg_data $server $check_mode}
|
||||
{
|
||||
vpc: $aws_priv_vpc,
|
||||
subnet: $aws_priv_subnet,
|
||||
cidr_block: $aws_priv_cidr_block,
|
||||
avail_zone: $aws_priv_avail_zone,
|
||||
sg: $aws_priv_sg_data
|
||||
}
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG { print$"❗aws_priv_cidr_block not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) " }
|
||||
}
|
||||
let aws_sg_name = ($data_settings | get -o sg | get -o name | default "sg_pub")
|
||||
if ($aws_sg_name | is-empty) {
|
||||
print $"aws_sg_name not found in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset) "
|
||||
exit 1
|
||||
}
|
||||
let aws_vpc_subnet_data = (aws_vpc_subnet $aws_avail_zone $priv.subnet $task)
|
||||
if $task == "create" and ($aws_vpc_subnet_data | is-empty) {
|
||||
print $"❗No availability zone ($aws_avail_zone) "
|
||||
exit 1
|
||||
}
|
||||
print $aws_vpc_subnet_data
|
||||
let aws_sg_id = (aws_create_sg_id $aws_vpc $aws_sg_name $task)
|
||||
let aws_sg_data = {
|
||||
id: $aws_sg_id,
|
||||
name: $aws_sg_name,
|
||||
perms: ($env_settings | get -o main | get -o sg | get -o perms | default [])
|
||||
}
|
||||
if $task == "create" or $task == "scan" { aws_add_sg_perms $aws_sg_data $server $check_mode }
|
||||
let main = {
|
||||
vpc: $aws_vpc,
|
||||
subnet: $aws_subnet,
|
||||
cidr_block: ($aws_subnet_data | get -o CidrBlock | default ""),
|
||||
avail_zone: $aws_avail_zone,
|
||||
sg: $aws_sg_data,
|
||||
}
|
||||
let data_settings = if ($aws_priv_cidr_block | is-not-empty) {
|
||||
{ main: $main, priv: $priv }
|
||||
} else {
|
||||
{ main: $main }
|
||||
}
|
||||
save_provider_env (load_provider_env $settings $server $provider_path | merge $data_settings) $settings $provider_path
|
||||
print $"✅ (_ansi green_bold)AWS(_ansi reset) (_ansi cyan_bold)settings(_ansi reset) completed in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset)"
|
||||
}
|
||||
export def aws_scan_servers [
|
||||
provider_path: string
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
mut servers = []
|
||||
for server_info in ($settings.data.servers? | default []) {
|
||||
let hostname = ($server_info | get -o hostname | default "" )
|
||||
let network_private_ip = ($server_info | get -o network_private_ip | default "")
|
||||
let res = (^aws ec2 describe-instances --out json --filters $'"Name=tag:hostname,Values=($hostname)"' --filters "Name=instance-state-name,Values=running"
|
||||
--query "Reservations[*].Instances[].{
|
||||
id: InstanceId,
|
||||
priv: NetworkInterfaces[],
|
||||
pub: PublicIpAddress,
|
||||
type: InstanceType,
|
||||
status: State.Name,
|
||||
keyname: KeyName,
|
||||
launchtime: LaunchTime,
|
||||
block_devices: BlockDeviceMappings
|
||||
}"
|
||||
--output json | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗No data found for ($hostname) in ($server.provider) "
|
||||
continue
|
||||
}
|
||||
for instance_data in ($res.stdout | from json ) {
|
||||
if ($instance_data | get -o status | str contains "erminated") { continue }
|
||||
let instance_id = ($instance_data | get -o id | default "")
|
||||
mut volumes = []
|
||||
for device in ($instance_data | get -o block_devices | default []) {
|
||||
let vol_id = ($device | get -o Ebs | get -o VolumeId | default "")
|
||||
if ($vol_id | is-empty) { continue }
|
||||
let res_vols = (^aws ec2 describe-volumes --volume-id $vol_id --filters $"Name=attachment.instance-id,Values=($instance_id)"
|
||||
--query "Volumes[]" --output=json | complete)
|
||||
if $res_vols.exit_code == 0 {
|
||||
$volumes = ($volumes | append ($res_vols.stdout | from json))
|
||||
}
|
||||
}
|
||||
$servers = ($servers | append {
|
||||
id: $instance_id
|
||||
hostname: $hostname
|
||||
keyname: ($instance_data | get -o keyname | default ""),
|
||||
private_ips: ($instance_data | get -o priv | default []),
|
||||
puplic_ips: ($instance_data | get -o pub | default []),
|
||||
volumes: $volumes,
|
||||
devices: ($instance_data | get -o block_devices | default []),
|
||||
launchtime: ($instance_data | get -o launchtime | default ""),
|
||||
info: $server_info
|
||||
})
|
||||
}
|
||||
}
|
||||
save_provider_env (load_provider_env $settings $server $provider_path | merge { servers: $servers}) $settings $provider_path
|
||||
print $"✅ (_ansi green_bold)AWS(_ansi reset) (_ansi blue_bold)servers settings(_ansi reset)
|
||||
completed in (_ansi yellow_bold)($provider_path | path basename)(_ansi reset)"
|
||||
}
|
||||
6
providers/aws/nulib/aws/mod.nu
Normal file
6
providers/aws/nulib/aws/mod.nu
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use env.nu
|
||||
export use lib.nu *
|
||||
export use servers.nu *
|
||||
export use usage.nu *
|
||||
export use prices.nu *
|
||||
export use utils.nu *
|
||||
250
providers/aws/nulib/aws/prices.nu
Normal file
250
providers/aws/nulib/aws/prices.nu
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
use ../../../../core/nulib/lib_provisioning/utils/format.nu money_conversion
|
||||
|
||||
def aws_default_store_type [] {
|
||||
"Provisioned IOPS"
|
||||
}
|
||||
export def aws_get_price [
|
||||
all_data: record
|
||||
key: string
|
||||
price_col: string = "pricePerUnit"
|
||||
] {
|
||||
let data = ($all_data | get -o item)
|
||||
let str_price_col = if ($price_col | is-empty) { "pricePerUnit" } else { $price_col }
|
||||
let value = ($data | get -o $str_price_col | get -o "USD" | default "")
|
||||
let val = if ($value | is-empty) {
|
||||
0
|
||||
} else {
|
||||
money_conversion "USD" "EUR" ($value | into float)
|
||||
}
|
||||
let unit = $"($val) ($data | get -o unit | default "")"
|
||||
if ($unit | str contains "Hrs") {
|
||||
match $key {
|
||||
"month" => (($val * 24) * 30),
|
||||
"day" => ($val * 24),
|
||||
"hour" => ($val),
|
||||
"minute" => ($val / 60),
|
||||
"unit" => $unit,
|
||||
}
|
||||
} else if ($unit | str contains "Mo") {
|
||||
match $key {
|
||||
"month" => $val,
|
||||
"day" => ($val / 30),
|
||||
"hour" => (($val / 30) / 24),
|
||||
"minute" => ((($val / 30) / 24) / 60),
|
||||
"unit" => $unit,
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
export def aws_get_provider_path [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let data_path = if ($settings.data.prov_data_dirpath | str starts-with "." ) {
|
||||
($settings.src_path | path join $settings.data.prov_data_dirpath)
|
||||
} else { $settings.data.prov_data_dirpath }
|
||||
if not ($data_path | path exists) { mkdir $data_path }
|
||||
($data_path | path join $"($server.provider)_prices.($env.PROVISIONING_WK_FORMAT)")
|
||||
}
|
||||
export def aws_get_item_for_server [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
] {
|
||||
let provider_prices_path = (aws_get_provider_path $settings $server)
|
||||
if not ($provider_prices_path | path exists) { return {} }
|
||||
let pricing_data = (open $provider_prices_path | default [])
|
||||
let memory = $"(($server.reqplan.memory | default 1024) / 1024) GiB"
|
||||
let cores = $"($server.reqplan.cores | default 1)"
|
||||
let current_gen = if ($server.reqplan.gen | default "") == "current" { "Yes" } else { "No" }
|
||||
#let arch = if ($server.reqplan.arch | str contains "x86_64") { "Intel" } else { ""}
|
||||
for item in $pricing_data {
|
||||
if ($item | get -o data | is-empty) or ($item | get -o plan | is-empty) { continue }
|
||||
if ($item.plan != $server.plan and $item.zone != $server.zone) { continue }
|
||||
for it in $item.data {
|
||||
if ($it | get -o product | is-empty) { continue }
|
||||
if ( $it.product.attributes.memory == $memory
|
||||
and $it.product.attributes.vcpu == $cores
|
||||
and $it.product.attributes.currentGeneration == $current_gen
|
||||
and ($it.product.attributes.operatingSystem | str contains "Linux")
|
||||
) {
|
||||
return ($it.on_demand | get -o priceDimensions | default {})
|
||||
}
|
||||
}
|
||||
}
|
||||
{}
|
||||
}
|
||||
export def aws_get_item_for_storage [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
] {
|
||||
let provider_prices_path = (aws_get_provider_path $settings $server)
|
||||
if not ($provider_prices_path | path exists) { return [] }
|
||||
let pricing_data = (open $provider_prices_path | default [])
|
||||
if ($pricing_data | length) == 0 { return [] }
|
||||
let default_store_type = aws_default_store_type
|
||||
mut $data = []
|
||||
for store in ($server | get -o storages | default []) {
|
||||
let store_type = ($store | get -o prov_type | default $default_store_type)
|
||||
for item in $pricing_data {
|
||||
let item_type = ($item | get -o store | default "")
|
||||
if ($item_type | is-empty) or $item_type != $store_type and $item.zone != $server.zone { continue }
|
||||
if ($item | get -o data | is-empty) { continue }
|
||||
let item_type = ($item | get -o store | default "")
|
||||
return ($item | get data | get -o 0 | get -o on_demand | get -o priceDimensions | default {})
|
||||
# $data = ($data | append ($item | get data | get -o 0 | get -o on_demand | get -o priceDimensions | default {}))
|
||||
}
|
||||
}
|
||||
{}
|
||||
#$data
|
||||
}
|
||||
export def aws_load_infra_servers_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let provider_prices_path = (aws_get_provider_path $settings $server)
|
||||
if ($provider_prices_path | path exists) {
|
||||
let pricing_data = (open $provider_prices_path)
|
||||
for it in $pricing_data {
|
||||
let zone = ($it | get -o zone | default "")
|
||||
let plan = ($it | get -o plan | default "")
|
||||
if $zone == $server.zone and $plan == $server.plan {
|
||||
return {plan: $plan, zone: $zone }
|
||||
}
|
||||
}
|
||||
}
|
||||
(aws_load_infra_servers $provider_prices_path $settings $server)
|
||||
}
|
||||
export def aws_load_infra_storages_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let provider_prices_path = (aws_get_provider_path $settings $server)
|
||||
if ($provider_prices_path | path exists) {
|
||||
let default_store_type = aws_default_store_type
|
||||
let pricing_data = (open $provider_prices_path)
|
||||
for it in $pricing_data {
|
||||
let zone = ($it | get -o zone | default "")
|
||||
let store = ($it | get -o store | default "")
|
||||
if $zone == $server.zone and $store == $default_store_type {
|
||||
return {zone: $zone, store: $store }
|
||||
}
|
||||
}
|
||||
}
|
||||
aws_load_infra_storages $provider_prices_path $settings $server
|
||||
}
|
||||
export def aws_get_price_data [
|
||||
filter: record
|
||||
server: record
|
||||
] {
|
||||
let res = (^aws pricing get-products --service-code AmazonEC2 --filters
|
||||
$"Type=TERM_MATCH,Field=($filter.field),Value=($filter.value)" $"Type=TERM_MATCH,Field=regionCode,Value=($server.zone)"
|
||||
--query "PriceList[]" --region us-east-1 --out json | complete
|
||||
)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Errors on ($server.hostname) ($server.provider) ($server.plan) in ($server.zone) load cloud price data error: ($res.stdout ) "
|
||||
return
|
||||
}
|
||||
# | str replace '\' ''| str replace '"{' '{' | str replace '}"' '}')
|
||||
mut $data = []
|
||||
for it in ($res.stdout | from json) {
|
||||
let it_data = ($it | from json)
|
||||
|
||||
let product = ($it_data | get -o product | default {})
|
||||
if ($product | is-empty) { continue }
|
||||
|
||||
#let attributes = ($product | get -o attributes | default {})
|
||||
let on_demand_key = ($it_data | get -o terms | get -o OnDemand | columns | first)
|
||||
let on_demand_data = ($it_data | get -o terms | get -o OnDemand | get -o $on_demand_key | default {})
|
||||
let price_dimension = if ($on_demand_data | is-not-empty) {
|
||||
let price_dimension_key = ($on_demand_data | get -o priceDimensions | columns | first | default "")
|
||||
($on_demand_data | get -o priceDimensions | get -o $price_dimension_key | default {})
|
||||
} else {
|
||||
{}
|
||||
}
|
||||
$data = ( $data | append {
|
||||
product: $product,
|
||||
on_demand: {
|
||||
priceDimensions: $price_dimension,
|
||||
sku: ($on_demand_data | get -o sku),
|
||||
effectiveDate: ($on_demand_data | get -o effectiveDate),
|
||||
offerTermCode: ($on_demand_data | get -o offerTermCode),
|
||||
termAttributes: ($on_demand_data | get -o termAttributes)
|
||||
}
|
||||
})
|
||||
}
|
||||
$data
|
||||
}
|
||||
export def aws_load_infra_storages [
|
||||
provider_prices_path: string
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let default_store_type = aws_default_store_type
|
||||
let curr_data = if ($provider_prices_path | path exists) {
|
||||
(open $provider_prices_path)
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
$curr_data | where {|it|
|
||||
if $it.zone == $server.zone and $it.store? != null and $it.store == $default_store_type {
|
||||
print $it
|
||||
return
|
||||
}
|
||||
}
|
||||
let filter = {
|
||||
field: "volumeType",
|
||||
value: $default_store_type
|
||||
}
|
||||
let data = (aws_get_price_data $filter $server)
|
||||
let srv_data = { zone: $server.zone, store: $default_store_type, data: $data}
|
||||
let all_data = if ($provider_prices_path | path exists) {
|
||||
(open $provider_prices_path | append $srv_data)
|
||||
} else {
|
||||
[$srv_data]
|
||||
}
|
||||
if $env.PROVISIONING_WK_FORMAT == "json" {
|
||||
$all_data | to json | save -f $provider_prices_path
|
||||
} else {
|
||||
$all_data | to yaml | save -f $provider_prices_path
|
||||
}
|
||||
if $env.PROVISIONING_DEBUG { print $"Storage prices for ($server.provider) in: ($provider_prices_path | path basename) with ($server.zone) saved" }
|
||||
}
|
||||
export def aws_load_infra_servers [
|
||||
provider_prices_path: string
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let curr_data = if ($provider_prices_path | path exists) {
|
||||
(open $provider_prices_path)
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
$curr_data | where {|it|
|
||||
if $it.zone? != null and $it.zone == $server.zone and $it.plan? != null and $it.plan == $server.plan {
|
||||
return $curr_data
|
||||
}
|
||||
}
|
||||
let filter = {
|
||||
field: "instanceType",
|
||||
value: $server.plan
|
||||
}
|
||||
let data = (aws_get_price_data $filter $server)
|
||||
let srv_data = { zone: $server.zone, plan: $server.plan, data: $data}
|
||||
let all_data = if ($provider_prices_path | path exists) {
|
||||
(open $provider_prices_path | append $srv_data)
|
||||
} else {
|
||||
[$srv_data]
|
||||
}
|
||||
if $env.PROVISIONING_WK_FORMAT == "json" {
|
||||
$all_data | to json | save -f $provider_prices_path
|
||||
} else {
|
||||
$all_data | to yaml | save -f $provider_prices_path
|
||||
}
|
||||
if $env.PROVISIONING_DEBUG { print $"Server prices for ($server.provider) in: ($provider_prices_path | path basename) with ($server.plan)/($server.zone) saved" }
|
||||
{ plan: $server.plan, zone: $server.zone }
|
||||
}
|
||||
1100
providers/aws/nulib/aws/servers.nu
Normal file
1100
providers/aws/nulib/aws/servers.nu
Normal file
File diff suppressed because it is too large
Load diff
41
providers/aws/nulib/aws/usage.nu
Normal file
41
providers/aws/nulib/aws/usage.nu
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
#!/usr/bin/env nu
|
||||
|
||||
# myscript.nu
|
||||
export def usage [provider: string, infra: string] {
|
||||
let info = if ( $env.CURRENT_FILE? | into string ) != "" { (^grep "^# Info:" $env.CURRENT_FILE ) | str replace "# Info: " "" } else { "" }
|
||||
# $(declare -F _usage_options >/dev/null && _usage_options)
|
||||
$"
|
||||
USAGE provisioning ($provider) -k cloud-path file-settings.yaml provider-options
|
||||
DESCRIPTION
|
||||
AWS ($info)
|
||||
OPTIONS
|
||||
-s server-hostname
|
||||
with server-hostname target selection
|
||||
-p provider-name
|
||||
use provider name
|
||||
do not need if 'current directory path basename' is not one of providers available
|
||||
-new | new [provisioning-name]
|
||||
create a new provisioning-directory-name by a copy of ($infra)
|
||||
-k cloud-path-item
|
||||
use cloud-path-item as base directory for settings
|
||||
-x
|
||||
Trace script with 'set -x'
|
||||
providerslist | providers-list | providers list
|
||||
Get available providers list
|
||||
taskslist | tasks-list | tasks list
|
||||
Get available tasks list
|
||||
serviceslist | service-list
|
||||
Get available services list
|
||||
tools
|
||||
Run core/on-tools info
|
||||
-i
|
||||
About this
|
||||
-v
|
||||
Print version
|
||||
-h, --help
|
||||
Print this help and exit.
|
||||
"
|
||||
# ["hello" $name $title]
|
||||
}
|
||||
|
||||
24
providers/aws/nulib/aws/utils.nu
Normal file
24
providers/aws/nulib/aws/utils.nu
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
export def aws_check_requirements [
|
||||
settings: record
|
||||
fix_error: bool
|
||||
] {
|
||||
let has_aws = (^bash -c "type -P aws")
|
||||
if ($has_aws | path exists) == false and $fix_error {
|
||||
( ^($env.PROVISIONING_NAME) "tools" "install" "aws")
|
||||
}
|
||||
let has_aws = (^bash -c "type -P aws")
|
||||
if ($has_aws | path exists) == false {
|
||||
(throw-error $"🛑 CLI command aws not found"
|
||||
"aws_check_requirements" --span (metadata $has_aws).span)
|
||||
exit 1
|
||||
}
|
||||
let aws_version = (^aws --version | cut -f1 -d" " | sed 's,aws-cli/,,g')
|
||||
let req_version = (open $env.PROVISIONING_REQ_VERSIONS).aws?.version? | default "")
|
||||
if ($aws_version != $req_version ) and $fix_error {
|
||||
( ^($env.PROVISIONING_NAME) "tools" "update" "aws")
|
||||
}
|
||||
let aws_version = (^aws --version | cut -f1 -d" " | sed 's,aws-cli/,,g')
|
||||
if $aws_version != $req_version {
|
||||
print $"warning❗ aws command as CLI for AWS ($aws_version) with Provisioning is not ($req_version)"
|
||||
}
|
||||
}
|
||||
9
providers/aws/provisioning.yaml
Normal file
9
providers/aws/provisioning.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
version: 1.0
|
||||
info: AWS provisioning
|
||||
site: https://docs.aws.amazon.com/cli/
|
||||
tools:
|
||||
aws:
|
||||
version: 2.17.7
|
||||
source: "https://awscli.amazonaws.com/awscli-exe-${OS}-${ORG_ARCH}.zip"
|
||||
tags: https://github.com/aws/aws-cli/tags
|
||||
site: https://docs.aws.amazon.com/cli/
|
||||
4
providers/aws/versions
Normal file
4
providers/aws/versions
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
AWS_AWS_VERSION="2.17.7"
|
||||
AWS_AWS_SOURCE="https://awscli.amazonaws.com/awscli-exe-${OS}-${ORG_ARCH}.zip"
|
||||
AWS_AWS_TAGS="https://github.com/aws/aws-cli/tags"
|
||||
AWS_AWS_SITE="https://docs.aws.amazon.com/cli/"
|
||||
12
providers/aws/versions.yaml
Normal file
12
providers/aws/versions.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
aws:
|
||||
version: 2.17.7
|
||||
fixed: false
|
||||
source: https://github.com/aws/aws-cli/releases
|
||||
tags: https://github.com/aws/aws-cli/tags
|
||||
site: https://docs.aws.amazon.com/cli/
|
||||
detector:
|
||||
method: command
|
||||
command: aws --version
|
||||
pattern: aws-cli/(\d+\.\d+\.\d+)
|
||||
capture: capture0
|
||||
comparison: semantic
|
||||
102
providers/local/bin/install.sh
Executable file
102
providers/local/bin/install.sh
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
#!/bin/bash
|
||||
# Info: Script to install provider
|
||||
# Author: JesusPerezLorenzo
|
||||
# Release: 1.0
|
||||
# Date: 15-04-2024
|
||||
|
||||
[ "$DEBUG" == "-x" ] && set -x
|
||||
|
||||
USAGE="install [ tool-name: upctl, etc | all | info] [--update]
|
||||
As alternative use environment var TOOL_TO_INSTALL with a list-of-tools (separeted with spaces)
|
||||
Versions are set in ./versions file
|
||||
|
||||
This can be called by directly with an argumet or from an other script
|
||||
"
|
||||
|
||||
ORG=$(pwd)
|
||||
function _info_tools {
|
||||
local match=$1
|
||||
local info_keys
|
||||
info_keys="info version site"
|
||||
|
||||
if [ -z "$match" ] || [ "$match" == "all" ] || [ "$match" == "-" ]; then
|
||||
match="all"
|
||||
fi
|
||||
echo "$PROVIDER_TITLE"
|
||||
[ ! -r "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" ] && return
|
||||
echo "-------------------------------------------------------"
|
||||
case "$match" in
|
||||
"i" | "?" | "info")
|
||||
for key in $info_keys
|
||||
do
|
||||
echo -n "$key:"
|
||||
[ "$key" != "version" ] && echo -ne "\t"
|
||||
echo " $(grep "^$key:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$key: //g")"
|
||||
done
|
||||
;;
|
||||
"all")
|
||||
cat "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml"
|
||||
;;
|
||||
*)
|
||||
echo -e "$match:\t $(grep "^$match:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$match: //g")"
|
||||
esac
|
||||
echo "________________________________________________________"
|
||||
}
|
||||
function _install_tools {
|
||||
local match=$1
|
||||
shift
|
||||
local options
|
||||
options="$*"
|
||||
local has_tool
|
||||
local tool_version
|
||||
|
||||
OS="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
ORG_OS=$(uname)
|
||||
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')"
|
||||
ORG_ARCH="$(uname -m)"
|
||||
|
||||
}
|
||||
function _on_tools {
|
||||
local tools_list=$1
|
||||
[ -z "$tools_list" ] || [[ "$tools_list" == -* ]] && tools_list=${TOOL_TO_INSTALL:-all}
|
||||
case $tools_list in
|
||||
"all")
|
||||
_install_tools "all" "$@"
|
||||
;;
|
||||
"info" | "i" | "?")
|
||||
shift
|
||||
_info_tools "$@"
|
||||
;;
|
||||
*)
|
||||
for tool in $tools_list
|
||||
do
|
||||
[[ "$tool" == -* ]] && continue
|
||||
_install_tools "$tool" "${*//$tool/}"
|
||||
done
|
||||
esac
|
||||
}
|
||||
|
||||
set -o allexport
|
||||
## shellcheck disable=SC1090
|
||||
[ -n "$PROVISIONING_ENV" ] && [ -r "$PROVISIONING_ENV" ] && source "$PROVISIONING_ENV"
|
||||
[ -r "../env-provisioning" ] && source ../env-provisioning
|
||||
[ -r "env-provisioning" ] && source ./env-provisioning
|
||||
#[ -r ".env" ] && source .env set
|
||||
set +o allexport
|
||||
|
||||
export PROVISIONING=${PROVISIONING:-/usr/local/provisioning}
|
||||
|
||||
PROVIDERS_PATH=${PROVIDERS_PATH:-"$PROVISIONING/providers"}
|
||||
|
||||
PROVIDER_NAME="local"
|
||||
PROVIDER_TITLE="Local"
|
||||
|
||||
if [ -r "$(dirname "$0")/../versions" ] ; then
|
||||
. "$(dirname "$0")"/../versions
|
||||
elif [ -r "$(dirname "$0")/versions" ] ; then
|
||||
. "$(dirname "$0")"/versions
|
||||
fi
|
||||
[ "$1" == "-h" ] && echo "$USAGE" && shift
|
||||
[ "$1" == "check" ] && CHECK_ONLY="yes" && shift
|
||||
[ -n "$1" ] && cd /tmp && _on_tools "$@"
|
||||
[ -z "$1" ] && _on_tools "$@"
|
||||
5
providers/local/nulib/local/env.nu
Normal file
5
providers/local/nulib/local/env.nu
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export-env {
|
||||
$env.LOCAL_API_URL = ($env | get -o LOCAL_API_URL | default "")
|
||||
$env.LOCAL_AUTH = ($env | get -o LOCAL_AUTH | default "")
|
||||
$env.LOCAL_INTERFACE = ($env | get -o LOCAL_INTERFACE | default "CLI") # API or CLI
|
||||
}
|
||||
4
providers/local/nulib/local/mod.nu
Normal file
4
providers/local/nulib/local/mod.nu
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
use env.nu
|
||||
export use servers.nu *
|
||||
export use usage.nu *
|
||||
export use utils.nu *
|
||||
575
providers/local/nulib/local/servers.nu
Normal file
575
providers/local/nulib/local/servers.nu
Normal file
|
|
@ -0,0 +1,575 @@
|
|||
#!/usr/bin/env nu
|
||||
use std
|
||||
|
||||
export def local_query_servers [
|
||||
find: string
|
||||
cols: string
|
||||
] {
|
||||
# TODO FIX
|
||||
let res = (^upctl server list -o json err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code == 0 {
|
||||
$res.stdout | from json | get servers
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
(throw-error "🛑 local server list " $"($res.exit_code) ($res.stdout)" "local query server" --span (metadata $res).span)
|
||||
} else {
|
||||
print $"🛑 Error local server list: ($res.exit_code) ($res.stdout | ^grep 'error')"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def local_server_info [
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
let hostname = $server.hostname
|
||||
# TODO FIX
|
||||
let res = (^upctl server show $hostname -o json err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code == 0 {
|
||||
$res.stdout | from json
|
||||
} else if $check {
|
||||
{}
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
(throw-error "🛑 local server show" $"($res.exit_code) ($res.stdout)" $"local server info ($hostname)" --span (metadata $res).span)
|
||||
} else {
|
||||
print $"🛑 local server show ($hostname):($res.stdout | ^grep 'error')"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def local_on_prov_server [
|
||||
server?: record
|
||||
infra?: string
|
||||
] {
|
||||
let info = if ( $env.CURRENT_FILE? | into string ) != "" { (^grep "^# Info:" $env.CURRENT_FILE ) | str replace "# Info: " "" } else { "" }
|
||||
print $env.CURRENT_FILE
|
||||
$" From LOCAL ($info) "
|
||||
}
|
||||
# infrastructure and services
|
||||
export def local [
|
||||
args: list<string> # Args for create command
|
||||
--server(-s): record
|
||||
#hostname?: string # Server hostname in settings
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--infra (-i): string # Infra path
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--debug (-x) # Use Debug mode
|
||||
] {
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
let target = ($args | get -o 0 | default "")
|
||||
let task = ($args | get -o 1 | default "")
|
||||
let cmd_args = if ($args | length) > 1 { ($args | drop nth ..1) } else { [] }
|
||||
match ($task) {
|
||||
"help" | "h" | "" => {
|
||||
print "TODO local help"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
},
|
||||
_ => {
|
||||
if ($args | find "help" | length) > 0 {
|
||||
match $task {
|
||||
"server" => {
|
||||
print "SERVER "
|
||||
local_server ($args | drop nth ..0)
|
||||
#local_server ($args | drop nth ..1) --server $server
|
||||
},
|
||||
"inventory" => {
|
||||
local_server ($args | drop nth ..0)
|
||||
},
|
||||
"ssh" => {
|
||||
local_server ($args | drop nth ..0)
|
||||
},
|
||||
"delete" => {
|
||||
local_server ($args | drop nth ..0)
|
||||
# ($args | drop nth ..1) --server $server
|
||||
},
|
||||
_ => {
|
||||
option_undefined "local" ""
|
||||
print "TODO local help"
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
#use utils/settings.nu [ load_settings ]
|
||||
let curr_settings = if $infra != null {
|
||||
if $settings != null {
|
||||
(load_settings --infra $infra --settings $settings)
|
||||
} else {
|
||||
(load_settings --infra $infra)
|
||||
}
|
||||
} else {
|
||||
if $settings != null {
|
||||
(load_settings --settings $settings)
|
||||
} else {
|
||||
(load_settings)
|
||||
}
|
||||
}
|
||||
match ($task) {
|
||||
"get_ip" => {
|
||||
local_get_ip $curr_settings $server ($cmd_args | get -o 0 | default "")
|
||||
},
|
||||
"server" => {
|
||||
print (
|
||||
local_server $cmd_args --server $server --settings $curr_settings --error_exit
|
||||
)
|
||||
},
|
||||
"inventory" => {
|
||||
},
|
||||
"ssh" => {
|
||||
},
|
||||
"delete" => {
|
||||
# ($args | drop nth ..1) --server $server
|
||||
},
|
||||
_ => {
|
||||
option_undefined "local" ""
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
export def local_get_ip [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type: string
|
||||
] {
|
||||
match $ip_type {
|
||||
"private" | "prv" | "priv" => {
|
||||
return $"($server.network_private_ip)"
|
||||
},
|
||||
_ => {
|
||||
let ip = ($server.network_public_ip | default "")
|
||||
# TODO FIX add NOT FOUND ERRORS
|
||||
return $ip
|
||||
#let result = (^upctl "server" "show" $server.hostname "-o" "json" | complete)
|
||||
#if $result.exit_code == 0 {
|
||||
# let data = ($result.stdout | from json)
|
||||
# #let id = ($data.id? | default "")
|
||||
# let ip_addresses = ($data.networking?.interfaces? | where {|it| ($it.type | str contains "public") }).ip_addresses?
|
||||
# return $"(($ip_addresses | get -o 0).address? | get -o 0 | default '')"
|
||||
#} else { "" }
|
||||
}
|
||||
}
|
||||
}
|
||||
# To create infrastructure and services
|
||||
export def local_server [
|
||||
args: list<string> # Args for create command
|
||||
--server(-s): record
|
||||
--error_exit
|
||||
--status
|
||||
#hostname?: string # Server hostname in settings
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--infra (-i): string # Infra path
|
||||
--settings (-s): record # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--debug (-x) # Use Debug mode
|
||||
] {
|
||||
let task = ($args | get -o 0)
|
||||
let target = if ($args | length) > 1 { ($args | get -o 1) } else { "" }
|
||||
let cmd_args = if ($args | length) > 1 { ($args | drop nth ..1) } else { [] }
|
||||
match ($task) {
|
||||
"help" | "h" | "" => {
|
||||
print "TODO local server help"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
},
|
||||
_ => {
|
||||
if $target == "" or ($args | find "help" | length) > 0 {
|
||||
match $task {
|
||||
"server" => {
|
||||
local_server $cmd_args
|
||||
},
|
||||
"status" => {
|
||||
print $server
|
||||
print $error_exit
|
||||
}
|
||||
"inventory" => {
|
||||
print "TODO local server inventory help"
|
||||
},
|
||||
"ssh" => {
|
||||
print "TODO local server ssh help"
|
||||
},
|
||||
"delete" => {
|
||||
# ($args | drop nth ..1) --server $server
|
||||
#local_delete_server $cmd_args true
|
||||
},
|
||||
_ => {
|
||||
option_undefined "local" "server"
|
||||
print "TODO local server help"
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
let server_target = if $server != null {
|
||||
$server
|
||||
} else if $settings != null {
|
||||
($settings.data.servers | where {|it| $it.hostname == $target } | get -o 0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if $server_target == null {
|
||||
if $error_exit {
|
||||
let text = $"($args | str join ' ')"
|
||||
(throw-error "🛑 local server" $text "" --span (metadata $server_target).span)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
if $status or $task == "status" {
|
||||
print "local server status "
|
||||
return true
|
||||
}
|
||||
match $task {
|
||||
"get_ip" => {
|
||||
local_get_ip $settings $server_target ($cmd_args | get -o 0 | default "")
|
||||
},
|
||||
"stop" => {
|
||||
print "TODO local server stop"
|
||||
},
|
||||
"start" => {
|
||||
print "TODO local server start"
|
||||
},
|
||||
"restart" => {
|
||||
print "TODO local server restart"
|
||||
},
|
||||
_ => {
|
||||
option_undefined "local" "server"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
export def local_create_private_network [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
if $server == null {
|
||||
print $"❗ No server found in settings "
|
||||
return ""
|
||||
}
|
||||
# new_upctl network list -o json |
|
||||
# let net_id = ($data.networks | get -o 0 ).uuid)
|
||||
let zone = ( $server.zone? | default "")
|
||||
if $zone == "" {
|
||||
print $"($server.hostname) No zone found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
let network_private_name = ($server.network_private_name? | default "")
|
||||
if $network_private_name == "" {
|
||||
print $"($server.hostname) No network_private_name found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
let priv_cidr_block = ($server.priv_cidr_block | default "")
|
||||
if $network_private_name == "" {
|
||||
print $"($server.hostname) No priv_cidr_block found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
# EXAMPLE_BASH private_net_id=$(upctl network list -o yaml | $YQ '.networks[] | select(.ip_networks.ip_network[].address == "'"$priv_cidr_block"'") | .uuid' 2>/dev/null | sed 's,",,g')
|
||||
let result = (^upctl "network" "list" "-o" "json" | complete)
|
||||
let private_net_id = if $result.exit_code == 0 {
|
||||
let data = ($result.stdout | from json )
|
||||
($data.networks? | find $priv_cidr_block | get -o 0 | get -o uuid | default "")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
if $check and $private_net_id == "" {
|
||||
print $"❗private_network will be register in a real creation request not in check state"
|
||||
return ""
|
||||
} else if $private_net_id == "" {
|
||||
let result = (^upctl network create --name $network_private_name --zone $zone --ip-network $"address='($priv_cidr_block)',dhcp=true" -o json ) | complete
|
||||
let new_net_id = if $result.exit_code == 0 {
|
||||
(($result.stdout | from json | find $priv_cidr_block | get -o 0).uuid? | default "")
|
||||
} else { "" }
|
||||
if $new_net_id == "" {
|
||||
(throw-error $"🛑 no private network ($network_private_name) found"
|
||||
$"for server ($server.hostname) ip ($server.network_private_ip)"
|
||||
$"local_check_requirements" --span (metadata $new_net_id.span))
|
||||
return false
|
||||
}
|
||||
# Save changes ...
|
||||
#use utils/settings.nu [ save_servers_settings save_settings_file ]
|
||||
let match_text = " network_private_id = "
|
||||
let defs_provider_path = $"($settings.data.server_path | get -o 0 | path dirname)/local_defaults"
|
||||
save_servers_setings $settings $match_text $new_net_id
|
||||
save_settings_file $settings $"($settings.src_path)/($settings.src)" $match_text $new_net_id
|
||||
save_settings_file $settings $"($defs_provider_path)" $match_text $new_net_id
|
||||
}
|
||||
return true
|
||||
}
|
||||
export def local_check_server_requirements [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
if $server.provider != "local" { return false }
|
||||
print ($"✅ (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) does not require creation !" )
|
||||
true
|
||||
}
|
||||
|
||||
export def local_make_settings [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
|
||||
# # _delete_settings
|
||||
let out_settings_path = $"($settings.infra_fullpath)/($server.provider)_settings.yaml"
|
||||
let data = if ($out_settings_path | path exists ) {
|
||||
(open $out_settings_path | from yaml)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
let task = if $data != null { "update" } else { "create" }
|
||||
let uuid = (^upctl server show $server.hostname "-o" "json" | from json).uuid? | default ""
|
||||
# echo "settings:" > "$out_settings"
|
||||
|
||||
# for server in $(_settings_hosts)
|
||||
# do
|
||||
if $uuid == "" {
|
||||
return false
|
||||
}
|
||||
let ip_pub = (local_get_ip $settings $server "public")
|
||||
let ip_priv = (local_get_ip $settings $server "private")
|
||||
|
||||
let server_settings = {
|
||||
name: $server.hostname,
|
||||
id: $uuid,
|
||||
private_net: {
|
||||
id: $server.network_private_id
|
||||
name: $server.network_private_name
|
||||
},
|
||||
zone: $server.zone,
|
||||
datetime: $env.NOW,
|
||||
ip_addresses: {
|
||||
pub: $ip_pub, priv: $ip_priv
|
||||
}
|
||||
}
|
||||
let new_data = if $data != null and $data.servers? != null {
|
||||
( $data.servers | each { |srv|
|
||||
where {|it| $it.name != $server.hostname }
|
||||
}) | append $server_settings
|
||||
} else {
|
||||
## create data record
|
||||
{
|
||||
servers: [ $server_settings ]
|
||||
}
|
||||
}
|
||||
$new_data | to yaml | save --force $out_settings_path
|
||||
print $"✅ local settings ($task) -> ($out_settings_path)"
|
||||
true
|
||||
}
|
||||
export def local_delete_settings [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
}
|
||||
export def local_post_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
if $server != null {
|
||||
return (local_storage_fix_size $settings $server 0)
|
||||
}
|
||||
true
|
||||
}
|
||||
export def local_modify_server [
|
||||
settings: record
|
||||
server: record
|
||||
new_values: list
|
||||
error_exit: bool
|
||||
] {
|
||||
# TODO LOCAL
|
||||
return
|
||||
let res = (^upctl server $server.hostname modify ...($new_values) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Server ($server.hostname) modify ($new_values | str join ' ') errors ($res.stdout ) "
|
||||
if $error_exit {
|
||||
exit 1
|
||||
} else {
|
||||
return "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def local_storage_fix_size [
|
||||
settings: record
|
||||
server: record
|
||||
storage_pos: int
|
||||
] {
|
||||
# TODO LOCAL
|
||||
return
|
||||
let total_size = ($server | get -o storages | get $storage_pos | get -o total | default 0)
|
||||
if $total_size == 0 { return 0 }
|
||||
let storage = (^upctl server show $server.hostname "-o" "json" | from json).storage_devices | (get -o $storage_pos)
|
||||
if $storage == null { return 0 }
|
||||
let curr_size = $storage.storage_size? | default 0
|
||||
if $curr_size == 0 { return 0 }
|
||||
if $curr_size != $total_size {
|
||||
print (
|
||||
$"Stop (_ansi blue_bold)($server.hostname)(_ansi reset) for storage (_ansi yellow_bold)($storage.storage)(_ansi reset)" +
|
||||
$" from (_ansi purple_bold)($curr_size)(_ansi reset) to (_ansi green_bold)($total_size)(_ansi reset) ... "
|
||||
)
|
||||
if (local_change_server_state $settings $server "stop" "") == false {
|
||||
print $"❗ Stop ($server.hostname) errors "
|
||||
return "error"
|
||||
}
|
||||
let res = (^upctl storage modify --size $total_size $storage.storage | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Storage modify errors ($res.stdout ) "
|
||||
return "error"
|
||||
}
|
||||
let new_storage = (^upctl server show $server.hostname "-o" "json" | from json).storage_devices | (get -o $storage_pos)
|
||||
let new_curr_size = $new_storage.storage_size? | default 0
|
||||
print $"Start (_ansi blue_bold)($server.hostname)(_ansi reset) with new size (_ansi green_bold)($new_curr_size)(_ansi reset) ... "
|
||||
if (local_change_server_state $settings $server "start" "") == false {
|
||||
print $"❗ Errors to start ($server.hostname): ($res.stdout ) "
|
||||
return "error"
|
||||
}
|
||||
return "storage"
|
||||
}
|
||||
""
|
||||
}
|
||||
export def local_status_server [
|
||||
hostname: string
|
||||
] {
|
||||
let res = (^upctl server show $hostname "-o" "json" | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ status ($hostname) errors ($res.stdout ) "
|
||||
return ""
|
||||
}
|
||||
return (($res.stdout | from json).state | default "")
|
||||
}
|
||||
export def local_server_exists [
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let res = (^upctl server show $server.hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
if $error_exit {
|
||||
print $"❗ status ($server.hostname) errors ($res.stdout ) "
|
||||
exit 1
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def local_server_state [
|
||||
server: record
|
||||
new_state: string
|
||||
error_exit: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
] {
|
||||
}
|
||||
export def local_server_is_running [
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
true
|
||||
#TODO FIX
|
||||
# let res = (^upctl server show $server.hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
# if $res.exit_code != 0 {
|
||||
# print $"❗ status ($server.hostname) errors ($res.stdout ) "
|
||||
# if $error_exit {
|
||||
# exit 1
|
||||
# } else {
|
||||
# return false
|
||||
# }
|
||||
# }
|
||||
# (($res.stdout | from json).state? | str contains "started" | default false)
|
||||
}
|
||||
export def local_change_server_state [
|
||||
settings: record
|
||||
server: record
|
||||
new_state: string
|
||||
ops: string
|
||||
] {
|
||||
let state = (local_status_server $server.hostname)
|
||||
if $state == "" { return false }
|
||||
if ($state | str contains $new_state) { return true }
|
||||
print $"Checking (_ansi blue_bold)($server.hostname)(_ansi reset) state (_ansi yellow_bold)($new_state)(_ansi reset) ..."
|
||||
let val_timeout = if $server.running_timeout? != null { $server.running_timeout } else { 60 }
|
||||
let wait = if $server.running_wait? != null { $server.running_wait } else { 10 }
|
||||
let wait_duration = ($"($wait)sec"| into duration)
|
||||
mut num = 0
|
||||
while true {
|
||||
let status = (local_status_server $server.hostname)
|
||||
if $status == "" {
|
||||
return false
|
||||
} else if ($status | str contains "maintenance") == false {
|
||||
print " "
|
||||
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)($new_state)(_ansi reset) (_ansi red_bold)failed(_ansi reset) "
|
||||
return false
|
||||
} else {
|
||||
$num = $num + $wait
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)(_ansi green)($server.hostname)(_ansi reset)->($status) "
|
||||
} else {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
}
|
||||
sleep $wait_duration
|
||||
}
|
||||
}
|
||||
let res = if ($ops | str contains "--type" ) {
|
||||
(^upctl server $new_state --type ($ops | str replace "--type " "") $server.hostname | complete)
|
||||
} else if $ops != "" {
|
||||
(^upctl server $new_state $ops $server.hostname | complete)
|
||||
} else {
|
||||
(^upctl server $new_state $server.hostname | complete)
|
||||
}
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗Errors ($server.hostname) to ($new_state) ($res.stdout ) "
|
||||
return false
|
||||
}
|
||||
$num = 0
|
||||
while true {
|
||||
let status = (local_status_server $server.hostname)
|
||||
if ($status | str contains $new_state) {
|
||||
print " "
|
||||
return true
|
||||
} 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)($new_state)(_ansi reset) (_ansi red_bold)failed(_ansi reset) "
|
||||
return false
|
||||
} else {
|
||||
$num = $num + $wait
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)(_ansi green)($server.hostname)(_ansi reset)->($status) "
|
||||
} else {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
}
|
||||
sleep $wait_duration
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
export def local_delete_server_storage [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
print ($"✅ (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) does not require delete storage !" )
|
||||
true
|
||||
}
|
||||
export def local_delete_server [
|
||||
settings: record
|
||||
server: record
|
||||
keep_storage: bool
|
||||
error_exit: bool
|
||||
] {
|
||||
print ($"✅ (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) does not require delete !" )
|
||||
true
|
||||
}
|
||||
41
providers/local/nulib/local/usage.nu
Normal file
41
providers/local/nulib/local/usage.nu
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
#!/usr/bin/env nu
|
||||
|
||||
# myscript.nu
|
||||
export def usage [provider: string, infra: string] {
|
||||
let info = if ( $env.CURRENT_FILE? | into string ) != "" { (^grep "^# Info:" $env.CURRENT_FILE ) | str replace "# Info: " "" } else { "" }
|
||||
# $(declare -F _usage_options >/dev/null && _usage_options)
|
||||
$"
|
||||
USAGE provisioning ($provider) -k cloud-path file-settings.yaml provider-options
|
||||
DESCRIPTION
|
||||
LOCAL ($info)
|
||||
OPTIONS
|
||||
-s server-hostname
|
||||
with server-hostname target selection
|
||||
-p provider-name
|
||||
use provider name
|
||||
do not need if 'current directory path basename' is not one of providers available
|
||||
-new | new [provisioning-name]
|
||||
create a new provisioning-directory-name by a copy of ($infra)
|
||||
-k cloud-path-item
|
||||
use cloud-path-item as base directory for settings
|
||||
-x
|
||||
Trace script with 'set -x'
|
||||
providerslist | providers-list | providers list
|
||||
Get available providers list
|
||||
taskslist | tasks-list | tasks list
|
||||
Get available tasks list
|
||||
serviceslist | service-list
|
||||
Get available services list
|
||||
tools
|
||||
Run core/on-tools info
|
||||
-i
|
||||
About this
|
||||
-v
|
||||
Print version
|
||||
-h, --help
|
||||
Print this help and exit.
|
||||
"
|
||||
# ["hello" $name $title]
|
||||
}
|
||||
|
||||
0
providers/local/nulib/local/utils.nu
Normal file
0
providers/local/nulib/local/utils.nu
Normal file
4
providers/local/provisioning.yaml
Normal file
4
providers/local/provisioning.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
version: 1.0
|
||||
info: Local provisioning
|
||||
site: ""
|
||||
tools: []
|
||||
0
providers/local/versions
Normal file
0
providers/local/versions
Normal file
882
providers/prov_lib/create_middleware.nu
Normal file
882
providers/prov_lib/create_middleware.nu
Normal file
|
|
@ -0,0 +1,882 @@
|
|||
def provider_lib_has_method [
|
||||
providers_path: string
|
||||
prov: string
|
||||
method: string
|
||||
]: nothing -> bool {
|
||||
let prov_root = ($providers_path | path join $prov | path join "nulib" | path join $prov)
|
||||
let res = (^grep $method ...(glob ($prov_root | path join "*")) err> /dev/null | complete)
|
||||
($res.stdout | is-not-empty)
|
||||
}
|
||||
|
||||
def make_provider_undefined [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
'def provider_undefined [
|
||||
server: record
|
||||
] {
|
||||
#use defs/lists.nu providers_list
|
||||
let str_providers_list = (providers_list | each { |it| $it.name} | str join " ")
|
||||
print ($"(_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) ")
|
||||
let text = ( $"expected to be one of available providers [(_ansi green_italic)($str_providers_list)(_ansi reset)], " +
|
||||
$"got (_ansi green_bold)($server.provider)(_ansi reset)")
|
||||
print $"Error 🛑 provider ($text)"
|
||||
}'
|
||||
}
|
||||
def make_mw_query_servers [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_query_servers [
|
||||
settings: record
|
||||
find?: string
|
||||
cols?: string
|
||||
--prov: string
|
||||
--serverpos: int
|
||||
] {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
#let res = for idx in ..($settings.data.servers | length) {
|
||||
#let srv = ($settings.data.servers | get -o $idx)
|
||||
if $prov == null or $it.item.provider == $prov {
|
||||
if $serverpos == null or $serverpos == $it.index {
|
||||
let res = match $it.item.provider {'
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_query_servers"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $str_find $str_cols)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $it.item
|
||||
[]
|
||||
}
|
||||
}
|
||||
if ($res | length) > 0 {
|
||||
let result = if $str_find != "" {
|
||||
$res | find $str_find
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
if $str_cols != "" {
|
||||
let field_list = ($str_cols | split row ",")
|
||||
($result | select -o $field_list)
|
||||
} else {
|
||||
$result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# $list | append $srv
|
||||
} | flatten
|
||||
}' | str join ""
|
||||
}
|
||||
def make_mw_servers_ips [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_servers_ips [
|
||||
settings: record
|
||||
data: list
|
||||
prov?: string
|
||||
serverpos?: int
|
||||
]: nothing -> list {
|
||||
mut index = -1
|
||||
mut result = []
|
||||
for srv in $data {
|
||||
$index += 1
|
||||
let settings_server = ($settings.data.servers | where {|it| $it.hostname == $srv.hostname})
|
||||
if ($settings_server | length) == 0 { continue }
|
||||
let provider = ($settings_server | get -o provider | default "")
|
||||
if $prov != null and $provider != $prov { continue }
|
||||
if $serverpos != null and $serverpos != $index { continue }
|
||||
match $provider { '
|
||||
for prov in $providers_list {
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {' | append '
|
||||
if $srv.ip_addresses? != null {
|
||||
$result = ($result | append ($srv.ip_addresses? |
|
||||
each {|it| { hostname: $srv.hostname, ip: $it.address, access: $it.access, family: $it.family }} |
|
||||
flatten
|
||||
))
|
||||
}
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $srv.provider
|
||||
[]
|
||||
}
|
||||
}
|
||||
}
|
||||
$result
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_server_info [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_server_info [
|
||||
server: record
|
||||
check: bool
|
||||
find?: string
|
||||
cols?: string
|
||||
]: nothing -> record {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
let res = match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_server_info"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $check)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output = ($output | append '
|
||||
_ => {
|
||||
provider_undefined $server.hostname
|
||||
[]
|
||||
}
|
||||
}
|
||||
if $res.hostname? != null {
|
||||
let result = if $str_find != "" {
|
||||
$res | find $str_find
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
let info = if $str_cols != "" {
|
||||
let field_list = ($str_cols | split row ",")
|
||||
($result | select -o $field_list)
|
||||
} else {
|
||||
($result)
|
||||
}
|
||||
let priv = match $server.provider {' | str join "")
|
||||
for prov in $providers_list {
|
||||
if $prov == "aws" {
|
||||
$output = ($output | append '
|
||||
"aws" => {
|
||||
($info | get -o private_ips | default [] | each {|it| ($it | select Description PrivateIpAddress VpcId SubnetId Groups) })
|
||||
},' | str join "")
|
||||
}
|
||||
}
|
||||
$output | append '
|
||||
_ => ($info | get -o priv | default "")
|
||||
}
|
||||
let full_info = if ($priv | length) > 0 {
|
||||
($info | merge { private_ips: $priv })
|
||||
} else {
|
||||
$info
|
||||
}
|
||||
if not $check {
|
||||
print ($full_info | table -e)
|
||||
}
|
||||
$full_info
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_servers_info [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
'
|
||||
export def mw_servers_info [
|
||||
settings: record
|
||||
find?: string
|
||||
cols?: string
|
||||
--prov: string
|
||||
--serverpos: int
|
||||
--check
|
||||
]: nothing -> nothing {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
if $prov == null or $it.item.provider == $prov {
|
||||
if $serverpos == null or $serverpos == $it.index {
|
||||
mw_server_info $it.item $check $str_find $str_cols
|
||||
}
|
||||
}
|
||||
}
|
||||
}'
|
||||
}
|
||||
def make_mw_create_server [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
let res = match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_check_server_requirements"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
print ($"\(($prov)_on_prov_server $server)")
|
||||
($"\(($method) $settings $server $check)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
if not $res {
|
||||
(throw-error $"🛑 ($server.provider) check requirements error"
|
||||
$"for server ($server.hostname)"
|
||||
"create_server" --span (metadata $server.provider).span)
|
||||
return false
|
||||
}
|
||||
print ($"Create (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($zone) ")
|
||||
return true
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_server_state [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_server_state [
|
||||
server: record
|
||||
new_state: string
|
||||
error_exit: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
]: nothing -> bool {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_server_state"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $new_state $error_exit $wait $settings)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return false }
|
||||
}
|
||||
}
|
||||
true
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_server_exists [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_server_exists [
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider {'
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_server_exists"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_server_is_running [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_server_is_running [
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_server_is_running"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_get_ip [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_get_ip [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type: string
|
||||
error_exit: bool
|
||||
]: nothing -> string {
|
||||
let use_type = match $ip_type {
|
||||
"$network_public_ip" => "public",
|
||||
"$network_private_ip" => "private",
|
||||
_ => $ip_type
|
||||
}
|
||||
let res = match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_server"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) [ "get_ip", $use_type ] --server $server --settings $settings)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { "" }
|
||||
}
|
||||
}
|
||||
$"($res)" | str trim
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_wait_storage [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_wait_storage [
|
||||
settings: record
|
||||
server: record
|
||||
new_state: str
|
||||
id: str
|
||||
]: nothing -> record {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_wait_storage"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
let str_it = "$server"
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $new_state $id)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_create_storage [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_create_storage [
|
||||
settings: record
|
||||
server: record
|
||||
server_info: record
|
||||
storage: record
|
||||
volumes: list
|
||||
total_size: int
|
||||
]: nothing -> record {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_create_storage"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
let str_it = "$server"
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $server_info $storage $volumes $total_size)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_post_create_server [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_post_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_post_create_server"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
let str_it = "$server"
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings ($str_it) $check)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_modify_server [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_modify_server [
|
||||
settings: record
|
||||
server: record
|
||||
new_values: list
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_modify_server"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
let str_it = "$server"
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings ($str_it) $new_values $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_delete_server_storage [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_delete_server_storage [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_delete_server_storage"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
print ($"\(($prov)_on_prov_server $server)")
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
#print ($"Delete storage (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
# $"(_ansi green_bold)($server.provider)(_ansi reset) ($zone) ")
|
||||
#true
|
||||
}
|
||||
def make_mw_delete_server [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_delete_server [
|
||||
settings: record
|
||||
server: record
|
||||
keep_storage: bool
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_delete_server"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
print ($"\(($prov)_on_prov_server $server)")
|
||||
($"\(($method) $settings $server $keep_storage $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
#print ($"Delete (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
#$"(_ansi green_bold)($server.provider)(_ansi reset) ($zone) ")
|
||||
#true
|
||||
}
|
||||
def make_mw_load_infra_servers_info [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_load_infra_servers_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_load_infra_servers_info"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { {} }
|
||||
}
|
||||
}
|
||||
} ' | str join "\n"
|
||||
}
|
||||
def make_mw_load_infra_storages_info [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_load_infra_storages_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_load_infra_storages_info"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { {} }
|
||||
}
|
||||
}
|
||||
} ' | str join "\n"
|
||||
}
|
||||
def make_mw_get_infra_storage [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_get_infra_storage [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
error_exit: bool
|
||||
]: nothing -> list {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_get_item_for_storage"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $settings $cloud_data)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { [] }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_get_infra_item [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_get_infra_item [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_get_item_for_server"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $server $settings $cloud_data)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return {} }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_get_infra_price [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_get_infra_price [
|
||||
server: record
|
||||
data: record
|
||||
key: string
|
||||
error_exit: bool
|
||||
price_col?: string
|
||||
]: nothing -> float {
|
||||
if ($data | get -o item | is-empty) { return {} }
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_get_price"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $data $key $price_col)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return 0 }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_start_cache_info [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_start_cache_info [
|
||||
settings: record
|
||||
server: record
|
||||
]: nothing -> nothing {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_start_cache_info"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_create_cache [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_create_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_create_cache"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return 0 }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_read_cache [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_read_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_read_cache"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_clean_cache [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_clean_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_clean_cache"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
def make_mw_ip_from_cache [
|
||||
providers_path: string
|
||||
providers_list: list<string>
|
||||
]: nothing -> string {
|
||||
mut output = '
|
||||
export def mw_ip_from_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider { '
|
||||
for prov in $providers_list {
|
||||
let method = $"($prov)_ip_from_cache"
|
||||
if not (provider_lib_has_method $providers_path $prov $method) { continue }
|
||||
$output = ($output | append $'
|
||||
"($prov)" => {
|
||||
($"\(($method) $settings $server $error_exit)")
|
||||
},' | str join "")
|
||||
}
|
||||
$output | append '
|
||||
"local" => {
|
||||
($server | get -o network_public_ip | default "")
|
||||
#(local_ip_from_cache $settings $server $error_exit)
|
||||
}
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
} ' | str join ""
|
||||
}
|
||||
# - > Make middleware (middleware.nu env_middleware.nu) for existing providers
|
||||
export def make_middleware [
|
||||
] {
|
||||
let provisioning_path = ($env.PROVISIONING? | default ("/" | path join "usr" |path join "local" | path join "provisioning"))
|
||||
let providers_path = ($provisioning_path | path join "providers")
|
||||
if not ($providers_path | path exists) {
|
||||
print $"🛑 providers path (ansi red_bold)($providers_path)(ansi reset) not found"
|
||||
exit 1
|
||||
}
|
||||
let middleware_path = ($providers_path | path join "prov_lib" | path join "middleware.nu" )
|
||||
let env_middleware_path = ($providers_path | path join "prov_lib" | path join "env_middleware.nu" )
|
||||
let providers_list = (ls -s $providers_path | where {|it| (
|
||||
($it.name | str starts-with "_") == false
|
||||
and ($providers_path | path join $it.name | path type) == "dir"
|
||||
and ($providers_path | path join $it.name | path join "templates" | path exists)
|
||||
)
|
||||
} | select name | values | flatten )
|
||||
let use_list = [ servers.nu, cache.nu, prices.nu, utils.nu ]
|
||||
mut output = $"# CNPROV middleware generated by 'make_middleware' on (date now | format date '%Y-%m-%d %H:%M:%S')"
|
||||
mut env_output = ($output | append "\nexport-env {" | str join "\n")
|
||||
for prov in $providers_list {
|
||||
let prov_root = ($providers_path | path join $prov | path join "nulib" | path join $prov)
|
||||
if not ($prov_root | path exists ) { continue }
|
||||
if ($prov_root | path join "env.nu" | path exists ) { $env_output = ($env_output | append $" use ($prov)/env.nu" | str join "\n") }
|
||||
for $item in $use_list {
|
||||
if ($prov_root | path join $item | path exists ) { $output = ($output | append $"use ($prov)/($item) *" | str join "\n") }
|
||||
}
|
||||
}
|
||||
$env_output | append "}" | str join "" | save --force $env_middleware_path
|
||||
$output | append (make_provider_undefined $providers_path $providers_list) | str join "\n"
|
||||
| append (make_mw_query_servers $providers_path $providers_list)
|
||||
| append (make_mw_servers_ips $providers_path $providers_list)
|
||||
| append (make_mw_server_info $providers_path $providers_list)
|
||||
| append (make_mw_servers_info $providers_path $providers_list)
|
||||
| append (make_mw_create_server $providers_path $providers_list)
|
||||
| append (make_mw_server_state $providers_path $providers_list)
|
||||
| append (make_mw_server_exists $providers_path $providers_list)
|
||||
| append (make_mw_server_is_running $providers_path $providers_list)
|
||||
| append (make_mw_get_ip $providers_path $providers_list)
|
||||
| append (make_mw_wait_storage $providers_path $providers_list)
|
||||
| append (make_mw_create_storage $providers_path $providers_list)
|
||||
| append (make_mw_post_create_server $providers_path $providers_list)
|
||||
| append (make_mw_modify_server $providers_path $providers_list)
|
||||
| append (make_mw_delete_server_storage $providers_path $providers_list)
|
||||
| append (make_mw_delete_server $providers_path $providers_list)
|
||||
| append (make_mw_load_infra_servers_info $providers_path $providers_list)
|
||||
| append (make_mw_load_infra_storages_info $providers_path $providers_list)
|
||||
| append (make_mw_get_infra_storage $providers_path $providers_list)
|
||||
| append (make_mw_get_infra_item $providers_path $providers_list)
|
||||
| append (make_mw_get_infra_price $providers_path $providers_list)
|
||||
| append (make_mw_start_cache_info $providers_path $providers_list)
|
||||
| append (make_mw_create_cache $providers_path $providers_list)
|
||||
| append (make_mw_read_cache $providers_path $providers_list)
|
||||
| append (make_mw_clean_cache $providers_path $providers_list)
|
||||
| str join ""
|
||||
| save --force $middleware_path
|
||||
}
|
||||
6
providers/prov_lib/env_middleware.nu
Normal file
6
providers/prov_lib/env_middleware.nu
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# CNPROV middleware generated by 'make_middleware' on 2024-04-08_21:24:42
|
||||
export-env {
|
||||
use aws/env.nu
|
||||
use local/env.nu
|
||||
use upcloud/env.nu
|
||||
}
|
||||
603
providers/prov_lib/middleware.nu
Normal file
603
providers/prov_lib/middleware.nu
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
# CNPROV middleware generated by 'make_middleware' on 2024-04-08_21:24:42
|
||||
use ../aws/nulib/aws/env.nu
|
||||
use ../aws/nulib/aws/servers.nu *
|
||||
use ../aws/nulib/aws/cache.nu *
|
||||
use ../aws/nulib/aws/prices.nu *
|
||||
use ../local/nulib/local/env.nu
|
||||
use ../local/nulib/local/servers.nu *
|
||||
use ../upcloud/nulib/upcloud/env.nu
|
||||
use ../upcloud/nulib/upcloud/servers.nu *
|
||||
use ../upcloud/nulib/upcloud/cache.nu *
|
||||
use ../upcloud/nulib/upcloud/prices.nu *
|
||||
def provider_undefined [
|
||||
server: record
|
||||
] {
|
||||
#use defs/lists.nu providers_list
|
||||
let str_providers_list = (providers_list "selection" | each { |it| $it.name} | str join " ")
|
||||
print ($"(_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) ")
|
||||
let text = ( $"expected to be one of available providers [(_ansi green_italic)($str_providers_list)(_ansi reset)], " +
|
||||
$"got (_ansi green_bold)($server.provider)(_ansi reset)")
|
||||
print $"Error 🛑 provider ($text)"
|
||||
}
|
||||
export def mw_query_servers [
|
||||
settings: record
|
||||
find?: string
|
||||
cols?: string
|
||||
--prov: string
|
||||
--serverpos: int
|
||||
] {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
#let res = for idx in ..($settings.data.servers | length) {
|
||||
#let srv = ($settings.data.servers | get -o $idx)
|
||||
if $prov == null or $it.item.provider == $prov {
|
||||
if $serverpos == null or $serverpos == $it.index {
|
||||
let res = match $it.item.provider {
|
||||
"aws" => {
|
||||
(aws_query_servers $str_find $str_cols)
|
||||
},
|
||||
"local" => {
|
||||
(local_query_servers $str_find $str_cols)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_query_servers $str_find $str_cols)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $it.item
|
||||
[]
|
||||
}
|
||||
}
|
||||
if ($res | length) > 0 {
|
||||
let result = if $str_find != "" {
|
||||
$res | find $str_find
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
if $str_cols != "" {
|
||||
let field_list = ($str_cols | split row ",")
|
||||
($result | select -o $field_list)
|
||||
} else {
|
||||
$result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# $list | append $srv
|
||||
} | flatten
|
||||
}
|
||||
export def mw_servers_ips [
|
||||
settings: record
|
||||
data: list
|
||||
prov?: string
|
||||
serverpos?: int
|
||||
]: nothing -> list {
|
||||
mut index = -1
|
||||
mut result = []
|
||||
for srv in $data {
|
||||
$index += 1
|
||||
let settings_server = ($settings.data.servers | where {|it| $it.hostname == $srv.hostname})
|
||||
if ($settings_server | length) == 0 { continue }
|
||||
let provider = ($settings_server | get -o 0 | get -o provider | default "")
|
||||
if $prov != null and $provider != $prov { continue }
|
||||
if $serverpos != null and $serverpos != $index { continue }
|
||||
match $provider {
|
||||
"aws" => {
|
||||
if $srv.ip_addresses? != null {
|
||||
$result = ($result | append ($srv.ip_addresses? |
|
||||
each {|it| { hostname: $srv.hostname, ip: $it.address, access: $it.access, family: $it.family }} |
|
||||
flatten
|
||||
))
|
||||
}
|
||||
},
|
||||
"local" => {
|
||||
if $srv.ip_addresses? != null {
|
||||
$result = ($result | append ($srv.ip_addresses? |
|
||||
each {|it| { hostname: $srv.hostname, ip: $it.address, access: $it.access, family: $it.family }} |
|
||||
flatten
|
||||
))
|
||||
}
|
||||
},
|
||||
"upcloud" => {
|
||||
if $srv.ip_addresses? != null {
|
||||
$result = ($result | append ($srv.ip_addresses? |
|
||||
each {|it| { hostname: $srv.hostname, ip: $it.address, access: $it.access, family: $it.family }} |
|
||||
flatten
|
||||
))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $srv.provider
|
||||
[]
|
||||
}
|
||||
}
|
||||
}
|
||||
$result
|
||||
}
|
||||
export def mw_server_info [
|
||||
server: record
|
||||
check: bool
|
||||
find?: string
|
||||
cols?: string
|
||||
]: nothing -> record {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
let res = match $server.provider {
|
||||
"aws" => {
|
||||
(aws_server_info $server $check)
|
||||
},
|
||||
"local" => {
|
||||
(local_server_info $server $check)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_server_info $server $check)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server.hostname
|
||||
[]
|
||||
}
|
||||
}
|
||||
if ($res | describe | str starts-with "record") and $res.hostname? != null {
|
||||
let result = if $str_find != "" {
|
||||
$res | find $str_find
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
let info = if $str_cols != "" {
|
||||
let field_list = ($str_cols | split row ",")
|
||||
($result | select -o $field_list)
|
||||
} else {
|
||||
($result)
|
||||
}
|
||||
let priv = match $server.provider {
|
||||
"aws" => {
|
||||
($info | get -o private_ips | default [] | each {|it| ($it | select Description PrivateIpAddress VpcId SubnetId Groups) })
|
||||
},
|
||||
_ => ($info | get -o priv | default [])
|
||||
}
|
||||
let full_info = if ($priv | length) > 0 {
|
||||
($info | merge { private_ips: $priv })
|
||||
} else {
|
||||
$info
|
||||
}
|
||||
let out = ($env | get -o PROVISIONING_OUT| default "")
|
||||
if ($out | is-empty) {
|
||||
print ($full_info | table -e)
|
||||
}
|
||||
if (not $check) {
|
||||
($full_info | table -e)
|
||||
}
|
||||
$full_info
|
||||
} else {
|
||||
$res
|
||||
}
|
||||
}
|
||||
export def mw_servers_info [
|
||||
settings: record
|
||||
find?: string
|
||||
cols?: string
|
||||
--prov: string
|
||||
--serverpos: int
|
||||
--check
|
||||
]: nothing -> list {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
if $prov == null or $it.item.provider == $prov {
|
||||
if $serverpos == null or $serverpos == $it.index {
|
||||
mw_server_info $it.item $check $str_find $str_cols
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
let res = match $server.provider {
|
||||
"aws" => {
|
||||
print (aws_on_prov_server $server)
|
||||
(aws_check_server_requirements $settings $server $check)
|
||||
},
|
||||
"local" => {
|
||||
print (local_on_prov_server $server)
|
||||
(local_check_server_requirements $settings $server $check)
|
||||
},
|
||||
"upcloud" => {
|
||||
print (upcloud_on_prov_server $server)
|
||||
(upcloud_check_server_requirements $settings $server $check)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
if not $res {
|
||||
(throw-error $"🛑 ($server.provider) check requirements error"
|
||||
$"for server ($server.hostname)"
|
||||
"create_server" --span (metadata $server.provider).span)
|
||||
return false
|
||||
}
|
||||
print ($"Create (_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($zone) ")
|
||||
return true
|
||||
}
|
||||
export def mw_server_state [
|
||||
server: record
|
||||
new_state: string
|
||||
error_exit: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
]: nothing -> bool {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_server_state $server $new_state $error_exit $wait $settings)
|
||||
},
|
||||
"local" => {
|
||||
(local_server_state $server $new_state $error_exit $wait $settings)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_server_state $server $new_state $error_exit $wait $settings)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return false }
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def mw_server_exists [
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_server_exists $server $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
(local_server_exists $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_server_exists $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_server_is_running [
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_server_is_running $server $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
(local_server_is_running $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_server_is_running $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_get_ip [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type: string
|
||||
error_exit: bool
|
||||
]: nothing -> string {
|
||||
let use_type = match $ip_type {
|
||||
"$network_public_ip" => "public",
|
||||
"$network_private_ip" => "private",
|
||||
_ => $ip_type
|
||||
}
|
||||
let res = match $server.provider {
|
||||
"aws" => {
|
||||
(aws_server [ "get_ip", $use_type ] --server $server --settings $settings)
|
||||
},
|
||||
"local" => {
|
||||
(local_server [ "get_ip", $use_type ] --server $server --settings $settings)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_server [ "get_ip", $use_type ] --server $server --settings $settings)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { "" }
|
||||
}
|
||||
}
|
||||
$"($res)" | str trim
|
||||
}
|
||||
export def mw_post_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_post_create_server $settings $server $check)
|
||||
},
|
||||
"local" => {
|
||||
(local_post_create_server $settings $server $check)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_post_create_server $settings $server $check)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_modify_server [
|
||||
settings: record
|
||||
server: record
|
||||
new_values: list
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_modify_server $settings $server $new_values $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
(local_modify_server $settings $server $new_values $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_modify_server $settings $server $new_values $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server.provider
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_delete_server_storage [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
print (aws_on_prov_server $server)
|
||||
(aws_delete_server_storage $settings $server $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
print (local_on_prov_server $server)
|
||||
(local_delete_server_storage $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
print (upcloud_on_prov_server $server)
|
||||
(upcloud_delete_server_storage $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_delete_server [
|
||||
settings: record
|
||||
server: record
|
||||
keep_storage: bool
|
||||
error_exit: bool
|
||||
]: nothing -> bool {
|
||||
let zone = $server.zone? | default ""
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
print (aws_on_prov_server $server)
|
||||
(aws_delete_server $settings $server $keep_storage $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
print (local_on_prov_server $server)
|
||||
(local_delete_server $settings $server $keep_storage $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
print (upcloud_on_prov_server $server)
|
||||
(upcloud_delete_server $settings $server $keep_storage $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_load_infra_servers_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_load_infra_servers_info $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_load_infra_servers_info $settings $server $error_exit)
|
||||
},
|
||||
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_load_infra_storages_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_load_infra_storages_info $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_load_infra_storages_info $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_get_infra_storage [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
error_exit: bool
|
||||
]: nothing -> list {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_get_item_for_storage $server $settings $cloud_data)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_get_item_for_storage $server $settings $cloud_data)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { [] }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_get_infra_item [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_get_item_for_server $server $settings $cloud_data)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_get_item_for_server $server $settings $cloud_data)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_get_infra_price [
|
||||
server: record
|
||||
data: record
|
||||
key: string
|
||||
error_exit: bool
|
||||
price_col?: string
|
||||
]: nothing -> float {
|
||||
if ($data | get -o item | is-empty) { return {} }
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_get_price $data $key $price_col)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_get_price $data $key $price_col)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_start_cache_info [
|
||||
settings: record
|
||||
server: record
|
||||
]: nothing -> nothing {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_start_cache_info $settings $server)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_start_cache_info $settings $server)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_create_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_create_cache $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_create_cache $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_read_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_read_cache $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_read_cache $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_clean_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_clean_cache $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_clean_cache $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
}
|
||||
export def mw_ip_from_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> nothing {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_ip_from_cache $settings $server $error_exit)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_ip_from_cache $settings $server $error_exit)
|
||||
},
|
||||
"local" => {
|
||||
($server | get -o network_public_ip | default "")
|
||||
#(local_ip_from_cache $settings $server $error_exit)
|
||||
},
|
||||
_ => {
|
||||
provider_undefined $server
|
||||
if $error_exit { exit } else { return }
|
||||
}
|
||||
}
|
||||
}
|
||||
233
providers/prov_lib/middleware_enhanced.nu
Normal file
233
providers/prov_lib/middleware_enhanced.nu
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
# Enhanced middleware with extension support
|
||||
# This file can replace middleware.nu to support dynamic provider loading
|
||||
|
||||
use ../../core/nulib/lib_provisioning/extensions/registry.nu *
|
||||
|
||||
# Import core providers (keep existing functionality)
|
||||
use ../aws/nulib/aws/env.nu
|
||||
use ../aws/nulib/aws/servers.nu *
|
||||
use ../aws/nulib/aws/cache.nu *
|
||||
use ../aws/nulib/aws/prices.nu *
|
||||
use ../local/nulib/local/env.nu
|
||||
use ../local/nulib/local/servers.nu *
|
||||
use ../upcloud/nulib/upcloud/env.nu
|
||||
use ../upcloud/nulib/upcloud/servers.nu *
|
||||
use ../upcloud/nulib/upcloud/cache.nu *
|
||||
use ../upcloud/nulib/upcloud/prices.nu *
|
||||
|
||||
# Initialize extension registry on first load
|
||||
init-registry
|
||||
|
||||
def provider_undefined [
|
||||
server: record
|
||||
] {
|
||||
let str_providers_list = (providers_list "selection" | each { |it| $it.name} | str join " ")
|
||||
print ($"(_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
|
||||
$"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) ")
|
||||
let text = ( $"expected to be one of available providers [(_ansi green_italic)($str_providers_list)(_ansi reset)], " +
|
||||
$"got (_ansi green_bold)($server.provider)(_ansi reset)")
|
||||
print $"Error 🛑 provider ($text)"
|
||||
}
|
||||
|
||||
# Load extension provider dynamically
|
||||
def load_extension_provider [provider_name: string] {
|
||||
let provider_info = (get-provider $provider_name)
|
||||
if ($provider_info | is-not-empty) and $provider_info.available {
|
||||
try {
|
||||
use ($provider_info.entry_point) *
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
# Enhanced query with extension support
|
||||
export def mw_query_servers [
|
||||
settings: record
|
||||
find?: string
|
||||
cols?: string
|
||||
--prov: string
|
||||
--serverpos: int
|
||||
] {
|
||||
let str_find = if $find != null { $find } else { "" }
|
||||
let str_cols = if $cols != null { $cols } else { "" }
|
||||
$settings.data.servers | enumerate | each { |it|
|
||||
if $prov == null or $it.item.provider == $prov {
|
||||
if $serverpos == null or $serverpos == $it.index {
|
||||
let res = match $it.item.provider {
|
||||
"aws" => {
|
||||
(aws_query_servers $str_find $str_cols)
|
||||
},
|
||||
"local" => {
|
||||
(local_query_servers $str_find $str_cols)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_query_servers $str_find $str_cols)
|
||||
},
|
||||
_ => {
|
||||
# Try loading extension provider
|
||||
if (load_extension_provider $it.item.provider) {
|
||||
# Dynamically call provider function
|
||||
try {
|
||||
# Convention: {provider}_query_servers
|
||||
let func_name = $"($it.item.provider)_query_servers"
|
||||
(nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($str_find) ($str_cols)")
|
||||
} catch {
|
||||
provider_undefined $it.item
|
||||
[]
|
||||
}
|
||||
} else {
|
||||
provider_undefined $it.item
|
||||
[]
|
||||
}
|
||||
}
|
||||
}
|
||||
$res
|
||||
}
|
||||
}
|
||||
} | flatten
|
||||
}
|
||||
|
||||
# Enhanced server creation with extension support
|
||||
export def mw_create_servers [
|
||||
settings: record
|
||||
servers: table
|
||||
check: bool
|
||||
wait: bool
|
||||
] {
|
||||
$servers | each { |server|
|
||||
# Check if provider is allowed by profile
|
||||
use ../../core/nulib/lib_provisioning/extensions/profiles.nu is-provider-allowed
|
||||
if not (is-provider-allowed $server.provider) {
|
||||
print $"🛑 Provider ($server.provider) blocked by profile"
|
||||
continue
|
||||
}
|
||||
|
||||
let res = match $server.provider {
|
||||
"aws" => {
|
||||
(aws_create_servers $settings [$server] $check $wait)
|
||||
},
|
||||
"local" => {
|
||||
(local_create_servers $settings [$server] $check $wait)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_create_servers $settings [$server] $check $wait)
|
||||
},
|
||||
_ => {
|
||||
# Try loading extension provider
|
||||
if (load_extension_provider $server.provider) {
|
||||
try {
|
||||
let func_name = $"($server.provider)_create_servers"
|
||||
(nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ([$server] | to json) ($check) ($wait)")
|
||||
} catch {
|
||||
provider_undefined $server
|
||||
[]
|
||||
}
|
||||
} else {
|
||||
provider_undefined $server
|
||||
[]
|
||||
}
|
||||
}
|
||||
}
|
||||
$res
|
||||
}
|
||||
}
|
||||
|
||||
# Enhanced server deletion with extension support
|
||||
export def mw_delete_servers [
|
||||
settings: record
|
||||
servers: table
|
||||
check: bool
|
||||
] {
|
||||
$servers | each { |server|
|
||||
# Check if provider is allowed by profile
|
||||
use ../../core/nulib/lib_provisioning/extensions/profiles.nu is-provider-allowed
|
||||
if not (is-provider-allowed $server.provider) {
|
||||
print $"🛑 Provider ($server.provider) blocked by profile"
|
||||
continue
|
||||
}
|
||||
|
||||
let res = match $server.provider {
|
||||
"aws" => {
|
||||
(aws_delete_servers $settings [$server] $check)
|
||||
},
|
||||
"local" => {
|
||||
(local_delete_servers $settings [$server] $check)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_delete_servers $settings [$server] $check)
|
||||
},
|
||||
_ => {
|
||||
# Try loading extension provider
|
||||
if (load_extension_provider $server.provider) {
|
||||
try {
|
||||
let func_name = $"($server.provider)_delete_servers"
|
||||
(nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ([$server] | to json) ($check)")
|
||||
} catch {
|
||||
provider_undefined $server
|
||||
[]
|
||||
}
|
||||
} else {
|
||||
provider_undefined $server
|
||||
[]
|
||||
}
|
||||
}
|
||||
}
|
||||
$res
|
||||
}
|
||||
}
|
||||
|
||||
# Get IP with extension support
|
||||
export def mw_get_ip [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type: string
|
||||
public_fallback: bool
|
||||
] -> string {
|
||||
match $server.provider {
|
||||
"aws" => {
|
||||
(aws_get_ip $settings $server $ip_type $public_fallback)
|
||||
},
|
||||
"local" => {
|
||||
(local_get_ip $settings $server $ip_type $public_fallback)
|
||||
},
|
||||
"upcloud" => {
|
||||
(upcloud_get_ip $settings $server $ip_type $public_fallback)
|
||||
},
|
||||
_ => {
|
||||
# Try loading extension provider
|
||||
if (load_extension_provider $server.provider) {
|
||||
try {
|
||||
let func_name = $"($server.provider)_get_ip"
|
||||
(nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ($server | to json) ($ip_type) ($public_fallback)")
|
||||
} catch {
|
||||
""
|
||||
}
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# List all providers (core + extensions)
|
||||
export def mw_list_all_providers [] {
|
||||
let core_providers = [
|
||||
{ name: "aws", type: "core", path: "../aws" }
|
||||
{ name: "local", type: "core", path: "../local" }
|
||||
{ name: "upcloud", type: "core", path: "../upcloud" }
|
||||
]
|
||||
|
||||
let extension_providers = (list-providers | each {|ext|
|
||||
{
|
||||
name: $ext.name
|
||||
type: "extension"
|
||||
path: $ext.source
|
||||
version: $ext.version
|
||||
}
|
||||
})
|
||||
|
||||
$core_providers | append $extension_providers
|
||||
}
|
||||
6
providers/prov_lib/mod.nu
Normal file
6
providers/prov_lib/mod.nu
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use upcloud/servers.nu *
|
||||
use aws/servers.nu *
|
||||
use local/servers.nu *
|
||||
|
||||
export use middleware.nu *
|
||||
|
||||
1
providers/providers
Symbolic link
1
providers/providers
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../providers
|
||||
4
providers/upcloud/bin/get_plans.sh
Executable file
4
providers/upcloud/bin/get_plans.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
[ -z "$1" ] && echo "no prefix plans found !!
|
||||
All plans can be display with: upctl server plans" && exit 1
|
||||
upctl server plans | grep $1 | awk '{ print $1}' | sed 's/^/\| "/g' | sed 's/$/"/g' | tr -d "\n"
|
||||
4
providers/upcloud/bin/get_zones.sh
Executable file
4
providers/upcloud/bin/get_zones.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
[ -z "$1" ] && echo "no prefix zone found !!
|
||||
All zones can be display with: upctl zone list" && exit 1
|
||||
upctl zone list | grep $1 | awk '{ print $1}' | sed 's/^/\| "/g' | sed 's/$/"/g' | tr -d "\n"
|
||||
122
providers/upcloud/bin/install.sh
Executable file
122
providers/upcloud/bin/install.sh
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
#!/bin/bash
|
||||
# Info: Script to install provider
|
||||
# Author: JesusPerezLorenzo
|
||||
# Release: 1.0
|
||||
# Date: 15-04-2024
|
||||
|
||||
[ "$DEBUG" == "-x" ] && set -x
|
||||
|
||||
USAGE="install [ tool-name: upctl, etc | all | info] [--update]
|
||||
As alternative use environment var TOOL_TO_INSTALL with a list-of-tools (separeted with spaces)
|
||||
Versions are set in ./versions file
|
||||
|
||||
This can be called by directly with an argumet or from an other script
|
||||
"
|
||||
|
||||
ORG=$(pwd)
|
||||
function _info_tools {
|
||||
local match=$1
|
||||
local info_keys
|
||||
info_keys="info version site"
|
||||
|
||||
if [ -z "$match" ] || [ "$match" == "all" ] || [ "$match" == "-" ]; then
|
||||
match="all"
|
||||
fi
|
||||
echo "$PROVIDER_TITLE"
|
||||
[ ! -r "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" ] && return
|
||||
echo "-------------------------------------------------------"
|
||||
case "$match" in
|
||||
"i" | "?" | "info")
|
||||
for key in $info_keys
|
||||
do
|
||||
echo -n "$key:"
|
||||
[ "$key" != "version" ] && echo -ne "\t"
|
||||
echo " $(grep "^$key:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$key: //g")"
|
||||
done
|
||||
;;
|
||||
"all")
|
||||
cat "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml"
|
||||
;;
|
||||
*)
|
||||
echo -e "$match:\t $(grep "^$match:" "$PROVIDERS_PATH/$PROVIDER_NAME/provisioning.yaml" | sed "s/$match: //g")"
|
||||
esac
|
||||
echo "________________________________________________________"
|
||||
}
|
||||
function _install_tools {
|
||||
local match=$1
|
||||
shift
|
||||
local options
|
||||
options="$*"
|
||||
local has_tool
|
||||
local tool_version
|
||||
|
||||
OS="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
ORG_OS=$(uname)
|
||||
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')"
|
||||
ORG_ARCH="$(uname -m)"
|
||||
|
||||
UPCTL_VERSION=${UPCLOUD_UPCTL_VERSION:-}
|
||||
if [ -n "$UPCTL_VERSION" ] && [ "$match" == "all" ] || [ "$match" == "upctl" ] ; then
|
||||
has_upctl=$(type -P upctl)
|
||||
num_version="0"
|
||||
[ -n "$has_upctl" ] && upctl_version=$(upctl version | grep "Version" | cut -f2 -d":" | sed 's/ //g') && num_version=${upctl_version//\./}
|
||||
expected_version_num=${UPCTL_VERSION//\./}
|
||||
if [ -z "$CHECK_ONLY" ] && [ "$num_version" -lt "$expected_version_num" ] ; then
|
||||
mkdir -p upctl && cd upctl &&
|
||||
#curl -fsSLO $UPCLOUD_UPCTL_SOURCE/v${tool_version}/upcloud-cli_${tool_version}_${OS}_${ORG_ARCH}.tar.gz &&
|
||||
curl -fsSLO https://github.com/UpCloudLtd/upcloud-cli/releases/download/v${UPCTL_VERSION}/upcloud-cli_${UPCTL_VERSION}_${OS}_${ORG_ARCH}.tar.gz &&
|
||||
tar -xzf "upcloud-cli_${UPCTL_VERSION}_${OS}_${ORG_ARCH}.tar.gz" &&
|
||||
sudo mv upctl /usr/local/bin &&
|
||||
cd "$ORG" && rm -rf /tmp/upct "/upcloud-cli_${UPCTL_VERSION}_${OS}_${ORG_ARCH}.tar.gz"
|
||||
printf "%s\t%s\n" "upctl" "installed $UPCTL_VERSION"
|
||||
elif [ -n "$CHECK_ONLY" ] ; then
|
||||
printf "%s\t%s\t%s\n" "upctl" "$upctl_version" "expected $UPCTL_VERSION"
|
||||
else
|
||||
printf "%s\t%s\n" "upctl" "already $UPCTL_VERSION"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
function _on_tools {
|
||||
local tools_list=$1
|
||||
[ -z "$tools_list" ] || [[ "$tools_list" == -* ]] && tools_list=${TOOL_TO_INSTALL:-all}
|
||||
case $tools_list in
|
||||
"all")
|
||||
_install_tools "all" "$@"
|
||||
;;
|
||||
"info" | "i" | "?")
|
||||
shift
|
||||
_info_tools "$@"
|
||||
;;
|
||||
*)
|
||||
for tool in $tools_list
|
||||
do
|
||||
[[ "$tool" == -* ]] && continue
|
||||
_install_tools "$tool" "${*//$tool/}"
|
||||
done
|
||||
esac
|
||||
}
|
||||
|
||||
set -o allexport
|
||||
## shellcheck disable=SC1090
|
||||
[ -n "$PROVISIONING_ENV" ] && [ -r "$PROVISIONING_ENV" ] && source "$PROVISIONING_ENV"
|
||||
[ -r "../env-provisioning" ] && source ../env-provisioning
|
||||
[ -r "env-provisioning" ] && source ./env-provisioning
|
||||
#[ -r ".env" ] && source .env set
|
||||
set +o allexport
|
||||
|
||||
export PROVISIONING=${PROVISIONING:-/usr/local/provisioning}
|
||||
|
||||
PROVIDERS_PATH=${PROVIDERS_PATH:-"$PROVISIONING/providers"}
|
||||
|
||||
PROVIDER_NAME="upcloud"
|
||||
PROVIDER_TITLE="Upcloud"
|
||||
|
||||
if [ -r "$(dirname "$0")/../versions" ] ; then
|
||||
. "$(dirname "$0")"/../versions
|
||||
elif [ -r "$(dirname "$0")/versions" ] ; then
|
||||
. "$(dirname "$0")"/versions
|
||||
fi
|
||||
[ "$1" == "-h" ] && echo "$USAGE" && shift
|
||||
[ "$1" == "check" ] && CHECK_ONLY="yes" && shift
|
||||
[ -n "$1" ] && cd /tmp && _on_tools "$@"
|
||||
[ -z "$1" ] && _on_tools "$@"
|
||||
362
providers/upcloud/nulib/upcloud/api.nu
Executable file
362
providers/upcloud/nulib/upcloud/api.nu
Executable file
|
|
@ -0,0 +1,362 @@
|
|||
#!/usr/bin/env nu
|
||||
# Info: UpCloud
|
||||
# api.nu
|
||||
|
||||
export def upcloud_api_auth [
|
||||
]: nothing -> string {
|
||||
let upcloud_auth = if (($env | get -o UPCLOUD_AUTH | default "") | is-empty) {
|
||||
let upcloud_username = ($env | get -o UPCLOUD_USERNAME | default "")
|
||||
let upcloud_password = ($env | get -o UPCLOUD_PASSWORD | default "")
|
||||
$"($upcloud_username):($upcloud_password)" | encode base64
|
||||
} else {
|
||||
($env | get -o UPCLOUD_AUTH | default "")
|
||||
}
|
||||
if $upcloud_auth == ":" or ($upcloud_auth | is-empty) {
|
||||
_print $"🛑 Not found (_ansi purple)UpCloud(_ansi reset) (_ansi red)credentials(_ansi reset)"
|
||||
return ""
|
||||
}
|
||||
$upcloud_auth
|
||||
}
|
||||
|
||||
export def upcloud_api_url [
|
||||
url_path: string
|
||||
]: nothing -> any {
|
||||
let upcloud_api_url = ($env | get -o UPCLOUD_API_URL | default "")
|
||||
if ($upcloud_api_url | is-empty) {
|
||||
_print $"🛑 Not found (_ansi purple)UpCloud(_ansi reset) (_ansi red)API URL(_ansi reset) not found"
|
||||
return ""
|
||||
}
|
||||
$"($upcloud_api_url)/($url_path)"
|
||||
}
|
||||
|
||||
export def upcloud_api_request [
|
||||
method: string
|
||||
url_path: string
|
||||
data?: any
|
||||
]: nothing -> any {
|
||||
let $upcloud_auth = (upcloud_api_auth)
|
||||
let upcloud_api_url = (upcloud_api_url $url_path)
|
||||
if ($upcloud_auth | is-empty) or ($upcloud_api_url | is-empty) { return "" }
|
||||
|
||||
# http options $"($upcloud_api_url)/($url_path)" --allow-errors --headers [Origin "https://api.upcloud.com" Access-Control-Request-Headers "Content-Type, X-Custom-Header" Access-Control-Request-Method GET, "Authorization" $" Basic ($upcloud_auth)"]
|
||||
let result = match $method {
|
||||
"post" => {
|
||||
if ($data | describe | str starts-with "record") {
|
||||
http post --content-type application/json --allow-errors --headers ["Authorization" $" Basic ($upcloud_auth)"] $upcloud_api_url $data
|
||||
} else {
|
||||
http post --allow-errors --headers ["Authorization" $" Basic ($upcloud_auth)"] $upcloud_api_url $data
|
||||
}
|
||||
},
|
||||
"put" => {
|
||||
http put --allow-errors --headers ["Authorization" $" Basic ($upcloud_auth)"] $upcloud_api_url $data
|
||||
}
|
||||
"delete" => {
|
||||
http delete --allow-errors --headers ["Authorization" $" Basic ($upcloud_auth)"] $upcloud_api_url
|
||||
}
|
||||
_ => {
|
||||
http get --allow-errors --headers ["Authorization" $" Basic ($upcloud_auth)"] $upcloud_api_url
|
||||
}
|
||||
}
|
||||
if ($result | describe) == "string" {
|
||||
if ($result | is-empty) { return "OK" }
|
||||
_print $"🛑 Error (_ansi purple)UpCloud(_ansi reset) (_ansi red)($upcloud_api_url)(_ansi reset):\n ($result)"
|
||||
return ""
|
||||
}
|
||||
let status = ($result | get -o status | default "")
|
||||
let error = ($result | get -o error | default "")
|
||||
if ($status | is-not-empty) or ($error | is-not-empty) {
|
||||
_print $"🛑 Error (_ansi purple)UpCloud(_ansi reset) (_ansi red)($upcloud_api_url)(_ansi reset)\n ($status) ($error))"
|
||||
return ""
|
||||
}
|
||||
$result
|
||||
}
|
||||
|
||||
export def upcloud_api_new_server [
|
||||
server: record
|
||||
]: nothing -> record {
|
||||
{
|
||||
hostname: "dev-wrkr",
|
||||
zone: "es-mad1",
|
||||
title: "dev-wrkr Debian server",
|
||||
labels: {
|
||||
label: [
|
||||
{
|
||||
"key": "test",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
plan: "DEV-1xCPU-1GB",
|
||||
#plan: "DEV-1xCPU-4GB",
|
||||
metadata: "yes",
|
||||
simple_backup: "0400,dailies",
|
||||
timezone: "UTC",
|
||||
storage_devices: {
|
||||
storage_device: [
|
||||
{
|
||||
action: "clone",
|
||||
labels: [
|
||||
{
|
||||
"key": "foo",
|
||||
"value": "bar"
|
||||
}
|
||||
],
|
||||
storage: "01000000-0000-4000-8000-000020070100" # Debian GNU/Linux 12 (Bookworm)
|
||||
encrypted: "no",
|
||||
title: "dev-wrkr Debian from a template",
|
||||
#size: 50,
|
||||
size: 20,
|
||||
tier: "standard"
|
||||
#tier: "maxiops"
|
||||
}
|
||||
]
|
||||
},
|
||||
networking: {
|
||||
interfaces: {
|
||||
interface: [
|
||||
{
|
||||
ip_addresses: {
|
||||
ip_address: [
|
||||
{
|
||||
family: "IPv4"
|
||||
}
|
||||
]
|
||||
},
|
||||
type: "public"
|
||||
},
|
||||
{
|
||||
ip_addresses: {
|
||||
ip_address: [
|
||||
{
|
||||
family: "IPv4"
|
||||
}
|
||||
]
|
||||
},
|
||||
type: "utility"
|
||||
},
|
||||
{
|
||||
ip_addresses: {
|
||||
ip_address: [
|
||||
{
|
||||
family: "IPv6"
|
||||
}
|
||||
]
|
||||
},
|
||||
type: "public"
|
||||
},
|
||||
{
|
||||
type: "private",
|
||||
network: "03b1115c-522b-4608-ae08-9a4d32a2d16d"
|
||||
source_ip_filtering: "yes"
|
||||
ip_addresses: {
|
||||
ip_address: [
|
||||
{
|
||||
family: "IPv4",
|
||||
address: "10.11.2.11",
|
||||
dhcp_provided: "no"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
login_user: {
|
||||
ssh_keys: {
|
||||
ssh_key: [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5GLeuDFUdLl7p72xt4nCOmCrdwP5QG1F16kIAQQlMT cdci"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def upcloud_api_list_servers [
|
||||
format?: string
|
||||
]: nothing -> list {
|
||||
let result = (upcloud_api_request "get" "server" )
|
||||
if ($result | is-empty) {
|
||||
return []
|
||||
}
|
||||
match $format {
|
||||
"main" => {
|
||||
mut servers_list = []
|
||||
for it in ($result | get -o servers | flatten) {
|
||||
let srv = ($it | get -o server )
|
||||
$servers_list = ($servers_list | append {
|
||||
state: ($srv| get -o state | default ""),
|
||||
hostname: ($srv| get -o hostname | default ""),
|
||||
uuid: ($srv| get -o uuid | default ""),
|
||||
title: ($srv| get -o title | default ""),
|
||||
plan: ($srv| get -o plan | default ""),
|
||||
zone: ($srv| get -o zone | default ""),
|
||||
memory_amount: ($srv| get -o memory_amount | default ""),
|
||||
core_number: ($srv| get -o core_number | default ""),
|
||||
simple_backup: ($srv| get -o simple_backup | default ""),
|
||||
server_group: ($srv| get -o server_group | default ""),
|
||||
})
|
||||
}
|
||||
$servers_list
|
||||
},
|
||||
_ => ($result | get -o servers | flatten)
|
||||
}
|
||||
}
|
||||
|
||||
export def upcloud_api_server_info [
|
||||
hostname: string
|
||||
]: nothing -> any {
|
||||
let servers_list = (upcloud_api_list_servers | where {|it| $it.server.hostname == $hostname })
|
||||
($servers_list | get -o 0 | get -o server | default "")
|
||||
}
|
||||
|
||||
export def upcloud_api_server_uuid [
|
||||
hostname: string
|
||||
uuid: string
|
||||
]: nothing -> string {
|
||||
if ($uuid | is-empty) {
|
||||
if ($hostname | is-empty) { return "" }
|
||||
(upcloud_api_server_info $hostname | get -o uuid | default "")
|
||||
} else { $uuid }
|
||||
}
|
||||
|
||||
export def upcloud_api_server_ip [
|
||||
server_info: record
|
||||
type: string = "public"
|
||||
family: string = "IPv4"
|
||||
]: nothing -> any {
|
||||
($server_info | get -o server | get -o networking | get -o interfaces | get -o interface
|
||||
| flatten | where {|item| $item.type == $type} | get -o ip_address
|
||||
| flatten | where {|it| $it.family == $family} | get -o address | get -o 0 | default ""
|
||||
)
|
||||
}
|
||||
export def upcloud_api_server_uuid_ip [
|
||||
uuid: string
|
||||
type: string = "public"
|
||||
family: string = "IPv4"
|
||||
]: nothing -> any {
|
||||
let result = (upcloud_api_request "get" $"server/($uuid)" )
|
||||
if ($result | is-empty) { return "" }
|
||||
(upcloud_api_server_ip $result $type $family)
|
||||
}
|
||||
export def upcloud_api_server_new_state [
|
||||
state: string
|
||||
uuid: string
|
||||
wait: int = 60
|
||||
]: nothing -> any {
|
||||
(upcloud_api_request
|
||||
"post"
|
||||
$"server/($uuid)/($state)"
|
||||
{ stop_server: { stop_type: "soft", timeout: $wait } }
|
||||
)
|
||||
}
|
||||
export def upcloud_api_server_state [
|
||||
hostname: string
|
||||
uuid: string
|
||||
]: nothing -> any {
|
||||
if ($uuid | is-not-empty) {
|
||||
(upcloud_api_request "get" $"server/($uuid)" | get -o state | default "" )
|
||||
} else if ($hostname | is-not-empty) {
|
||||
(upcloud_api_server_info $hostname | get -o state | default "")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
export def upcloud_api_server_delete [
|
||||
hostname: string
|
||||
uuid: string
|
||||
# storages Controls what to do with storages related to the deleted server. 0, 1, true, false 0
|
||||
storage: bool = true
|
||||
# backups If storages are to be deleted, controls what to do with backups related to the storages. keep, keep_latest, delete keep
|
||||
backups: string = "delete"
|
||||
]: nothing -> any {
|
||||
let server_uuid = (upcloud_api_server_uuid $hostname $uuid)
|
||||
if ($server_uuid | is-empty) {
|
||||
_print $"🛑 Error (_ansi purple)UpCloud(_ansi reset) DELETE (_ansi red)($hostname) ($uuid)(_ansi reset)"
|
||||
return
|
||||
}
|
||||
(upcloud_api_request "delete" $"server/($uuid)?storages=($storage)&backups=($backups)")
|
||||
}
|
||||
export def upcloud_api_get_info [
|
||||
hostname: string
|
||||
type: string = "public"
|
||||
family: string = "IPv4"
|
||||
]: nothing -> string {
|
||||
let server = (upcloud_api_server_info $hostname)
|
||||
if ($server | is-empty) { return "" }
|
||||
# _print ($server | table -e)
|
||||
let uuid = ($server | get -o uuid | default "")
|
||||
if ($uuid | is-empty) { return "" }
|
||||
(upcloud_api_server_uuid_ip $uuid "public" "IPv4")
|
||||
}
|
||||
export def upcloud_api_test [
|
||||
]: nothing -> string {
|
||||
let hostname = "dev-wrkr"
|
||||
|
||||
# let result = (upcloud_api_request "get" "account")
|
||||
# if ($result | is-not-empty) and ($result | get -o account | get -o credits | default "" | is-not-empty) {
|
||||
# _print $"Account '($result | get -o account | get -o username | default "")' credit: ($result | get -o account | get -o credits)"
|
||||
# }
|
||||
|
||||
let server_info = (upcloud_api_server_info $hostname)
|
||||
if ($server_info | is-not-empty) {
|
||||
_print $"🛑 Error (_ansi purple)UpCloud(_ansi reset) create (_ansi red)($hostname)(_ansi reset)"
|
||||
_print $"Server (_ansi green)($hostname)(_ansi reset) ($server_info | get -o uuid | default "") => ($server_info | get -o state | default "")"
|
||||
} else {
|
||||
_print $"Server (_ansi green)($hostname)(_ansi reset) creation ..."
|
||||
let server_data = (upcloud_api_new_server {})
|
||||
let result = (upcloud_api_request "post" "server" { server: $server_data} )
|
||||
if ($result | is-not-empty) {
|
||||
let pub_ip = (upcloud_api_server_ip $result "public" "IPv4")
|
||||
if ($pub_ip | is-not-empty) {
|
||||
_print $"ssh -i $HOME/.ssh/id_cdci -l root ($pub_ip)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#let pub_ip = (upcloud_get_info $hostname "public" "IPv4")
|
||||
|
||||
_print $"Server (_ansi green)($hostname)(_ansi reset) state: (upcloud_api_server_state $hostname "")"
|
||||
|
||||
let servers_list = (upcloud_api_list_servers "main")
|
||||
_print ($servers_list | table -i false -e)
|
||||
let server = (upcloud_api_server_info $hostname)
|
||||
if ($server | is-empty) { exit }
|
||||
# _print ($server | table -e)
|
||||
let uuid = ($server | get -o uuid | default "")
|
||||
if ($uuid | is-empty) { exit }
|
||||
let pub_ip = (upcloud_api_server_uuid_ip $uuid "public" "IPv4")
|
||||
if ($pub_ip | is-not-empty) {
|
||||
_print $"ssh -i $HOME/.ssh/id_cdci -l root ($pub_ip)"
|
||||
}
|
||||
|
||||
let server_state = (upcloud_api_server_state $hostname "")
|
||||
if $server_state == "maintenance" or $server_state == "error" {
|
||||
_print $"🛑 Server (_ansi green)($hostname)(_ansi reset) in (_ansi red)($server_state)(_ansi reset) !!! "
|
||||
exit 1
|
||||
}
|
||||
if $server_state == "started" {
|
||||
let wait = 20
|
||||
let max_wait = 240
|
||||
mut wait_time = 0
|
||||
_print $"Server (_ansi green)($hostname)(_ansi reset) state: (_ansi yellow)($server_state)(_ansi reset)"
|
||||
_print $"Server (_ansi green)($hostname | default "")(_ansi reset) ($uuid) to (_ansi yellow)stop(_ansi reset) state ... try every ($wait)sec until ($max_wait)sec"
|
||||
_print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
(upcloud_api_server_new_state "stop" $uuid 30)
|
||||
while true {
|
||||
if (upcloud_api_server_state $hostname "") == "stopped" { break }
|
||||
$wait_time = ($wait_time + $wait)
|
||||
if ($wait_time > $max_wait) {
|
||||
_print $"🛑 Server (_ansi green)($hostname)(_ansi reset) state (_ansi red)stop(_ansi reset) not found in ($max_wait)secs !!! "
|
||||
exit 1
|
||||
}
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset) [($wait_time)]"
|
||||
sleep ($"($wait)sec"| into duration)
|
||||
}
|
||||
_print ""
|
||||
}
|
||||
let result = (upcloud_api_server_delete "" $uuid)
|
||||
if $result == "OK" {
|
||||
_print $"Server (_ansi green)($hostname)(_ansi reset) DELETED "
|
||||
_print (upcloud_api_server_info $hostname)
|
||||
}
|
||||
}
|
||||
93
providers/upcloud/nulib/upcloud/cache.nu
Normal file
93
providers/upcloud/nulib/upcloud/cache.nu
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env nu
|
||||
# Info: UpCloud
|
||||
|
||||
use std
|
||||
|
||||
export def upcloud_start_cache_info [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
$""
|
||||
}
|
||||
export def upcloud_create_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
print $"❗ No settings found "
|
||||
return
|
||||
}
|
||||
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-not-empty) or ($data | get -o main) != "?" {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"UpCloud main data already exists in ($provider_path | path basename)"
|
||||
}
|
||||
}
|
||||
let result = (^upctl "server" "show" $server.hostname -o "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })| complete)
|
||||
let info_server = if $result.exit_code == 0 {
|
||||
($result.stdout | from json)
|
||||
} else { {} }
|
||||
let all_servers = if ($data.servers? == null) {
|
||||
{}
|
||||
} else if ($info_server | is-empty) {
|
||||
$data.servers
|
||||
} else {
|
||||
$data.servers | default {} | append $info_server
|
||||
}
|
||||
let new_data = ( $data | merge { servers: $all_servers})
|
||||
save_provider_env $new_data $settings $provider_path
|
||||
if $env.PROVISIONING_DEBUG { print $"Cache for ($server.provider) on ($server.hostname) saved in: ($provider_path | path basename)" }
|
||||
}
|
||||
export def upcloud_read_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
print $"❗ No settings found "
|
||||
return
|
||||
}
|
||||
}
|
||||
export def upcloud_clean_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
if $settings == null {
|
||||
print $"❗ No settings found "
|
||||
return
|
||||
}
|
||||
let provider_path = (get_provider_data_path $settings $server)
|
||||
let data = (load_provider_env $settings $server $provider_path)
|
||||
if ($data.servers? == null) { return {} }
|
||||
if ($data.servers | where {|it| ($it.hostname? | default "") == $server.hostname} | length) == 0 {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print $"❗server ($server.hostname) already deleted from ($provider_path | path basename)"
|
||||
}
|
||||
return
|
||||
}
|
||||
let all_servers = ( $data.servers? | default [] | where {|it| ($it.hostname? | is-not-empty) and ($it.hostname? | default "") != $server.hostname})
|
||||
if $env.PROVISIONING_DEBUG { print $"Cache for ($server.provider) delete ($server.hostname) in: ($provider_path | path basename)" }
|
||||
let new_data = if ($all_servers | length) == 0 {
|
||||
( $data | merge { servers: []})
|
||||
} else {
|
||||
( $data | merge { servers: $all_servers})
|
||||
}
|
||||
save_provider_env $new_data $settings $provider_path
|
||||
}
|
||||
export def upcloud_ip_from_cache [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let data = ($settings.providers | find $server.provider | get -o settings | get -o servers | flatten
|
||||
| find $server.hostname | select -o ip_addresses)
|
||||
mut pub_ip = ""
|
||||
for it in $data {
|
||||
$pub_ip = ($it | get -o ip_addresses | find "public" | get -o address | get -o 0)
|
||||
}
|
||||
$pub_ip
|
||||
}
|
||||
6
providers/upcloud/nulib/upcloud/env.nu
Normal file
6
providers/upcloud/nulib/upcloud/env.nu
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export-env {
|
||||
$env.UPCLOUD_API_URL = ($env | get -o UPCLOUD_API_URL | default "https://api.upcloud.com/1.3")
|
||||
$env.UPCLOUD_AUTH = ($env | get -o UPCLOUD_AUTH | default "")
|
||||
$env.UPCLOUD_INTERFACE = ($env | get -o UPCLOUD_INTERFACE | default "CLI") # API or CLI
|
||||
#$env.UPCLOUD_INTERFACE = ($env | get -o UPCLOUD_INTERFACE | default "API") # API or CLI
|
||||
}
|
||||
13
providers/upcloud/nulib/upcloud/list_nu_curl_defs.txt
Normal file
13
providers/upcloud/nulib/upcloud/list_nu_curl_defs.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
upcloud_api_auth
|
||||
upcloud_api_url
|
||||
upcloud_api_request
|
||||
upcloud_api_new_server
|
||||
upcloud_api_list_servers
|
||||
upcloud_api_server_info
|
||||
upcloud_api_server_uuid
|
||||
upcloud_api_server_ip
|
||||
upcloud_api_server_uuid_ip
|
||||
upcloud_api_server_new_state
|
||||
upcloud_api_server_state
|
||||
upcloud_api_server_delete
|
||||
upcloud_api_get_info
|
||||
6
providers/upcloud/nulib/upcloud/mod.nu
Normal file
6
providers/upcloud/nulib/upcloud/mod.nu
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use env.nu
|
||||
export use servers.nu *
|
||||
export use cache.nu *
|
||||
export use usage.nu *
|
||||
export use utils.nu *
|
||||
export use prices.nu *
|
||||
304
providers/upcloud/nulib/upcloud/prices.nu
Normal file
304
providers/upcloud/nulib/upcloud/prices.nu
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
export def upcloud_sel_data_table [
|
||||
data: any
|
||||
id: string
|
||||
] {
|
||||
($data | where {|it| $it.id == $id } | get -o table | get -o 0)
|
||||
}
|
||||
|
||||
export def upcloud_get_plan_prefix [
|
||||
id: string
|
||||
] {
|
||||
match $id {
|
||||
"general-purpose" | "general" => "",
|
||||
"developer-plans" | "dev" => "DEV-",
|
||||
"high-cpu-plans" | "high-cpu" | "cpu" => "HICPU-",
|
||||
"high-memory-plans" | "high-memory" | "memory" | "ram" => "HIMEM-",
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
export def upcloud_get_id_from_plan [
|
||||
plan: string
|
||||
] {
|
||||
if ($plan | str starts-with "HICPU-") {
|
||||
"high-cpu-plans"
|
||||
} else if ($plan | str starts-with "HIMEM-") {
|
||||
"high-memory-plans"
|
||||
} else if ($plan | str starts-with "DEV-") {
|
||||
"developer-plans"
|
||||
} else {
|
||||
"general-purpose"
|
||||
}
|
||||
}
|
||||
export def upcloud_sel_table_item [
|
||||
data: list
|
||||
key: string
|
||||
condition: string
|
||||
value: string
|
||||
] {
|
||||
($data | where {|it|
|
||||
let item_data = match $key {
|
||||
"memory" | "ram" => ($it | get $key | get 0 | str replace "GB" "" | str trim),
|
||||
_ => ($it | get $key | get 0 ),
|
||||
}
|
||||
(match $condition {
|
||||
"lt" | "<" => (($item_data | into int ) < ($value | str replace "GB" "" | into int)),
|
||||
"lte" | "<=" => (($item_data | into int ) <= ($value | str replace "GB" "" | into int)),
|
||||
_ => false
|
||||
})
|
||||
}| flatten)
|
||||
}
|
||||
export def upcloud_get_price [
|
||||
all_data: record
|
||||
key: string
|
||||
price_col: string = "global_price"
|
||||
] {
|
||||
let data = ($all_data | get -o item)
|
||||
let str_price_col = if ($price_col | is-empty) { "global_price" } else { $price_col }
|
||||
match ($all_data | get -o target) {
|
||||
"server" => {
|
||||
let table_key = if $key == "unit" { "hour" } else { $key }
|
||||
let value = ($data | get -o $str_price_col | flatten | get -o $table_key | default "" | str replace -a "€" "" )
|
||||
if $key == "unit" {
|
||||
$"($value | get -o 0) Hrs"
|
||||
} else if ($value | is-not-empty) {
|
||||
($value | get -o 0 | into float)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
},
|
||||
"storage" => {
|
||||
# Index 0 should be part of the server PLAN
|
||||
let it = ($all_data | get -o src )
|
||||
if ($it | is-empty) or ($it | get -o item | is-empty) { return 0 }
|
||||
if ($it.index) == 0 { return 0 }
|
||||
let storage = $it.item
|
||||
let storage_type = match ($storage | get -o voltype) {
|
||||
"maxiops" => "MaxIOPS",
|
||||
"hdd" => "HDD",
|
||||
"custom" => "Custom image",
|
||||
}
|
||||
let month = ($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "" | into float)
|
||||
let hour = ($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float)
|
||||
match $key {
|
||||
"unit" =>
|
||||
$"($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "") GB-Mo",
|
||||
"month" =>
|
||||
($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "" | into float),
|
||||
"day" =>
|
||||
(($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float) * 24),
|
||||
"hour" =>
|
||||
($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float),
|
||||
_ => 0,
|
||||
}
|
||||
},
|
||||
"networking" => {
|
||||
0
|
||||
},
|
||||
"backups" => {
|
||||
0
|
||||
},
|
||||
_ => {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_get_item_for_storage [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
] {
|
||||
let data = ($cloud_data | get -o $server.provider| get -o "block_storage")
|
||||
if ($data | is-empty) { return {} }
|
||||
($data | get -o table | get -o 0)
|
||||
}
|
||||
export def upcloud_get_item_for_server [
|
||||
server: record
|
||||
settings: record
|
||||
cloud_data: record
|
||||
] {
|
||||
let data = ($cloud_data | get -o $server.provider | get -o "servers")
|
||||
if ($data | is-empty) { return {} }
|
||||
let plan = ($server | get -o plan | default "")
|
||||
let key_id = (upcloud_get_id_from_plan $plan)
|
||||
let cloud_table_data = (upcloud_sel_data_table $data $key_id)
|
||||
if ($cloud_table_data | is-empty) { return {} }
|
||||
($cloud_table_data | where {|it|
|
||||
($it | get -o plan ) == $plan
|
||||
} | get -o 0)
|
||||
}
|
||||
export def upcloud_clean_table [
|
||||
id: string
|
||||
data: string
|
||||
target: string
|
||||
] {
|
||||
let table = ( $data | split row "<tr>" | where {|it| $it | str starts-with "<" } |
|
||||
each {|it| $it | str replace -a -r "<(\/td|sup|\/sup|small|\/small|b|\/b|br|\/tr|tbody|\/tbody|\/thead|\/th)>" "" }
|
||||
)
|
||||
let table_cols = if ($table | get 0 | str contains "<th>") {
|
||||
($table | get 0 | split row "<th>")
|
||||
} else {
|
||||
($table | get 0 | split row "<td>")
|
||||
}
|
||||
let cols = ($table_cols | where {|it| $it != "" } | str replace " *" " " |
|
||||
str trim | str downcase | str replace " " "_" | str replace 'price*' 'price')
|
||||
let plan_prefix = (upcloud_get_plan_prefix $id)
|
||||
let res = ( $table | drop nth 0 | each {|line| $line | split column "<td>" -c ...$cols } |
|
||||
each {|it|
|
||||
#if $target == "networking" => { print $it }
|
||||
match $target {
|
||||
"block-storage" => {
|
||||
$it |
|
||||
update storage_type $"($it | get -o 'storage_type' | get -o 0 )" |
|
||||
update global_price ($it| get -o global_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
|
||||
update helsinki_price ($it| get -o helsinki_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0)
|
||||
},
|
||||
"object-storage" => {
|
||||
$it |
|
||||
update price ($it| get -o price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
|
||||
},
|
||||
"cloud-servers" | "servers" => {
|
||||
let helsinki_price = ($it| get -o helsinki_price | get -o 0 | default "")
|
||||
if ($helsinki_price | is-not-empty) {
|
||||
$it | insert plan $"($plan_prefix)($it | get -o 'cpu_cores' | get -o 0 )xCPU-($it | get -o 'memory' | get -o 0 | str replace ' ' '')" |
|
||||
update global_price ($it| get -o global_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
|
||||
update helsinki_price ($it| get -o helsinki_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0)
|
||||
} else {
|
||||
$it | insert plan $"($plan_prefix)($it | get -o 'cpu_cores' | get -o 0 )xCPU-($it | get -o 'memory' | get -o 0 | str replace ' ' '')" |
|
||||
update global_price ($it| get -o global_price | get -o 0 | default "" | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
|
||||
}
|
||||
},
|
||||
"simple-backups" => {
|
||||
$it | update global_price ($it| get -o global_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0) |
|
||||
update helsinki_price ($it| get -o helsinki_price | get -o 0 | parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h" | get -o 0)
|
||||
},
|
||||
"networking" => {
|
||||
$it | update price ($it| get -o price | get -o 0 | str replace "Price" "---" | str replace " " " " |
|
||||
parse --regex "(?<month>.*?)/mo (?<hour>.*?)/h|(?<price>.*)" | get -o 0)
|
||||
},
|
||||
_ => { $it },
|
||||
}
|
||||
})
|
||||
($res | flatten)
|
||||
}
|
||||
export def upcloud_get_provider_path [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let data_path = if ($settings.data.prov_data_dirpath | str starts-with "." ) {
|
||||
($settings.src_path | path join $settings.data.prov_data_dirpath)
|
||||
} else { $settings.data.prov_data_dirpath }
|
||||
if not ($data_path | path exists) { mkdir $data_path }
|
||||
($data_path | path join $"($server.provider)_prices.($env.PROVISIONING_WK_FORMAT)")
|
||||
}
|
||||
export def upcloud_load_infra_storages_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let data = (upcloud_load_infra_servers_info $settings $server $error_exit)
|
||||
let res = ($data | get -o "block-storage")
|
||||
print ($res | table -e)
|
||||
$res
|
||||
}
|
||||
export def upcloud_load_infra_servers_info [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
]: nothing -> record {
|
||||
let provider_prices_path = (upcloud_get_provider_path $settings $server)
|
||||
let data = if ($provider_prices_path | path exists) {
|
||||
open $provider_prices_path
|
||||
} else {
|
||||
let url = "https://upcloud.com/pricing"
|
||||
let pricing_html_path = ($env.PROVISIONING_PROVIDERS_PATH | path join "upcloud" | path join "pricing.html")
|
||||
{ servers: (upcloud_load_infra $url $pricing_html_path "cloud-servers"),
|
||||
block_storage: (upcloud_load_infra $url $pricing_html_path "block-storage"),
|
||||
object_storage: (upcloud_load_infra $url $pricing_html_path "object-storage"),
|
||||
backups: (upcloud_load_infra $url $pricing_html_path "simple-backups"),
|
||||
networking: (upcloud_load_infra $url $pricing_html_path "networking"),
|
||||
}
|
||||
}
|
||||
if ($provider_prices_path | path exists) { return $data }
|
||||
if $env.PROVISIONING_WK_FORMAT == "json" {
|
||||
$data | to json | save -f $provider_prices_path
|
||||
} else {
|
||||
$data | to yaml | save -f $provider_prices_path
|
||||
}
|
||||
if $env.PROVISIONING_DEBUG { print $"Price for ($server.provider) in: ($provider_prices_path | path basename)" }
|
||||
$data
|
||||
}
|
||||
export def upcloud_load_infra [
|
||||
url: string
|
||||
html_path: string
|
||||
target: string = "servers"
|
||||
]: nothing -> list {
|
||||
let id_target = match $target {
|
||||
"object" | "object-storage" | "os" => "object-storage",
|
||||
"block" | "block-storage" | "bs" => "block-storage",
|
||||
"server" | "servers" | "s" => "cloud-servers",
|
||||
"backup" | "simple-backups" | "s" => "simple-backups",
|
||||
"network" | "networking" | "s" => "networking",
|
||||
_ => "cloud-servers",
|
||||
}
|
||||
# cookie error if use curl o http get
|
||||
let html_content = if ($html_path | path exists) {
|
||||
open -r $html_path
|
||||
} else {
|
||||
#let res = (http get $url -r )
|
||||
let res = (^curl -s $url | complete)
|
||||
if ($res.exit_code != 0) {
|
||||
print $"🛑 Error (_ansi red)($url)(_ansi reset):\n ($res.exit_code) ($res.stderr)"
|
||||
return ""
|
||||
} else { $res.stdout }
|
||||
}
|
||||
($html_content | split row "<section "| find $'id="($id_target)"' | split row role="tabpanel" | find "<table" | each {|it|
|
||||
let id = ($it | parse --regex 'id="(?<id>.*?)"' | get id | get -o 0 | str replace -r "-tab$" "")
|
||||
let title = ($it | parse --regex '<h3>(?<title>.*?)<\/h3>' | get title | get -o 0)
|
||||
let info = ($it | parse --regex '<\/h3><p>(?<info>.*?)<\/p>' | get info | get -o 0)
|
||||
let table = ($it | parse --regex '<table\s*(?<table>.*?)<\/table>' | get table | get -o 0)
|
||||
{ id: $id, table: (upcloud_clean_table $id $table $id_target), title: $title, info: $info }
|
||||
})
|
||||
# mut $group_data = {}
|
||||
# for item in $data {
|
||||
# print $item
|
||||
# let group = ($item | get -o id)
|
||||
# let table = ($item | get -o table)
|
||||
# print $group
|
||||
# print ($table | flatten | table -e)
|
||||
# if ($group | is-empty) { continue }
|
||||
# # if ($group_data | get -o $group | is-empty) {
|
||||
# # $group_data = ($group_data | merge { $group: [($item | reject id)]})
|
||||
# # } else {
|
||||
# # $group_data = ($group_data | merge { $group: ($group_data | get -o $group | append ($item | reject id))})
|
||||
# # }
|
||||
# }
|
||||
# exit
|
||||
# $group_data
|
||||
# each { |it| $it | parse --regex 'id="(?<id>.*?)"(?<other>.*)<h3>(?<title>.*)<\/h3><p>(?<info>.*)</p>(?.*)<table\s*(?<table>.*)<\/table>' }
|
||||
# where {|it| $it | str starts-with "<" } |
|
||||
#print ($cloud_servers | each {|it| select id table} | flatten | each {|it|
|
||||
#let res = ($cloud_servers | each {|it| select id table} | flatten | each {|it|
|
||||
# let id = ($it.id | str replace -r "-tab$" "")
|
||||
# { id: $id, table: (upcloud_clean_table $id $it.table) }
|
||||
# }
|
||||
#)
|
||||
}
|
||||
export def upcloud_test_infra_servers [
|
||||
] {
|
||||
let data_infra_servers = (upcloud_load_infra_servers "https://upcloud.com/pricing")
|
||||
let key_id = ($data_infra_servers | get id | input list "Select server group ")
|
||||
let cloud_data = (upcloud_sel_data_table $data_infra_servers $key_id)
|
||||
let mem_limit = (["4 GB" "8 GB" "16 GB" "32 GB" "64 GB" "96 GB" "128 GB" "256 GB" "512 GB" ] | input list "Select MEMORY limit ")
|
||||
|
||||
let items = (upcloud_sel_table_item $cloud_data "memory" "lte" $mem_limit)
|
||||
print ($items | table -e)
|
||||
#let line = ($cloud_servers | get 0 | get table | get 1 )
|
||||
print $"From ($key_id) with ($mem_limit)\n"
|
||||
print $"memory | cores | month | hour | plan "
|
||||
print "============================================="
|
||||
for line in $items {
|
||||
print ($"($line | get memory) \t| ($line | get cpu_cores) \t| (upcloud_get_price $line 'month')" +
|
||||
$" \t| (upcloud_get_price $line 'hour') | ($line | get plan) "
|
||||
)
|
||||
}
|
||||
}
|
||||
829
providers/upcloud/nulib/upcloud/servers.nu
Normal file
829
providers/upcloud/nulib/upcloud/servers.nu
Normal file
|
|
@ -0,0 +1,829 @@
|
|||
#!/usr/bin/env nu
|
||||
# Info: UpCloud
|
||||
# servers.nu
|
||||
|
||||
use std
|
||||
use api.nu *
|
||||
|
||||
export def upcloud_interface [
|
||||
]: nothing -> string {
|
||||
($env | get -o UPCLOUD_INTERFACE | default "CLI") # API or CLI
|
||||
}
|
||||
export def upcloud_use_api [
|
||||
]: nothing -> bool {
|
||||
(upcloud_interface) == "API"
|
||||
}
|
||||
export def upcloud_query_servers [
|
||||
find: string
|
||||
cols: string
|
||||
]: nothing -> list {
|
||||
if upcloud_use_api {
|
||||
upcloud_api_list_servers
|
||||
} else {
|
||||
let res = (^upctl server list -o json err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code == 0 {
|
||||
$res.stdout | from json | get servers
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
(throw-error "🛑 upctl server list " $"($res.exit_code) ($res.stdout)" "upcloud query server" --span (metadata $res).span)
|
||||
} else {
|
||||
print $"🛑 Error upctl server list: ($res.exit_code) ($res.stdout | ^grep 'error')"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_server_info [
|
||||
server: record
|
||||
check: bool
|
||||
]: nothing -> record {
|
||||
let hostname = $server.hostname
|
||||
if (upcloud_use_api) {
|
||||
upcloud_api_server_info $hostname
|
||||
} else {
|
||||
let res = (^upctl server show $hostname -o json err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code == 0 {
|
||||
$res.stdout | from json
|
||||
} else if $check {
|
||||
{}
|
||||
} else {
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
(throw-error "🛑 upctl server show" $"($res.exit_code) ($res.stdout)" $"upcloud server info ($hostname)" --span (metadata $res).span)
|
||||
} else {
|
||||
print $"🛑 upctl server show ($hostname):($res.stdout | ^grep 'error')"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_on_prov_server [
|
||||
server?: record
|
||||
] {
|
||||
#let info = if ( $env.CURRENT_FILE? | into string ) != "" { (^grep "^# Info:" $env.CURRENT_FILE ) | str replace "# Info: " "" } else { "" }
|
||||
#$"From (_ansi purple_bold)UpCloud(_ansi reset)"
|
||||
}
|
||||
# infrastructure and services
|
||||
export def upcloud [
|
||||
args: list<string> # Args for create command
|
||||
--server(-s): record
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--infra (-i): string # Infra path
|
||||
--settings (-s): string # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--debug (-x) # Use Debug mode
|
||||
]: nothing -> any {
|
||||
if $debug { $env.PROVISIONING_DEBUG = true }
|
||||
let target = ($args | get -o 0 | default "")
|
||||
let task = ($args | get -o 1 | default "")
|
||||
let cmd_args = if ($args | length) > 1 { ($args | drop nth ..1) } else { [] }
|
||||
match ($task) {
|
||||
"help" | "h" => {
|
||||
print "TODO upcloud help"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
},
|
||||
_ => {
|
||||
if ($args | find "help" | length) > 0 {
|
||||
match $task {
|
||||
"server" => {
|
||||
print "SERVER "
|
||||
upcloud_server ($args | drop nth ..0)
|
||||
},
|
||||
"inventory" => {
|
||||
upcloud_server ($args | drop nth ..0)
|
||||
},
|
||||
"ssh" => {
|
||||
upcloud_server ($args | drop nth ..0)
|
||||
},
|
||||
"delete" => {
|
||||
upcloud_server ($args | drop nth ..0)
|
||||
# ($args | drop nth ..1) --server $server
|
||||
},
|
||||
_ => {
|
||||
option_undefined "upcloud" ""
|
||||
print "TODO upcloud help"
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
#use utils/settings.nu [ load_settings ]
|
||||
let curr_settings = if $infra != null {
|
||||
if $settings != null {
|
||||
(load_settings --infra $infra --settings $settings)
|
||||
} else {
|
||||
(load_settings --infra $infra)
|
||||
}
|
||||
} else {
|
||||
if $settings != null {
|
||||
(load_settings --settings $settings)
|
||||
} else {
|
||||
(load_settings)
|
||||
}
|
||||
}
|
||||
match ($task) {
|
||||
"get_ip" => {
|
||||
upcloud_get_ip $curr_settings $server ($cmd_args | get -o 0 | default "")
|
||||
},
|
||||
"server" => {
|
||||
print (
|
||||
upcloud_server $cmd_args --server $server --settings $curr_settings --error_exit
|
||||
)
|
||||
},
|
||||
"inventory" => {
|
||||
},
|
||||
"ssh" => {
|
||||
},
|
||||
"delete" => {
|
||||
# ($args | drop nth ..1) --server $server
|
||||
},
|
||||
_ => {
|
||||
option_undefined "upcloud" ""
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_get_ip [
|
||||
settings: record
|
||||
server: record
|
||||
ip_type?: string = "public"
|
||||
family?: string = "IPv4"
|
||||
]: nothing -> string {
|
||||
match $ip_type {
|
||||
"private" | "prv" | "priv" => {
|
||||
$"($server.network_private_ip)"
|
||||
},
|
||||
_ => {
|
||||
if (upcloud_use_api) {
|
||||
let server = (upcloud_api_server_info $server.hostname)
|
||||
if ($server | is-empty) { return "" }
|
||||
let uuid = ($server | get -o uuid | default "")
|
||||
if ($uuid | is-empty) { return "" }
|
||||
(upcloud_api_server_uuid_ip $uuid $ip_type $family)
|
||||
} else {
|
||||
let result = (^upctl "server" "show" $server.hostname "-o" "json" | complete)
|
||||
if $result.exit_code == 0 {
|
||||
let data = ($result.stdout | from json)
|
||||
#let id = ($data.id? | default "")
|
||||
let ip_addresses = ($data.networking?.interfaces? | where {|it| ($it.type | str contains "public") }).ip_addresses?
|
||||
$"(($ip_addresses | get -o 0).address? | get -o 0 | default '')"
|
||||
} else { "" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# To create infrastructure and services
|
||||
export def upcloud_server [
|
||||
args: list<string> # Args for create command
|
||||
--server: record
|
||||
--error_exit
|
||||
--status
|
||||
--serverpos (-p): int # Server position in settings
|
||||
--check (-c) # Only check mode no servers will be created
|
||||
--wait (-w) # Wait servers to be created
|
||||
--infra (-i): string # Infra path
|
||||
--settings (-s): record # Settings path
|
||||
--outfile (-o): string # Output file
|
||||
--debug (-x) # Use Debug mode
|
||||
]: nothing -> nothing {
|
||||
let task = ($args | get -o 0)
|
||||
let target = if ($args | length) > 1 { ($args | get -o 1) } else { "" }
|
||||
let cmd_args = if ($args | length) > 1 { ($args | drop nth ..1) } else { [] }
|
||||
match ($task) {
|
||||
"help" | "h" | "" => {
|
||||
print "TODO upcloud server help"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
},
|
||||
_ => {
|
||||
if $target == "" or ($args | find "help" | length) > 0 {
|
||||
match $task {
|
||||
"server" => {
|
||||
upcloud_server $cmd_args
|
||||
},
|
||||
"status" => {
|
||||
print $server
|
||||
print $error_exit
|
||||
}
|
||||
"inventory" => {
|
||||
print "TODO upcloud server inventory help"
|
||||
},
|
||||
"ssh" => {
|
||||
print "TODO upcloud server ssh help"
|
||||
},
|
||||
"delete" => {
|
||||
# ($args | drop nth ..1) --server $server
|
||||
#upcloud_delete_server $cmd_args true
|
||||
},
|
||||
_ => {
|
||||
option_undefined "upcloud" "server"
|
||||
print "TODO upcloud server help"
|
||||
}
|
||||
}
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
let server_target = if $server != null {
|
||||
$server
|
||||
} else if $settings != null {
|
||||
($settings.data.servers | where {|it| $it.hostname == $target } | get -o 0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if $server_target == null {
|
||||
if $error_exit {
|
||||
let text = $"($args | str join ' ')"
|
||||
(throw-error "🛑 upcloud server" $text "" --span (metadata $server_target).span)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
if $status or $task == "status" {
|
||||
print "upcloud server status "
|
||||
return true
|
||||
}
|
||||
match $task {
|
||||
"get_ip" => {
|
||||
upcloud_get_ip $settings $server_target ($cmd_args | get -o 0 | default "")
|
||||
},
|
||||
"stop" => {
|
||||
print "TODO upcloud server stop"
|
||||
},
|
||||
"start" => {
|
||||
print "TODO upcloud server start"
|
||||
},
|
||||
"restart" => {
|
||||
print "TODO upcloud server restart"
|
||||
},
|
||||
_ => {
|
||||
option_undefined "upcloud" "server"
|
||||
if not $env.PROVISIONING_DEBUG { end_run "" }
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_create_private_network [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
if $server == null {
|
||||
print $"❗ No server found in settings "
|
||||
return ""
|
||||
}
|
||||
# new_upctl network list -o json |
|
||||
# let net_id = ($data.networks | get -o 0 ).uuid)
|
||||
let zone = ( $server.zone? | default "")
|
||||
if $zone == "" {
|
||||
print $"($server.hostname) No zone found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
let network_private_name = ($server.network_private_name? | default "")
|
||||
if $network_private_name == "" {
|
||||
print $"($server.hostname) No network_private_name found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
let priv_cidr_block = ($server.priv_cidr_block | default "")
|
||||
if $network_private_name == "" {
|
||||
print $"($server.hostname) No priv_cidr_block found to CREATE network_privat_id"
|
||||
return ""
|
||||
}
|
||||
|
||||
let private_net_id = if (upcloud_use_api) {
|
||||
# TODO make it via API
|
||||
""
|
||||
} else {
|
||||
# EXAMPLE_BASH private_net_id=$(upctl network list -o yaml | $YQ '.networks[] | select(.ip_networks.ip_network[].address == "'"$priv_cidr_block"'") | .uuid' 2>/dev/null | sed 's,",,g')
|
||||
let result = (^upctl network list -o json | complete)
|
||||
if $result.exit_code == 0 {
|
||||
let data = ($result.stdout | from json | get -o networks | find $priv_cidr_block | get -o 0 | get -o uuid | default "" | str trim)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
if $check and ($private_net_id | is-empty) {
|
||||
print $"❗private_network will be register in a real creation request not in check state"
|
||||
return ""
|
||||
} else {
|
||||
let result = (^upctl network create --name ($network_private_name) --zone $zone --ip-network $"address=($priv_cidr_block),dhcp=true" -o json | complete)
|
||||
let new_net_id = if $result.exit_code == 0 {
|
||||
($result.stdout | from json | find $priv_cidr_block | get -o uuid | default "")
|
||||
} else { "" }
|
||||
if ($new_net_id | is-empty) {
|
||||
(throw-error $"🛑 no private network '($network_private_name)' created"
|
||||
$"for server ($server.hostname) ip ($server.network_private_ip)\n($result.stdout)"
|
||||
$"upcloud_create_private_network" --span (metadata $new_net_id).span)
|
||||
exit
|
||||
}
|
||||
# Save changes ...
|
||||
#use utils/settings.nu [ save_servers_settings save_settings_file ]
|
||||
let match_text = " network_private_id = "
|
||||
let default_provider_path = ($settings.data | get -o servers_paths | get -o 0 | default "" | path dirname | path join $"($server.provider)_defaults.k")
|
||||
let old_text = 'network_private_id = "CREATE"'
|
||||
let new_text = $'network_private_id = "($new_net_id)"'
|
||||
save_settings_file $settings $default_provider_path $old_text $new_text
|
||||
return $new_net_id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
export def upcloud_check_server_requirements [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
if $server.provider == "upcloud" {
|
||||
if (^upctl account show "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete).exit_code != 0 and $check {
|
||||
(throw-error $"🛑 no account found"
|
||||
$"for server ($server.hostname)"
|
||||
"upcloud_check_server_requirements" --span (metadata $server.provider).span)
|
||||
exit
|
||||
}
|
||||
let private_net_id = if ($server.network_private_id? | default "") == "CREATE" {
|
||||
print $"❗($server.network_private_id?) found for (_ansi yellow)network_private_id(_ansi reset) will be created for ($server.priv_cidr_block | default '')"
|
||||
(upcloud_create_private_network $settings $server $check)
|
||||
} else {
|
||||
($server.network_private_id? | default "" )
|
||||
}
|
||||
if ($private_net_id | is-empty) and $check {
|
||||
return true
|
||||
}
|
||||
let result = (^upctl network show $private_net_id -o json | complete)
|
||||
let privavet_net_id = if (not $check) and $result.exit_code != 0 {
|
||||
let net_id = (upcloud_create_private_network $settings $server $check)
|
||||
let res = (^upctl "network" "show" $private_net_id "-o" "json" | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗Error: no ($private_net_id) found "
|
||||
" "
|
||||
} else {
|
||||
let data = ($result.stdout | from json )
|
||||
($data.networks | get -o 0 | get -o uuid)
|
||||
}
|
||||
} else if $result.exit_code == 0 {
|
||||
let data = ($result.stdout | from json)
|
||||
($data.uuid)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
let server_private_ip = ($server.network_private_ip? | default "")
|
||||
if $private_net_id == "" and $server_private_ip != "" {
|
||||
(throw-error $"🛑 no private network ($private_net_id) found"
|
||||
$"for server ($server.hostname) ip ($server_private_ip)"
|
||||
"upcloud_check_requirements" --span (metadata $server_private_ip).span)
|
||||
exit
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def upcloud_make_settings [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
let out_settings_path = $"($settings.infra_fullpath)/($server.provider)_settings.yaml"
|
||||
let data = if ($out_settings_path | path exists ) {
|
||||
(open $out_settings_path | from yaml)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
let task = if $data != null { "update" } else { "create" }
|
||||
|
||||
let uuid = (^upctl server show $server.hostname "-o" "json" | from json).uuid? | default ""
|
||||
if $uuid == "" {
|
||||
return false
|
||||
}
|
||||
let ip_pub = (upcloud_get_ip $settings $server "public")
|
||||
let ip_priv = (upcloud_get_ip $settings $server "private")
|
||||
|
||||
let server_settings = {
|
||||
name: $server.hostname,
|
||||
id: $uuid,
|
||||
private_net: {
|
||||
id: $server.network_private_id
|
||||
name: $server.network_private_name
|
||||
},
|
||||
zone: $server.zone,
|
||||
datetime: $env.NOW,
|
||||
ip_addresses: {
|
||||
pub: $ip_pub, priv: $ip_priv
|
||||
}
|
||||
}
|
||||
let new_data = if $data != null and $data.servers? != null {
|
||||
( $data.servers | each { |srv|
|
||||
where {|it| $it.name != $server.hostname }
|
||||
}) | append $server_settings
|
||||
} else {
|
||||
{
|
||||
servers: [ $server_settings ]
|
||||
}
|
||||
}
|
||||
$new_data | to yaml | save --force $out_settings_path
|
||||
print $"✅ upcloud settings ($task) -> ($out_settings_path)"
|
||||
true
|
||||
}
|
||||
export def upcloud_delete_settings [
|
||||
settings: record
|
||||
server: record
|
||||
] {
|
||||
}
|
||||
export def upcloud_post_create_server [
|
||||
settings: record
|
||||
server: record
|
||||
check: bool
|
||||
] {
|
||||
mut req_storage = ""
|
||||
for storage in ($server | get -o storages | enumerate) {
|
||||
let res = (upcloud_storage_fix_size $settings $server $storage.index)
|
||||
if ($req_storage | is-empty) and ($res | is-not-empty) {
|
||||
$req_storage = $res
|
||||
}
|
||||
}
|
||||
$req_storage
|
||||
}
|
||||
export def upcloud_modify_server [
|
||||
settings: record
|
||||
server: record
|
||||
new_values: list
|
||||
error_exit: bool
|
||||
] {
|
||||
mut args = ""
|
||||
for item in $new_values {
|
||||
if ($item | get -o plan | is-not-empty) { $args = $args + $" --plan ($item.plan)" }
|
||||
}
|
||||
if ($args | is-empty) { return }
|
||||
print $"Stop (_ansi blue_bold)($server.hostname)(_ansi reset) to modify (_ansi yellow_bold)($args)(_ansi reset)"
|
||||
if (upcloud_change_server_state $settings $server "stop" "") == false {
|
||||
print $"❗ Stop ($server.hostname) errors "
|
||||
if $error_exit {
|
||||
exit 1
|
||||
} else {
|
||||
return "error"
|
||||
}
|
||||
}
|
||||
let res = (^upctl ...($"server modify ($server.hostname) ($args | str trim)" | split row " ") err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Server ($server.hostname) modify ($args) errors ($res.stdout ) "
|
||||
}
|
||||
print $"Start (_ansi blue_bold)($server.hostname)(_ansi reset) with modifications (_ansi green_bold)($args)(_ansi reset) ... "
|
||||
if (upcloud_change_server_state $settings $server "start" "") == false {
|
||||
print $"❗ Errors to start ($server.hostname)"
|
||||
if $error_exit {
|
||||
exit 1
|
||||
} else {
|
||||
return "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
export def upcloud_wait_storage [
|
||||
settings: record
|
||||
server: record
|
||||
new_state: string
|
||||
id: string
|
||||
] {
|
||||
print $"Checking storage ($id) state for (_ansi blue_bold)($server.hostname)(_ansi reset) state (_ansi yellow_bold)($new_state)(_ansi reset) ..."
|
||||
let state = (^upctl storage show $id -o json e> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | from json | get -o state)
|
||||
if ($state | str contains $new_state) { return true }
|
||||
let val_timeout = if $server.running_timeout? != null { $server.running_timeout } else { 60 }
|
||||
let wait = if $server.running_wait? != null { $server.running_wait } else { 10 }
|
||||
let wait_duration = ($"($wait)sec"| into duration)
|
||||
mut num = 0
|
||||
while true {
|
||||
let status = (^upctl storage show $id -o json e> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | from json | get -o state)
|
||||
if ($status | str contains $new_state) {
|
||||
return true
|
||||
} else if $val_timeout > 0 and $num > $val_timeout {
|
||||
print ($"\n🛑 (_ansi red)Timeout(_ansi reset) ($val_timeout) volume ($id) state for (_ansi blue)($server.hostname)(_ansi reset) " +
|
||||
$"(_ansi blue_bold)($new_state)(_ansi reset) (_ansi red_bold)failed(_ansi reset) "
|
||||
)
|
||||
return false
|
||||
} else {
|
||||
$num = $num + $wait
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print ($"(_ansi blue_bold) 🌥 (_ansi reset) storage state for (_ansi yellow)($id)(_ansi reset) " +
|
||||
$"for (_ansi green)($server.hostname)(_ansi reset)-> ($status | str trim) "
|
||||
)
|
||||
} else {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
}
|
||||
sleep $wait_duration
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
export def upcloud_create_storage [
|
||||
settings: record
|
||||
server: record
|
||||
server_info: record
|
||||
storage: record
|
||||
volumes: list
|
||||
total_size: int
|
||||
] {
|
||||
if $total_size <= 0 {
|
||||
print $"❗Create storage for ($server.hostname) size (_ansi red)($total_size) error(_ansi reset)"
|
||||
return {}
|
||||
}
|
||||
let av_zone = ($storage.item | get -o zone | default ($server | get -o zone))
|
||||
if ($av_zone | is-empty) {
|
||||
print ($"❗Create storage for (_ansi green_bold)($server.hostname)(_ansi reset) " +
|
||||
$"(_ansi cyan_bold)($total_size)(_ansi reset) (_ansi red)Zone error(_ansi reset)"
|
||||
)
|
||||
return {}
|
||||
}
|
||||
let vol_device = ($storage.item | get -o voldevice)
|
||||
let op_vol_device = if ($vol_device | is-not-empty) {
|
||||
$"--address ($vol_device)"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
let op_encrypted = if ($storage.item | get -o encrypted | default false) {
|
||||
"--encrypted"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
let $op_backup = if ($storage.item | get -o backup | is-not-empty) {
|
||||
( $" --backup-time ($storage.item | get -o backup | get -o time) " +
|
||||
$" --backup-interval ($storage.item | get -o backup | get -o interval) " +
|
||||
$" --backup-retention ($storage.item | get -o backup | get -o retention)"
|
||||
)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
print ($"Create storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) in " +
|
||||
$"(_ansi blue_bold)($av_zone)(_ansi reset) with name (_ansi yellow)($storage.item | get -o name)_($server | get -o hostname)(_ansi reset) ... "
|
||||
)
|
||||
let res_create = (^upctl storage create --title $"($storage.item | get -o name)_($server.hostname)" --size ($total_size)
|
||||
--tier ($storage.item | get -o voltype) --zone $av_zone $op_encrypted $op_backup -o json | complete)
|
||||
if $res_create.exit_code != 0 {
|
||||
print ($"❗ Create storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) in " +
|
||||
$"(_ansi blue_bold)($av_zone)(_ansi reset) with ($storage.item | get -o name) (_ansi red)error(_ansi reset) ($res_create.stdout)"
|
||||
)
|
||||
return {}
|
||||
}
|
||||
let server_id = ($server_info | get -o uuid | default "")
|
||||
let vol = ($res_create.stdout | from json)
|
||||
let vol_id = ($vol | get -o uuid)
|
||||
let new_state = "online"
|
||||
if not (upcloud_wait_storage $settings $server $new_state $vol_id) {
|
||||
print ($"❗ Wait ($vol_id) storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) ($storage.item | get -o name) " +
|
||||
$"in (_ansi blue_bold)($av_zone)(_ansi reset) errors not in (_ansi red)($new_state)(_ansi reset) state"
|
||||
)
|
||||
^upctl storage delete $vol_id
|
||||
print $"❗ Attach ($vol_id) deleted"
|
||||
return {}
|
||||
}
|
||||
let vol_device = ($storage.item | get -o voldevice)
|
||||
if ($server_id | is-empty) { return $vol }
|
||||
print ($"Attach storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) in " +
|
||||
$"(_ansi blue_bold)($av_zone)(_ansi reset) with name (_ansi yellow)($storage.item | get -o name)_($server | get -o hostname)(_ansi reset) ... "
|
||||
)
|
||||
let res_attach = if ($vol_device | is-not-empty) {
|
||||
(^upctl server storage attach $server_id --storage $vol_id --address $vol_device -o "json" | complete)
|
||||
} else {
|
||||
(^upctl server storage attach $server_id --storage $vol_id -o "json" | complete)
|
||||
}
|
||||
if $res_attach.exit_code != 0 {
|
||||
print $res_attach.exit_code
|
||||
print ($"❗Attach ($vol_id) storage for (_ansi green_bold)($server.hostname)(_ansi reset) (_ansi cyan_bold)($total_size)(_ansi reset) " +
|
||||
$"($storage.item | get -o name) ($vol_device) in (_ansi blue_bold)($av_zone)(_ansi reset) (_ansi red)errors(_ansi reset) " +
|
||||
$"\n($res_attach.stdout)"
|
||||
)
|
||||
^upctl storage delete $vol_id
|
||||
print $"❗Attach (_ansi red_bold)($vol_id)(_ansi reset) deleted"
|
||||
return {}
|
||||
}
|
||||
let res_vol = (^upctl storage show $vol_id -o json | complete)
|
||||
if $res_vol.exit_code == 0 {
|
||||
let info_vol = ($res_vol.stdout | from json)
|
||||
print $info_vol
|
||||
if ($info_vol | get -o servers | get -o server | where {|srv| $srv == $server_id } | length) > 0 {
|
||||
print ($"✅ Atached (_ansi yellow)($vol_id)(_ansi reset) storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) " +
|
||||
$"($storage.item | get -o name)(if $vol_device != "" { $' ($vol_device)'}) in (_ansi blue_bold)(_ansi blue_bold)($av_zone)(_ansi reset)(_ansi reset)"
|
||||
)
|
||||
} else {
|
||||
print ($"❗ Volume ($vol_id) storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) " +
|
||||
$"device ($vol_device) in (_ansi blue_bold)(_ansi blue_bold)($av_zone)(_ansi reset)(_ansi reset) (_ansi red)error(_ansi reset) not ($server_id)"
|
||||
)
|
||||
}
|
||||
$info_vol
|
||||
} else {
|
||||
print ($"❗ Volume ($vol_id) storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) " +
|
||||
$"device ($vol_device) in (_ansi blue_bold)(_ansi blue_bold)($av_zone)(_ansi reset)(_ansi reset) (_ansi red)errors(_ansi reset) ($res_vol.stdout)"
|
||||
)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
export def upcloud_storage_fix_size [
|
||||
settings: record
|
||||
server: record
|
||||
storage_pos: int
|
||||
] {
|
||||
let total_size = ($server | get -o storages | get -o $storage_pos | get -o total | default 0)
|
||||
if $total_size == 0 { return 0 }
|
||||
let storage = (^upctl server show $server.hostname "-o" "json" | from json | get -o storage_devices | get -o $storage_pos)
|
||||
if $storage == null {
|
||||
let server_info = (^upctl server show $server.hostname "-o" "json" | from json)
|
||||
let volumes = ($server_info | get -o storage_devices | default [])
|
||||
let storage_data = { item: ($server | get -o storages | get -o $storage_pos), index: $storage_pos }
|
||||
upcloud_create_storage $settings $server $server_info $storage_data $volumes $total_size
|
||||
}
|
||||
let $curr_size = ($storage | get -o storage_size | default 0)
|
||||
if $curr_size == 0 { return 0 }
|
||||
#let storage_parts = ($server.storages? | get -o $storage_pos | get -o parts | default [])
|
||||
#if ($storage_parts | length) == 0 { return 0 }
|
||||
if $curr_size != $total_size {
|
||||
print (
|
||||
$"Stop (_ansi blue_bold)($server.hostname)(_ansi reset) for storage (_ansi yellow_bold)($storage.storage)(_ansi reset)" +
|
||||
$" from (_ansi purple_bold)($curr_size)(_ansi reset) to (_ansi green_bold)($total_size)(_ansi reset) ... "
|
||||
)
|
||||
if (upcloud_change_server_state $settings $server "stop" "") == false {
|
||||
print $"❗ Stop ($server.hostname) errors "
|
||||
return "error"
|
||||
}
|
||||
if $storage_pos == 0 {
|
||||
let res = (^upctl storage modify --size $total_size $storage.storage err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Storage modify errors ($res.stdout ) "
|
||||
return "error"
|
||||
}
|
||||
let new_storage = (^upctl server show $server.hostname "-o" "json" | from json | get -o storage_devices | get -o $storage_pos)
|
||||
let new_curr_size = $new_storage.storage_size? | default 0
|
||||
print $"Start (_ansi blue_bold)($server.hostname)(_ansi reset) with new size (_ansi green_bold)($new_curr_size)(_ansi reset) ... "
|
||||
} else {
|
||||
let storage_settings = ($server | get -o storages | get -o $storage_pos)
|
||||
let new_storage = (^upctl storage $server.hostname "-o" "json" | from json | get -o storage_devices | get -o $storage_pos)
|
||||
let $op_backup = if ($storage_settings | get -o backup | is-not-empty) {
|
||||
( $" --backup-time ($storage_settings | get -o backup | get -o time) " +
|
||||
$" --backup-interval ($storage_settings | get -o backup | get -o interval) " +
|
||||
$" --backup-retention ($storage_settings | get -o backup | get -o retention)"
|
||||
)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
let op_encrypted = if ($storage_settings | get -o encrypted | default false) { "--encrypted" } else { "" }
|
||||
let res_modify = (^upctl storage modify ($new_storage | get -o uuid) --size $total_size $op_encrypted $op_backup| complete)
|
||||
if $res_modify.exit_code != 0 {
|
||||
print ($"❗ Modify storage for ($server.hostname) (_ansi cyan_bold)($total_size)(_ansi reset) in " +
|
||||
$"(_ansi blue_bold)($storage.zone)(_ansi reset) with ($storage.item | get -o name) (_ansi red)error(_ansi reset) ($res_modify.stdout)"
|
||||
)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
if (upcloud_change_server_state $settings $server "start" "") == false {
|
||||
print $"❗ Errors to start ($server.hostname) "
|
||||
return "error"
|
||||
}
|
||||
#return "storage"
|
||||
}
|
||||
"storage"
|
||||
}
|
||||
export def upcloud_status_server [
|
||||
hostname: string
|
||||
] {
|
||||
let res = (^upctl server show $hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ status ($hostname) errors "
|
||||
if $env.PROVISIONING_DEBUG { print $res.stdout }
|
||||
return ""
|
||||
}
|
||||
return ($res.stdout | from json | get -o state | default "")
|
||||
}
|
||||
export def upcloud_server_exists [
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let res = (^upctl server show $server.hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
if $error_exit {
|
||||
print $"❗ server ($server.hostname) exists errors ($res.stdout ) "
|
||||
exit 1
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def upcloud_server_state [
|
||||
server: record
|
||||
new_state: string
|
||||
error_exit: bool
|
||||
wait: bool
|
||||
settings: record
|
||||
] {
|
||||
let res = (^upctl server show $server.hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
if $error_exit {
|
||||
print $"❗ state ($server.hostname) errors ($res.stdout ) "
|
||||
exit 1
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def upcloud_server_is_running [
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let res = (^upctl server show $server.hostname "-o" "json" err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ is running ($server.hostname) errors ($res.stdout ) "
|
||||
if $error_exit {
|
||||
exit 1
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
(($res.stdout | from json).state? | str contains "started" | default false)
|
||||
}
|
||||
export def upcloud_change_server_state [
|
||||
settings: record
|
||||
server: record
|
||||
new_state: string
|
||||
ops: string
|
||||
] {
|
||||
let state = (upcloud_status_server $server.hostname)
|
||||
if $state == "" { return false }
|
||||
if ($state | str contains $new_state) { return true }
|
||||
print $"Checking (_ansi blue_bold)($server.hostname)(_ansi reset) state (_ansi yellow_bold)($new_state)(_ansi reset) ..."
|
||||
let val_timeout = if $server.running_timeout? != null { $server.running_timeout } else { 60 }
|
||||
let wait = if $server.running_wait? != null { $server.running_wait } else { 10 }
|
||||
let wait_duration = ($"($wait)sec"| into duration)
|
||||
let res = if ($ops | str contains "--type" ) {
|
||||
(^upctl server $new_state --type ($ops | str replace "--type " "") $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
} else if $ops != "" {
|
||||
(^upctl server $new_state $ops $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" })| complete)
|
||||
} else {
|
||||
(^upctl server $new_state $server.hostname err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
}
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗Errors ($server.hostname) to ($new_state) ($res.stdout ) "
|
||||
return false
|
||||
}
|
||||
mut num = 0
|
||||
while true {
|
||||
let status = (upcloud_status_server $server.hostname)
|
||||
if ($status | str contains $new_state) {
|
||||
print " "
|
||||
return true
|
||||
} 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)($new_state)(_ansi reset) (_ansi red_bold)failed(_ansi reset) "
|
||||
return false
|
||||
} else {
|
||||
$num = $num + $wait
|
||||
if $env.PROVISIONING_DEBUG {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)(_ansi green)($server.hostname)(_ansi reset)->($status) "
|
||||
} else {
|
||||
print -n $"(_ansi blue_bold) 🌥 (_ansi reset)"
|
||||
}
|
||||
sleep $wait_duration
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
export def upcloud_delete_server_storage [
|
||||
settings: record
|
||||
server: record
|
||||
error_exit: bool
|
||||
] {
|
||||
let res = (^upctl storage list --normal -o json | complete)
|
||||
if $res.exit_code == 0 {
|
||||
let data = ($res.stdout | from json)
|
||||
$data.storages? | default [] | each {|storage|
|
||||
if ($storage.title | str starts-with $server.hostname ) {
|
||||
if (upcloud_server_exists $server false) {
|
||||
print $"❗ (_ansi blue_bold)($server.hostname)(_ansi reset) (_ansi red_bold)exists(_ansi reset) can not delete storage (_ansi yellow)($storage.uuid)(_ansi reset)"
|
||||
} else {
|
||||
let del_res = (^upctl storage delete $storage.uuid err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) | complete)
|
||||
if $del_res.exit_code != 0 {
|
||||
print $"❗ Delete storage (_ansi yellow)($storage.uuid)(_ansi reset) for (_ansi blue_bold)($server.hostname)(_ansi reset) (_ansi red_bold)errors(_ansi reset) ($del_res.stdout ) "
|
||||
} else {
|
||||
print $"(_ansi yellow)($storage.uuid)(_ansi reset) for (_ansi blue_bold)($server.hostname)(_ansi reset) (_ansi green_bold)deleted(_ansi reset) ($del_res.stdout ) "
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
export def upcloud_delete_server [
|
||||
settings: record
|
||||
server: record
|
||||
keep_storage: bool
|
||||
error_exit: bool
|
||||
] {
|
||||
if not (upcloud_change_server_state $settings $server "stop" "--type hard") {
|
||||
if $env.PROVISIONING_DEBUG { print $"❗ Stop (_ansi blue_bold)($server.hostname)(_ansi reset) errors " }
|
||||
return false
|
||||
}
|
||||
let ops = if $keep_storage { "" } else { "--delete-storages" }
|
||||
let res = (^upctl server delete $server.hostname $ops err> (std null-device) | complete)
|
||||
if $res.exit_code != 0 {
|
||||
print $"❗ Delete (_ansi blue_bold)($server.hostname)(_ansi reset) (_ansi red_bold)errors(_ansi reset) ($res.stdout ) "
|
||||
return false
|
||||
}
|
||||
print $"(_ansi blue_bold)($server.hostname)(_ansi reset) (_ansi green_bold)deleted(_ansi reset)"
|
||||
true
|
||||
}
|
||||
42
providers/upcloud/nulib/upcloud/usage.nu
Normal file
42
providers/upcloud/nulib/upcloud/usage.nu
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
#!/usr/bin/env nu
|
||||
|
||||
# myscript.nu
|
||||
export def usage [provider: string, infra: string] {
|
||||
let info = if ( $env.CURRENT_FILE? | into string ) != "" { (^grep "^# Info:" $env.CURRENT_FILE ) | str replace "# Info: " "" } else { "" }
|
||||
# $(declare -F _usage_options >/dev/null && _usage_options)
|
||||
$"
|
||||
USAGE provisioning ($provider) -k cloud-path file-settings.yaml provider-options
|
||||
DESCRIPTION
|
||||
UPCLOUD ($info)
|
||||
OPTIONS
|
||||
-s server-hostname
|
||||
with server-hostname target selection
|
||||
-p provider-name
|
||||
use provider name
|
||||
do not need if 'current directory path basename' is not one of providers available
|
||||
-new | new [provisioning-name]
|
||||
create a new provisioning-directory-name by a copy of ($infra)
|
||||
-k cloud-path-item
|
||||
use cloud-path-item as base directory for settings
|
||||
-x
|
||||
Trace script with 'set -x'
|
||||
providerslist | providers-list | providers list
|
||||
Get available providers list
|
||||
taskslist | tasks-list | tasks list
|
||||
Get available tasks list
|
||||
serviceslist | service-list
|
||||
Get available services list
|
||||
tools
|
||||
Run core/on-tools info
|
||||
-i
|
||||
About this
|
||||
-v
|
||||
Print version
|
||||
-h, --help
|
||||
Print this help and exit.
|
||||
PROV: ($env.WK_CNPROV)
|
||||
"
|
||||
# ["hello" $name $title]
|
||||
}
|
||||
|
||||
24
providers/upcloud/nulib/upcloud/utils.nu
Normal file
24
providers/upcloud/nulib/upcloud/utils.nu
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
export def upcloud_check_requirements [
|
||||
settings: record
|
||||
fix_error: bool
|
||||
] {
|
||||
let has_upctl = (^bash -c "type -P upctl")
|
||||
if ($has_upctl | path exists) == false and $fix_error {
|
||||
( ^($env.PROVISIONING_NAME) "tools" "install" "upctl")
|
||||
}
|
||||
let has_upctl = (^bash -c "type -P upctl")
|
||||
if ($has_upctl | path exists) == false {
|
||||
(throw-error $"🛑 CLI command upclouds not found"
|
||||
"upcloud_check_requirements" --span (metadata $has_upctl).span)
|
||||
exit 1
|
||||
}
|
||||
let upctl_version = (^upctl version | grep "Version" | cut -f2 -d":" | sed 's/ //g')
|
||||
let req_version = (open $env.PROVISIONING_REQ_VERSIONS).upctl?.version? | default "")
|
||||
if ($upctl_version != $req_version ) and $fix_error {
|
||||
( ^($env.PROVISIONING_NAME) "tools" "update" "upctl")
|
||||
}
|
||||
let upctl_version = (^upctl version | grep "Version" | cut -f2 -d":" | sed 's/ //g')
|
||||
if $upctl_version != $req_version {
|
||||
print $"warning❗ upctl command as CLI for UpCloud ($upctl_version) with Provisioning is not ($req_version)"
|
||||
}
|
||||
}
|
||||
394
providers/upcloud/pricing.html
Normal file
394
providers/upcloud/pricing.html
Normal file
File diff suppressed because one or more lines are too long
9
providers/upcloud/provisioning.yaml
Normal file
9
providers/upcloud/provisioning.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
version: 1.0
|
||||
info: UpCloud provisioning
|
||||
site: https://upcloudltd.github.io/upcloud-cli
|
||||
tools:
|
||||
upctl:
|
||||
version: 3.9.0
|
||||
source: https://github.com/UpCloudLtd/upcloud-cli/releases/download
|
||||
tags: https://github.com/UpCloudLtd/upcloud-cli/tags
|
||||
site: https://upcloudltd.github.io/upcloud-cli
|
||||
4
providers/upcloud/versions
Normal file
4
providers/upcloud/versions
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
UPCLOUD_UPCTL_VERSION="3.20.1"
|
||||
UPCLOUD_UPCTL_SOURCE="https://github.com/UpCloudLtd/upcloud-cli/releases/download"
|
||||
UPCLOUD_UPCTL_TAGS="https://github.com/UpCloudLtd/upcloud-cli/tags"
|
||||
UPCLOUD_UPCTL_SITE="https://upcloudltd.github.io/upcloud-cli"
|
||||
12
providers/upcloud/versions.yaml
Normal file
12
providers/upcloud/versions.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
upctl:
|
||||
version: 3.9.0
|
||||
fixed: false
|
||||
source: https://github.com/UpCloudLtd/upcloud-cli/releases
|
||||
tags: https://github.com/UpCloudLtd/upcloud-cli/tags
|
||||
site: https://upcloudltd.github.io/upcloud-cli
|
||||
detector:
|
||||
method: command
|
||||
command: upctl version
|
||||
pattern: Version:\s+(\d+\.\d+\.\d+)
|
||||
capture: capture0
|
||||
comparison: semantic
|
||||
12
providers/upcloud/versions.yaml.backup
Normal file
12
providers/upcloud/versions.yaml.backup
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
upctl:
|
||||
version: 3.9.0
|
||||
fixed: false
|
||||
source: https://github.com/UpCloudLtd/upcloud-cli/releases
|
||||
tags: https://github.com/UpCloudLtd/upcloud-cli/tags
|
||||
site: https://upcloudltd.github.io/upcloud-cli
|
||||
detector:
|
||||
method: command
|
||||
command: upctl version
|
||||
pattern: Version:\s+(\d+\.\d+\.\d+)
|
||||
capture: capture0
|
||||
comparison: semantic
|
||||
Loading…
Add table
Add a link
Reference in a new issue