From fc9bc1023c21319ab2f82f76052f810825d8a11e Mon Sep 17 00:00:00 2001 From: Laimonas Rastenis Date: Thu, 14 Sep 2023 13:22:14 +0300 Subject: [PATCH] feat: add node template custom taint effect support --- castai/resource_node_template.go | 28 ++++++++++++------- castai/resource_node_template_test.go | 14 ++++++++-- castai/sdk/api.gen.go | 26 ++++++++++++----- docs/resources/node_template.md | 2 +- .../gke_cluster_autoscaler_policies/castai.tf | 2 ++ 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/castai/resource_node_template.go b/castai/resource_node_template.go index a107964d..ac041cc7 100644 --- a/castai/resource_node_template.go +++ b/castai/resource_node_template.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/samber/lo" "log" - "regexp" "strings" "time" ) @@ -55,6 +54,12 @@ const ( FieldNodeTemplateUseSpotFallbacks = "use_spot_fallbacks" ) +const ( + TaintEffectNoSchedule = "NoSchedule" + TaintEffectNoExecute = "NoExecute" + TaintEffectPreferNoSchedule = "PreferNoSchedule" +) + const ( ArchAMD64 = "amd64" ArchARM64 = "arm64" @@ -346,11 +351,11 @@ func resourceNodeTemplate() *schema.Resource { FieldEffect: { Optional: true, Type: schema.TypeString, - Default: "NoSchedule", + Default: TaintEffectNoSchedule, ValidateDiagFunc: validation.ToDiagFunc( - validation.StringMatch(regexp.MustCompile("^NoSchedule$"), "effect must be NoSchedule"), + validation.StringInSlice([]string{TaintEffectNoSchedule, TaintEffectNoExecute, TaintEffectPreferNoSchedule}, false), ), - Description: "Effect of a taint to be added to nodes created from this template. The effect must always be NoSchedule.", + Description: "Effect of a taint to be added to nodes created from this template.", }, }, }, @@ -630,7 +635,7 @@ func updateNodeTemplate(ctx context.Context, d *schema.ResourceData, meta any, s ts = append(ts, val.(map[string]any)) } - req.CustomTaints = toCustomTaintsWithoutEffect(ts) + req.CustomTaints = toCustomTaintsWithOptionalEffect(ts) } if !(*req.ShouldTaint) && req.CustomTaints != nil && len(*req.CustomTaints) > 0 { @@ -709,7 +714,7 @@ func resourceNodeTemplateCreate(ctx context.Context, d *schema.ResourceData, met ts = append(ts, val.(map[string]any)) } - req.CustomTaints = toCustomTaintsWithoutEffect(ts) + req.CustomTaints = toCustomTaintsWithOptionalEffect(ts) } if !(*req.ShouldTaint) && req.CustomTaints != nil && len(*req.CustomTaints) > 0 { @@ -848,22 +853,25 @@ func toCustomLabel(obj map[string]any) *sdk.NodetemplatesV1Label { return out } -func toCustomTaintsWithoutEffect(objs []map[string]any) *[]sdk.NodetemplatesV1TaintWithoutEffect { +func toCustomTaintsWithOptionalEffect(objs []map[string]any) *[]sdk.NodetemplatesV1TaintWithOptionalEffect { if len(objs) == 0 { return nil } - out := &[]sdk.NodetemplatesV1TaintWithoutEffect{} + out := &[]sdk.NodetemplatesV1TaintWithOptionalEffect{} for _, taint := range objs { - t := sdk.NodetemplatesV1TaintWithoutEffect{} + t := sdk.NodetemplatesV1TaintWithOptionalEffect{} if v, ok := taint[FieldKey]; ok && v != "" { - t.Key = toPtr(v.(string)) + t.Key = v.(string) } if v, ok := taint[FieldValue]; ok && v != "" { t.Value = toPtr(v.(string)) } + if v, ok := taint[FieldEffect]; ok && v != "" { + t.Effect = toPtr(sdk.NodetemplatesV1TaintEffect(v.(string))) + } *out = append(*out, t) } diff --git a/castai/resource_node_template_test.go b/castai/resource_node_template_test.go index 40083fab..323cfe92 100644 --- a/castai/resource_node_template_test.go +++ b/castai/resource_node_template_test.go @@ -373,11 +373,16 @@ func TestAccResourceNodeTemplate_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "custom_labels.%", "2"), resource.TestCheckResourceAttr(resourceName, "custom_labels."+rName+"-label-key-1", rName+"-label-value-1"), resource.TestCheckResourceAttr(resourceName, "custom_labels."+rName+"-label-key-2", rName+"-label-value-2"), - resource.TestCheckResourceAttr(resourceName, "custom_taints.#", "2"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.#", "3"), resource.TestCheckResourceAttr(resourceName, "custom_taints.0.key", rName+"-taint-key-1"), resource.TestCheckResourceAttr(resourceName, "custom_taints.0.value", rName+"-taint-value-1"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.0.effect", "NoSchedule"), resource.TestCheckResourceAttr(resourceName, "custom_taints.1.key", rName+"-taint-key-2"), resource.TestCheckResourceAttr(resourceName, "custom_taints.1.value", rName+"-taint-value-2"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.1.value", "NoExecute"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.2.key", rName+"-taint-key-3"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.2.value", rName+"-taint-value-3"), + resource.TestCheckResourceAttr(resourceName, "custom_taints.2.value", "NoSchedule"), resource.TestCheckResourceAttr(resourceName, "constraints.0.instance_families.0.exclude.0", "m5"), resource.TestCheckResourceAttr(resourceName, "constraints.0.gpu.0.manufacturers.0", "NVIDIA"), resource.TestCheckResourceAttr(resourceName, "constraints.0.gpu.0.include_names.#", "0"), @@ -470,7 +475,12 @@ func testAccNodeTemplateConfig(rName, clusterName string) string { custom_taints { key = "%[1]s-taint-key-2" value = "%[1]s-taint-value-2" - effect = "NoSchedule" + effect = "NoExecute" + } + + custom_taints { + key = "%[1]s-taint-key-3" + value = "%[1]s-taint-value-3" } constraints { diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go index 3ccd5ba3..0496b776 100644 --- a/castai/sdk/api.gen.go +++ b/castai/sdk/api.gen.go @@ -89,6 +89,13 @@ const ( OnDemand NodetemplatesV1AvailableInstanceTypeStorageOptimizedOption = "OnDemand" ) +// Defines values for NodetemplatesV1TaintEffect. +const ( + NoExecute NodetemplatesV1TaintEffect = "NoExecute" + NoSchedule NodetemplatesV1TaintEffect = "NoSchedule" + PreferNoSchedule NodetemplatesV1TaintEffect = "PreferNoSchedule" +) + // Defines values for PoliciesV1EvictorStatus. const ( Compatible PoliciesV1EvictorStatus = "Compatible" @@ -1437,7 +1444,7 @@ type NodetemplatesV1NewNodeTemplate struct { CustomLabels *NodetemplatesV1NewNodeTemplate_CustomLabels `json:"customLabels,omitempty"` // Custom taints for the template. - CustomTaints *[]NodetemplatesV1TaintWithoutEffect `json:"customTaints,omitempty"` + CustomTaints *[]NodetemplatesV1TaintWithOptionalEffect `json:"customTaints,omitempty"` // Flag whether this template is the default template for the cluster. IsDefault *bool `json:"isDefault,omitempty"` @@ -1518,11 +1525,16 @@ type NodetemplatesV1Taint struct { Value *string `json:"value,omitempty"` } -// TaintWithoutEffect is used when creating/updating a node template. -// We only support the NoSchedule effect for node templates, hence it cannot be set/updated. -type NodetemplatesV1TaintWithoutEffect struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value"` +// TaintEffect is a node taint effect. +type NodetemplatesV1TaintEffect string + +// TaintWithOptionalEffect is used when creating/updating a node template. +// We are adding support for specifying taint effect on node templates and effect should be optional to be backwards compatible. +type NodetemplatesV1TaintWithOptionalEffect struct { + // TaintEffect is a node taint effect. + Effect *NodetemplatesV1TaintEffect `json:"effect,omitempty"` + Key string `json:"key"` + Value *string `json:"value"` } // NodetemplatesV1TemplateConstraints defines model for nodetemplates.v1.TemplateConstraints. @@ -1602,7 +1614,7 @@ type NodetemplatesV1UpdateNodeTemplate struct { CustomLabels *NodetemplatesV1UpdateNodeTemplate_CustomLabels `json:"customLabels,omitempty"` // Custom taints for the template. - CustomTaints *[]NodetemplatesV1TaintWithoutEffect `json:"customTaints,omitempty"` + CustomTaints *[]NodetemplatesV1TaintWithOptionalEffect `json:"customTaints,omitempty"` // Flag whether this template is the default template for the cluster. IsDefault *bool `json:"isDefault,omitempty"` diff --git a/docs/resources/node_template.md b/docs/resources/node_template.md index 8c1ca86b..26e4d82a 100644 --- a/docs/resources/node_template.md +++ b/docs/resources/node_template.md @@ -103,7 +103,7 @@ Required: Optional: -- `effect` (String) Effect of a taint to be added to nodes created from this template. The effect must always be NoSchedule. +- `effect` (String) Effect of a taint to be added to nodes created from this template. diff --git a/examples/gke/gke_cluster_autoscaler_policies/castai.tf b/examples/gke/gke_cluster_autoscaler_policies/castai.tf index 2ec75a3d..386cb5a6 100644 --- a/examples/gke/gke_cluster_autoscaler_policies/castai.tf +++ b/examples/gke/gke_cluster_autoscaler_policies/castai.tf @@ -88,10 +88,12 @@ module "castai-gke-cluster" { { key = "custom-taint-key-1" value = "custom-taint-value-1" + effect = "NoSchedule" }, { key = "custom-taint-key-2" value = "custom-taint-value-2" + effect = "NoSchedule" } ]