diff --git a/README.md b/README.md index cae6f8fd..78cd84a9 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,41 @@ module "castai-aks-cluster" { } ``` + +Migrating from 6.x.x to 7.x.x +--------------------------- + +Version 7.x.x changed: +* Removed `compute_optimized` and `storage_optimized` attributes in `castai_node_template` resource, `constraints` object. Use `compute_optimized_state` and `storage_optimized_state` instead. + +Old configuration: +```terraform +module "castai-aks-cluster" { + node_templates = { + spot_tmpl = { + constraints = { + compute_optimized = false + storage_optimized = true + } + } + } +} +``` + +New configuration: +```terraform +module "castai-aks-cluster" { + node_templates = { + spot_tmpl = { + constraints = { + compute_optimized_state = "disabled" + storage_optimized_state = "enabled" + } + } + } +} +``` + For more information for `castai-aks-cluster` module follow: https://github.com/castai/terraform-castai-aks/blob/main/README.md#migrating-from-2xx-to-3xx If you have used `castai-eks-cluster` or other modules follow: diff --git a/castai/const.go b/castai/const.go index 6e6bd773..2f7e9054 100644 --- a/castai/const.go +++ b/castai/const.go @@ -6,4 +6,7 @@ const ( FieldKey = "key" FieldValue = "value" FieldEffect = "effect" + + Enabled = "enabled" + Disabled = "disabled" ) diff --git a/castai/resource_node_template.go b/castai/resource_node_template.go index 38bc151d..6c8aca00 100644 --- a/castai/resource_node_template.go +++ b/castai/resource_node_template.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -21,6 +22,7 @@ const ( FieldNodeTemplateArchitectures = "architectures" FieldNodeTemplateAZs = "azs" FieldNodeTemplateComputeOptimized = "compute_optimized" + FieldNodeTemplateComputeOptimizedState = "compute_optimized_state" FieldNodeTemplateConfigurationId = "configuration_id" FieldNodeTemplateConstraints = "constraints" FieldNodeTemplateCustomInstancesEnabled = "custom_instances_enabled" @@ -55,6 +57,7 @@ const ( FieldNodeTemplateSpotInterruptionPredictionsEnabled = "spot_interruption_predictions_enabled" FieldNodeTemplateSpotInterruptionPredictionsType = "spot_interruption_predictions_type" FieldNodeTemplateStorageOptimized = "storage_optimized" + FieldNodeTemplateStorageOptimizedState = "storage_optimized_state" FieldNodeTemplateUseSpotFallbacks = "use_spot_fallbacks" FieldNodeTemplateCustomPriority = "custom_priority" FieldNodeTemplateDedicatedNodeAffinity = "dedicated_node_affinity" @@ -231,8 +234,24 @@ func resourceNodeTemplate() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: false, - Description: "Storage optimized instance constraint - will only pick storage optimized nodes if true", - Deprecated: "Storage optimized constraint is deprecated and will be replaced by a new argument in the next major release.", + Description: "Storage optimized instance constraint (deprecated).", + ValidateDiagFunc: func(i interface{}, path cty.Path) diag.Diagnostics { + return diag.Diagnostics{ + { + Severity: diag.Error, + Summary: "Deprecated field `storage_optimized`", + Detail: "Please use `storage_optimized_state` instead, supported values: `enabled`, `disabled` or empty string. See: https://github.com/castai/terraform-provider-castai#migrating-from-6xx-to-7xx", + AttributePath: path, + }, + } + }, + }, + FieldNodeTemplateStorageOptimizedState: { + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "Storage optimized instance constraint - will only pick storage optimized nodes if enabled and won't pick if disabled. Empty value will have no effect. Supported values: `enabled`, `disabled` or empty string.", + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"", Enabled, Disabled}, false)), }, FieldNodeTemplateIsGpuOnly: { Type: schema.TypeBool, @@ -244,8 +263,24 @@ func resourceNodeTemplate() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: false, - Description: "Compute optimized instance constraint - will only pick compute optimized nodes if true.", - Deprecated: "Compute optimized constraint is deprecated and will be replaced by a new argument in the next major release.", + Description: "Compute optimized instance constraint (deprecated).", + ValidateDiagFunc: func(i interface{}, path cty.Path) diag.Diagnostics { + return diag.Diagnostics{ + { + Severity: diag.Error, + Summary: "Deprecated field `compute_optimized`", + Detail: "Please use `compute_optimized_state` instead, supported values: `enabled`, `disabled` or empty string. See: https://github.com/castai/terraform-provider-castai#migrating-from-6xx-to-7xx", + AttributePath: path, + }, + } + }, + }, + FieldNodeTemplateComputeOptimizedState: { + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "Will only include compute optimized nodes when enabled and exclude compute optimized nodes when disabled. Empty value won't have effect on instances filter. Supported values: `enabled`, `disabled` or empty string.", + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"", Enabled, Disabled}, false)), }, FieldNodeTemplateInstanceFamilies: { Type: schema.TypeList, @@ -578,10 +613,18 @@ func flattenConstraints(c *sdk.NodetemplatesV1TemplateConstraints) ([]map[string out[FieldNodeTemplateInstanceFamilies] = flattenInstanceFamilies(c.InstanceFamilies) } if c.ComputeOptimized != nil { - out[FieldNodeTemplateComputeOptimized] = c.ComputeOptimized + if lo.FromPtr(c.ComputeOptimized) { + out[FieldNodeTemplateComputeOptimizedState] = Enabled + } else { + out[FieldNodeTemplateComputeOptimizedState] = Disabled + } } if c.StorageOptimized != nil { - out[FieldNodeTemplateStorageOptimized] = c.StorageOptimized + if lo.FromPtr(c.StorageOptimized) { + out[FieldNodeTemplateStorageOptimizedState] = Enabled + } else { + out[FieldNodeTemplateStorageOptimizedState] = Disabled + } } if c.Spot != nil { out[FieldNodeTemplateSpot] = c.Spot @@ -1049,8 +1092,15 @@ func toTemplateConstraints(obj map[string]any) *sdk.NodetemplatesV1TemplateConst } out := &sdk.NodetemplatesV1TemplateConstraints{} - if v, ok := obj[FieldNodeTemplateComputeOptimized].(bool); ok { - out.ComputeOptimized = toPtr(v) + if v, ok := obj[FieldNodeTemplateComputeOptimizedState].(string); ok { + switch v { + case Enabled: + out.ComputeOptimized = toPtr(true) + case Disabled: + out.ComputeOptimized = toPtr(false) + default: + out.ComputeOptimized = nil + } } if v, ok := obj[FieldNodeTemplateFallbackRestoreRateSeconds].(int); ok { out.FallbackRestoreRateSeconds = toPtr(int32(v)) @@ -1089,8 +1139,15 @@ func toTemplateConstraints(obj map[string]any) *sdk.NodetemplatesV1TemplateConst out.Spot = toPtr(!v) } } - if v, ok := obj[FieldNodeTemplateStorageOptimized].(bool); ok { - out.StorageOptimized = toPtr(v) + if v, ok := obj[FieldNodeTemplateStorageOptimizedState].(string); ok { + switch v { + case Enabled: + out.StorageOptimized = toPtr(true) + case Disabled: + out.StorageOptimized = toPtr(false) + default: + out.StorageOptimized = nil + } } if v, ok := obj[FieldNodeTemplateUseSpotFallbacks].(bool); ok { out.UseSpotFallbacks = toPtr(v) diff --git a/castai/resource_node_template_test.go b/castai/resource_node_template_test.go index 2f0b69f2..536bf5c3 100644 --- a/castai/resource_node_template_test.go +++ b/castai/resource_node_template_test.go @@ -56,7 +56,7 @@ func TestNodeTemplateResourceReadContext(t *testing.T) { "spotDiversityPriceIncreaseLimitPercent": 20, "spotInterruptionPredictionsEnabled": true, "spotInterruptionPredictionsType": "aws-rebalance-recommendations", - "storageOptimized": false, + "storageOptimized": true, "computeOptimized": false, "minCpu": 10, "maxCpu": 10000, @@ -160,6 +160,7 @@ constraints.0.azs.0 = us-west-2a constraints.0.azs.1 = us-west-2b constraints.0.azs.2 = us-west-2c constraints.0.compute_optimized = false +constraints.0.compute_optimized_state = disabled constraints.0.custom_priority.# = 1 constraints.0.custom_priority.0.instance_families.# = 2 constraints.0.custom_priority.0.instance_families.0 = a @@ -208,6 +209,7 @@ constraints.0.spot_diversity_price_increase_limit_percent = 20 constraints.0.spot_interruption_predictions_enabled = true constraints.0.spot_interruption_predictions_type = aws-rebalance-recommendations constraints.0.storage_optimized = false +constraints.0.storage_optimized_state = enabled constraints.0.use_spot_fallbacks = false custom_instances_enabled = true custom_instances_with_extended_memory_enabled = true @@ -467,6 +469,8 @@ func TestAccResourceNodeTemplate_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "constraints.0.custom_priority.0.spot", "true"), resource.TestCheckResourceAttr(resourceName, "constraints.0.custom_priority.0.on_demand", "true"), resource.TestCheckResourceAttr(resourceName, "constraints.0.dedicated_node_affinity.#", "0"), + resource.TestCheckResourceAttr(resourceName, "constraints.0.storage_optimized_state", "disabled"), + resource.TestCheckResourceAttr(resourceName, "constraints.0.compute_optimized_state", ""), ), }, { @@ -529,6 +533,8 @@ func TestAccResourceNodeTemplate_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "constraints.0.custom_priority.1.spot", "true"), resource.TestCheckResourceAttr(resourceName, "constraints.0.custom_priority.1.on_demand", "true"), resource.TestCheckResourceAttr(resourceName, "constraints.0.dedicated_node_affinity.#", "0"), + resource.TestCheckResourceAttr(resourceName, "constraints.0.storage_optimized_state", "enabled"), + resource.TestCheckResourceAttr(resourceName, "constraints.0.compute_optimized_state", "disabled"), ), }, }, @@ -583,6 +589,7 @@ func testAccNodeTemplateConfig(rName, clusterName string) string { spot_interruption_predictions_enabled = true spot_interruption_predictions_type = "interruption-predictions" use_spot_fallbacks = true + storage_optimized_state = "disabled" min_cpu = 4 max_cpu = 100 instance_families { @@ -593,9 +600,7 @@ func testAccNodeTemplateConfig(rName, clusterName string) string { include_names = [] exclude_names = [] manufacturers = ["NVIDIA"] - } - compute_optimized = false - storage_optimized = false + } custom_priority { instance_families = ["c", "d"] @@ -640,8 +645,8 @@ func testNodeTemplateUpdated(rName, clusterName string) string { spot_interruption_predictions_enabled = true spot_interruption_predictions_type = "interruption-predictions" fallback_restore_rate_seconds = 1800 - storage_optimized = false - compute_optimized = false + storage_optimized_state = "enabled" + compute_optimized_state = "disabled" architectures = ["arm64"] azs = ["eu-central-1a", "eu-central-1b", "eu-central-1c"] diff --git a/docs/resources/node_template.md b/docs/resources/node_template.md index dc734717..a83980ec 100644 --- a/docs/resources/node_template.md +++ b/docs/resources/node_template.md @@ -44,8 +44,9 @@ CAST AI node template resource to manage node templates Optional: - `architectures` (List of String) List of acceptable instance CPU architectures, the default is amd64. Allowed values: amd64, arm64. -- `compute_optimized` (Boolean, Deprecated) Compute optimized instance constraint - will only pick compute optimized nodes if true. - `azs` (List of String) The list of AZ names to consider for the node template, if empty or not set all AZs are considered. +- `compute_optimized` (Boolean) Compute optimized instance constraint (deprecated). +- `compute_optimized_state` (String) Will only include compute optimized nodes when enabled and exclude compute optimized nodes when disabled. Empty value won't have effect on instances filter. Supported values: `enabled`, `disabled` or empty string. - `custom_priority` (Block List) (see [below for nested schema](#nestedblock--constraints--custom_priority)) - `dedicated_node_affinity` (Block List) Dedicated node affinity - creates preference for instances to be created on sole tenancy or dedicated nodes. This feature is only available for GCP clusters and sole tenancy nodes with local @@ -68,7 +69,8 @@ Optional: - `spot_diversity_price_increase_limit_percent` (Number) Allowed node configuration price increase when diversifying instance types. E.g. if the value is 10%, then the overall price of diversified instance types can be 10% higher than the price of the optimal configuration. - `spot_interruption_predictions_enabled` (Boolean) Enable/disable spot interruption predictions. - `spot_interruption_predictions_type` (String) Spot interruption predictions type. Can be either "aws-rebalance-recommendations" or "interruption-predictions". -- `storage_optimized` (Boolean, Deprecated) Storage optimized instance constraint - will only pick storage optimized nodes if true +- `storage_optimized` (Boolean) Storage optimized instance constraint (deprecated). +- `storage_optimized_state` (String) Storage optimized instance constraint - will only pick storage optimized nodes if enabled and won't pick if disabled. Empty value will have no effect. Supported values: `enabled`, `disabled` or empty string. - `use_spot_fallbacks` (Boolean) Spot instance fallback constraint - when true, on-demand instances will be created, when spots are unavailable. diff --git a/examples/aks/aks_cluster_arm_template/castai.tf b/examples/aks/aks_cluster_arm_template/castai.tf index 52731d2e..1fa4ea4f 100644 --- a/examples/aks/aks_cluster_arm_template/castai.tf +++ b/examples/aks/aks_cluster_arm_template/castai.tf @@ -100,8 +100,8 @@ module "castai-aks-cluster" { instance_families = { exclude = ["standard_DPLSv5"] } - compute_optimized = false - storage_optimized = false + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" } } } diff --git a/examples/aks/aks_cluster_autoscaler_policies/castai.tf b/examples/aks/aks_cluster_autoscaler_policies/castai.tf index 73fd1f39..4107e011 100644 --- a/examples/aks/aks_cluster_autoscaler_policies/castai.tf +++ b/examples/aks/aks_cluster_autoscaler_policies/castai.tf @@ -100,8 +100,8 @@ module "castai-aks-cluster" { instance_families = { exclude = ["standard_DPLSv5"] } - compute_optimized = false - storage_optimized = false + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" # Optional: define custom priority for instances selection. # diff --git a/examples/eks/eks_cluster_autoscaler_policies/castai.tf b/examples/eks/eks_cluster_autoscaler_policies/castai.tf index 8fca4f88..465ff2ae 100644 --- a/examples/eks/eks_cluster_autoscaler_policies/castai.tf +++ b/examples/eks/eks_cluster_autoscaler_policies/castai.tf @@ -151,9 +151,9 @@ module "castai-eks-cluster" { instance_families = { exclude = ["m5"] } - compute_optimized = false - storage_optimized = false - is_gpu_only = false + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" + is_gpu_only = false # Optional: define custom priority for instances selection. # diff --git a/examples/eks/eks_clusters/module/castai/castai.tf b/examples/eks/eks_clusters/module/castai/castai.tf index ff20084d..a665a692 100644 --- a/examples/eks/eks_clusters/module/castai/castai.tf +++ b/examples/eks/eks_clusters/module/castai/castai.tf @@ -83,9 +83,9 @@ locals { instance_families = { exclude = ["m5"] } - compute_optimized = false - storage_optimized = false - is_gpu_only = false + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" + is_gpu_only = false } } }) diff --git a/examples/gke/gke_cluster_autoscaler_policies/castai.tf b/examples/gke/gke_cluster_autoscaler_policies/castai.tf index c6b648c9..d2321d51 100644 --- a/examples/gke/gke_cluster_autoscaler_policies/castai.tf +++ b/examples/gke/gke_cluster_autoscaler_policies/castai.tf @@ -109,9 +109,8 @@ module "castai-gke-cluster" { instance_families = { exclude = ["e2"] } - compute_optimized = false - storage_optimized = false - + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" # Optional: define custom priority for instances selection. # # 1. Prioritize C2D and C2 spot instances above all else, regardless of price. diff --git a/examples/gke/gke_cluster_existing/castai.tf b/examples/gke/gke_cluster_existing/castai.tf index c50c760a..558aa2aa 100644 --- a/examples/gke/gke_cluster_existing/castai.tf +++ b/examples/gke/gke_cluster_existing/castai.tf @@ -114,8 +114,8 @@ module "castai-gke-cluster" { instance_families = { exclude = ["e2"] } - compute_optimized = false - storage_optimized = false + compute_optimized_state = "disabled" + storage_optimized_state = "disabled" } custom_instances_enabled = true