diff --git a/providers/aws/nulib/aws/cache.nu b/providers/aws/nulib/aws/cache.nu index e426740..3d671f2 100644 --- a/providers/aws/nulib/aws/cache.nu +++ b/providers/aws/nulib/aws/cache.nu @@ -3,6 +3,7 @@ use lib.nu * use ../../../../../core/nulib/lib_provisioning/config/accessor.nu * +use ../../../../../core/nulib/lib_provisioning/utils/settings.nu [get_provider_data_path load_provider_env save_provider_env] export def aws_start_cache_info [ settings: record diff --git a/providers/prov_lib/create_middleware.nu b/providers/prov_lib/create_middleware.nu index fe0cc18..8aca78e 100644 --- a/providers/prov_lib/create_middleware.nu +++ b/providers/prov_lib/create_middleware.nu @@ -826,7 +826,7 @@ $output | append ' # - > Make middleware (middleware.nu env_middleware.nu) for existing providers export def make_middleware [ ] { - use ../../core/nulib/lib_provisioning/config/accessor.nu get-providers-path + use ../../../core/nulib/lib_provisioning/config/accessor.nu get-providers-path let providers_path = (get-providers-path) if not ($providers_path | path exists) { print $"🛑 providers path (ansi red_bold)($providers_path)(ansi reset) not found" diff --git a/providers/prov_lib/middleware.nu b/providers/prov_lib/middleware.nu index f385d87..9060019 100644 --- a/providers/prov_lib/middleware.nu +++ b/providers/prov_lib/middleware.nu @@ -234,8 +234,8 @@ export def mw_server_exists [ provider_undefined $server if $error_exit { exit } else { false } } else { - let result = $res - $result != null + # Return the boolean result directly (true/false from provider) + $res | default false } } @@ -414,6 +414,32 @@ export def mw_get_infra_price [ } } +# Get all infrastructure prices at once (provider-agnostic) - Phase 2 optimization +# Returns: { hour: float, day: float, month: float, unit_info: string } +export def mw_get_all_infra_prices [ + server: record + data: record + error_exit: bool + price_col?: string +]: nothing -> record { + # Try to call provider-specific batched implementation if available + let res = (dispatch_provider_function $server.provider "get_all_infra_prices" $server $data $error_exit $price_col) + + if $res != null { + # Provider has batched implementation + $res + } else { + # Fallback to individual calls (for providers without batched implementation) + let hour = (mw_get_infra_price $server $data "hour" $error_exit $price_col) + { + hour: $hour, + day: (($hour * 24) | math round -p 4), + month: ((mw_get_infra_price $server $data "month" $error_exit $price_col) | math round -p 4), + unit_info: (mw_get_infra_price $server $data "unit" $error_exit $price_col) + } + } +} + # Get infrastructure storage (provider-agnostic) export def mw_get_infra_storage [ server: record @@ -538,6 +564,99 @@ export def mw_suggest_deployment_strategy [ $recommendations } +# Create cache for server (provider-specific) +export def mw_create_cache [ + settings: record + server: record + error_exit: bool +]: nothing -> nothing { + if not ($env.PROVIDER_REGISTRY_INITIALIZED? | default false) { + init-middleware | ignore + } + + let provider_name = $server.provider + + # Dynamic provider dispatch + let res = (dispatch_provider_function $provider_name "create_cache" $settings $server $error_exit) + + if $res == null { + provider_undefined $server + if $error_exit { + log-error $"Failed to create cache for ($server.hostname)" "middleware" + } + } +} + +# Modify server (provider-specific) +export def mw_modify_server [ + settings: record + server: record + modifications: list + check: bool +]: nothing -> any { + if not ($env.PROVIDER_REGISTRY_INITIALIZED? | default false) { + init-middleware | ignore + } + + let provider_name = $server.provider + + # Dynamic provider dispatch + let res = (dispatch_provider_function $provider_name "modify_server" $settings $server $modifications $check) + + if $res == null { + provider_undefined $server + return null + } + + $res +} + +# Post-create server hook (provider-specific) +export def mw_post_create_server [ + settings: record + server: record + check: bool +]: nothing -> string { + if not ($env.PROVIDER_REGISTRY_INITIALIZED? | default false) { + init-middleware | ignore + } + + let provider_name = $server.provider + + # Dynamic provider dispatch + let res = (dispatch_provider_function $provider_name "post_create_server" $settings $server $check) + + if $res == null { + provider_undefined $server + return "" + } + + $res +} + +# Post-generate server hook (provider-specific) +export def mw_post_generate_server [ + settings: record + server: record + check: bool +]: nothing -> string { + if not ($env.PROVIDER_REGISTRY_INITIALIZED? | default false) { + init-middleware | ignore + } + + let provider_name = $server.provider + + # Dynamic provider dispatch + let res = (dispatch_provider_function $provider_name "post_generate_server" $settings $server $check) + + if $res == null { + provider_undefined $server + return "" + } + + $res +} + # Initialize middleware when loaded export-env { # This will be set when middleware functions are first called diff --git a/providers/upcloud/nulib/upcloud/cache.nu b/providers/upcloud/nulib/upcloud/cache.nu index 9c9d983..31c1649 100644 --- a/providers/upcloud/nulib/upcloud/cache.nu +++ b/providers/upcloud/nulib/upcloud/cache.nu @@ -3,6 +3,7 @@ use std use ../../../../../core/nulib/lib_provisioning/config/accessor.nu * +use ../../../../../core/nulib/lib_provisioning/utils/settings.nu [get_provider_data_path load_provider_env save_provider_env] export def upcloud_start_cache_info [ settings: record diff --git a/providers/upcloud/nulib/upcloud/prices.nu b/providers/upcloud/nulib/upcloud/prices.nu index d5be49b..9cfce9f 100644 --- a/providers/upcloud/nulib/upcloud/prices.nu +++ b/providers/upcloud/nulib/upcloud/prices.nu @@ -78,7 +78,7 @@ export def upcloud_get_price [ ($cleaned_value | into float) } }, - "storage" => { + "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 } @@ -89,31 +89,93 @@ export def upcloud_get_price [ "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) + 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" => 1, # Unit is always 1 for storage pricing (return as int to avoid quotes in table) - "month" => + "month" => ($data | find $storage_type | select $str_price_col | flatten | into record | get -o month | default "" | str replace -a "€" "" | into float), - "day" => + "day" => (($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float) * 24), - "hour" => + "hour" => ($data | find $storage_type | select $str_price_col | flatten | into record | get -o hour | default "" | str replace -a "€" "" | into float), _ => 0, } }, - "networking" => { + "networking" => { 0 }, - "backups" => { + "backups" => { 0 }, - _ => { + _ => { 0 } } } + +# Phase 2 Optimization: Get all prices at once +export def upcloud_get_all_infra_prices [ + all_data: record + error_exit: bool + price_col: string = "global_price" +] { + let data = ($all_data | get -o item) + # Return default record if item is empty or not a record + if ($data | is-empty) or (($data | describe) !~ "^record") { + return { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + let str_price_col = if ($price_col | is-empty) { "global_price" } else { $price_col } + match ($all_data | get -o target) { + "server" => { + let price_data = ($data | get -o $str_price_col) + if ($price_data | is-empty) or (($price_data | describe) !~ "^record") { + return { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + let hour_raw = ($price_data | get -o hour | default "") + let month_raw = ($price_data | get -o month | default "") + if ($hour_raw | is-empty) or ($hour_raw == "") { + return { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + let hour = ($hour_raw | str replace -a "€" "" | str trim | into float) + let month = ($month_raw | str replace -a "€" "" | str trim | into float) + { + hour: $hour, + day: (($hour * 24) | math round -p 4), + month: ($month | math round -p 4), + unit_info: 1 + } + }, + "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 { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + if ($it.index) == 0 { + return { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + 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) + { + hour: $hour, + day: (($hour * 24) | math round -p 4), + month: ($month | math round -p 4), + unit_info: 1 + } + }, + _ => { + { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + } +} export def upcloud_get_item_for_storage [ server: record settings: record diff --git a/providers/upcloud/provider.nu b/providers/upcloud/provider.nu index 81f4da5..bf58c80 100644 --- a/providers/upcloud/provider.nu +++ b/providers/upcloud/provider.nu @@ -244,6 +244,23 @@ export def get_infra_price [ } } +# Phase 2 Optimization: Get all prices at once +export def get_all_infra_prices [ + server: record + data: record + error_exit: bool + price_col?: string +]: nothing -> record { + if ($data | get -o item | is-empty) { + return { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } + try { + upcloud_get_all_infra_prices $data $error_exit $price_col + } catch { + { hour: 0.0, day: 0.0, month: 0.0, unit_info: 1 } + } +} + # Cache operations export def start_cache_info [ settings: record