diff --git a/.changes/v3.13.0/1266-bug-fixes.md b/.changes/v3.13.0/1266-bug-fixes.md new file mode 100644 index 000000000..2771d5530 --- /dev/null +++ b/.changes/v3.13.0/1266-bug-fixes.md @@ -0,0 +1,4 @@ +* Fix [Issue #1258](https://github.com/vmware/terraform-provider-vcd/issues/1258): `vcd_cse_kubernetes_cluster` fails +during creation when the chosen network belongs to a VDC Group [GH-1266] +* Fix [Issue #1265](https://github.com/vmware/terraform-provider-vcd/issues/1265): The `kubeconfig` attribute from + `vcd_cse_kubernetes_cluster` resource and data source is now marked as sensitive [GH-1266] \ No newline at end of file diff --git a/go.mod b/go.mod index 43e543e4e..bc14056bd 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 github.com/kr/pretty v0.3.1 - github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.5 + github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.6 ) require ( diff --git a/go.sum b/go.sum index b04a92efe..04819bdc3 100644 --- a/go.sum +++ b/go.sum @@ -148,8 +148,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.5 h1:jSIV59RPURJIij4uj4NRl+cWyl+l91yRrM33O6aR8gM= -github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.5/go.mod h1:vbuNYzuADDBFhi9i2dIKWeNxMK1VFF0dACq01amYBIM= +github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.6 h1:8lX7HfjqEs395K0c+8AHnK2Lu1FEHz1FKmWa/qFVGVc= +github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.6/go.mod h1:vbuNYzuADDBFhi9i2dIKWeNxMK1VFF0dACq01amYBIM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= diff --git a/vcd/datasource_vcd_cse_kubernetes_cluster.go b/vcd/datasource_vcd_cse_kubernetes_cluster.go index 483eeaa96..9814f412c 100644 --- a/vcd/datasource_vcd_cse_kubernetes_cluster.go +++ b/vcd/datasource_vcd_cse_kubernetes_cluster.go @@ -247,6 +247,7 @@ func datasourceVcdCseKubernetesCluster() *schema.Resource { Type: schema.TypeString, Computed: true, Description: "The contents of the kubeconfig of the Kubernetes cluster, only available when 'state=provisioned'", + Sensitive: true, }, "supported_upgrades": { Type: schema.TypeSet, diff --git a/vcd/resource_vcd_cse_kubernetes_cluster.go b/vcd/resource_vcd_cse_kubernetes_cluster.go index 2c0059b30..d6d57e34c 100644 --- a/vcd/resource_vcd_cse_kubernetes_cluster.go +++ b/vcd/resource_vcd_cse_kubernetes_cluster.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/go-vcloud-director/v2/govcd" + "regexp" "sort" "time" ) @@ -18,7 +19,7 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { // This regular expression matches strings with at most 31 characters, composed only by lowercase alphanumeric characters or '-', // that must start with an alphabetic character, and end with an alphanumeric. // This is used for any "name" property in CSE, like cluster name, worker pool name or storage class name. - const kubernetesNameRegex = `^[a-z](?:[a-z0-9-]{0,29}[a-z0-9])?$` + kubernetesNameRegex := regexp.MustCompile(`^[a-z](?:[a-z0-9-]{0,29}[a-z0-9])?$`) return &schema.Resource{ CreateContext: resourceVcdCseKubernetesClusterCreate, @@ -62,8 +63,8 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { Required: true, ForceNew: true, Description: "The name of the Kubernetes cluster", - ValidateDiagFunc: matchRegex(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ - "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters"), + ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ + "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters")), }, "kubernetes_template_id": { Type: schema.TypeString, @@ -135,7 +136,7 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { Optional: true, Default: 20, // As suggested in UI ForceNew: true, - ValidateDiagFunc: minimumValue(20, "disk size in Gibibytes (Gi) must be at least 20"), + ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(20)), Description: "Disk size, in Gibibytes (Gi), for the control plane nodes. Must be at least 20", }, "sizing_policy_id": { @@ -183,22 +184,22 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { Type: schema.TypeString, Required: true, Description: "The name of this worker pool. Must be unique", - ValidateDiagFunc: matchRegex(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ - "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters"), + ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ + "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters")), }, "machine_count": { Type: schema.TypeInt, Optional: true, Default: 1, // As suggested in UI Description: "The number of nodes that this worker pool has. Must be higher than or equal to 0", - ValidateDiagFunc: minimumValue(0, "number of nodes must be higher than or equal to 0"), + ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(0)), }, "disk_size_gi": { Type: schema.TypeInt, Optional: true, Default: 20, // As suggested in UI Description: "Disk size, in Gibibytes (Gi), for the control plane nodes", - ValidateDiagFunc: minimumValue(20, "disk size in Gibibytes (Gi) must be at least 20"), + ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(20)), }, "sizing_policy_id": { Type: schema.TypeString, @@ -241,8 +242,8 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { ForceNew: true, Type: schema.TypeString, Description: "Name to give to this storage class", - ValidateDiagFunc: matchRegex(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ - "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters"), + ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(kubernetesNameRegex, "name must contain only lowercase alphanumeric characters or '-',"+ + "start with an alphabetic character, end with an alphanumeric, and contain at most 31 characters")), }, "reclaim_policy": { Required: true, @@ -297,7 +298,7 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { Description: "The time, in minutes, to wait for the cluster operations to be successfully completed. For example, during cluster creation, it should be in `provisioned`" + "state before the timeout is reached, otherwise the operation will return an error. For cluster deletion, this timeout" + "specifies the time to wait until the cluster is completely deleted. Setting this argument to `0` means to wait indefinitely", - ValidateDiagFunc: minimumValue(0, "timeout must be at least 0 (no timeout)"), + ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(0)), }, "kubernetes_version": { Type: schema.TypeString, @@ -341,6 +342,7 @@ func resourceVcdCseKubernetesCluster() *schema.Resource { Type: schema.TypeString, Computed: true, Description: "The contents of the kubeconfig of the Kubernetes cluster, only available when 'state=provisioned'", + Sensitive: true, }, "supported_upgrades": { Type: schema.TypeSet, diff --git a/vcd/validate_funcs.go b/vcd/validate_funcs.go index 1ac00dc9c..58393f2a9 100644 --- a/vcd/validate_funcs.go +++ b/vcd/validate_funcs.go @@ -171,38 +171,6 @@ func IsIntAndAtLeast(min int) schema.SchemaValidateFunc { } } -// minimumValue returns a SchemaValidateDiagFunc that tests if the provided value is at least min (inclusive) -func minimumValue(min int, errorMessage string) schema.SchemaValidateDiagFunc { - return func(v interface{}, path cty.Path) diag.Diagnostics { - value, ok := v.(int) - if !ok { - return diag.Errorf("could not parse int value '%v'", v) - } - if value < min { - return diag.Errorf("%s: %d < %d", errorMessage, value, min) - } - return nil - } -} - -// matchRegex returns a SchemaValidateDiagFunc that tests whether the provided value matches the regular expression -func matchRegex(regex, errorMessage string) schema.SchemaValidateDiagFunc { - return func(v interface{}, path cty.Path) diag.Diagnostics { - value, ok := v.(string) - if !ok { - return diag.Errorf("could not parse string value '%v'", v) - } - r, err := regexp.Compile(regex) - if err != nil { - return diag.Errorf("could not compile regular expression '%s': %s", regex, err) - } - if !r.MatchString(value) { - return diag.Errorf("%s", errorMessage) - } - return nil - } -} - // IsFloatAndBetween returns a SchemaValidateFunc which tests if the provided value convertable to // float64 and is between min and max (inclusive). func IsFloatAndBetween(min, max float64) schema.SchemaValidateFunc { diff --git a/website/docs/r/cse_kubernetes_cluster.html.markdown b/website/docs/r/cse_kubernetes_cluster.html.markdown index 4669e24b0..b86b586db 100644 --- a/website/docs/r/cse_kubernetes_cluster.html.markdown +++ b/website/docs/r/cse_kubernetes_cluster.html.markdown @@ -111,7 +111,8 @@ resource "vcd_cse_kubernetes_cluster" "my_cluster" { } output "kubeconfig" { - value = vcd_cse_kubernetes_cluster.my_cluster.kubeconfig + value = vcd_cse_kubernetes_cluster.my_cluster.kubeconfig + sensitive = true } ``` @@ -244,7 +245,8 @@ To retrieve the Kubeconfig of a created cluster, you may set it as an output: ```hcl output "kubeconfig" { - value = vcd_cse_kubernetes_cluster.my_cluster.kubeconfig + value = vcd_cse_kubernetes_cluster.my_cluster.kubeconfig + sensitive = true } ```