provisioning/providers/upcloud/nulib/upcloud/prices.nu
2025-09-22 23:11:41 +01:00

304 lines
12 KiB
Text

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) "
)
}
}