From b834b4d21f41dd5cfda6bc54b934eb229951cf50 Mon Sep 17 00:00:00 2001 From: Praveen Kumar <42026111+Praveen005@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:25:52 +0530 Subject: [PATCH] Fix: Enhance Kubernetes version handling (#329) * Enhance Kubernetes version handling - improve error message by showing current stable and development versions --- .../kubernetes/resource_kubernetes_cluster.go | 66 +++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/civo/kubernetes/resource_kubernetes_cluster.go b/civo/kubernetes/resource_kubernetes_cluster.go index ca6fd7b4..003a2e63 100644 --- a/civo/kubernetes/resource_kubernetes_cluster.go +++ b/civo/kubernetes/resource_kubernetes_cluster.go @@ -4,11 +4,13 @@ import ( "context" "errors" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "log" + "regexp" "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/civo/civogo" "github.com/civo/terraform-provider-civo/internal/utils" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -236,6 +238,10 @@ func resourceKubernetesClusterCreate(ctx context.Context, d *schema.ResourceData config.NetworkID = defaultNetwork.ID } + if attr, ok := d.GetOk("cluster_type"); ok { + config.ClusterType = attr.(string) + } + if attr, ok := d.GetOk("kubernetes_version"); ok { config.KubernetesVersion = attr.(string) } @@ -260,10 +266,6 @@ func resourceKubernetesClusterCreate(ctx context.Context, d *schema.ResourceData config.Applications = "" } - if attr, ok := d.GetOk("cluster_type"); ok { - config.ClusterType = attr.(string) - } - if attr, ok := d.GetOk("firewall_id"); ok { firewallID := attr.(string) firewall, err := apiClient.FindFirewall(firewallID) @@ -514,6 +516,60 @@ func resourceKubernetesClusterDelete(ctx context.Context, d *schema.ResourceData } func customizeDiffKubernetesCluster(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { + + // Check if kubernetes version string is correct + if kubeVersion, ok := d.GetOk("kubernetes_version"); ok { + version := kubeVersion.(string) + var k3sVersionRegex = regexp.MustCompile(`^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-k3s\d$`) + var talosVersionRegex = regexp.MustCompile(`^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$`) + + clusterType := "k3s" // Default + attr, ok := d.GetOk("cluster_type") + if ok { + clusterType = attr.(string) + } + + availableVersions, err := getKubernetesVersions(meta, nil) + if err != nil { + return fmt.Errorf("failed to get available Kubernetes versions: %w", err) + } + + var stableVersions []string + var developmentVersions []string + + for _, v := range availableVersions { + kv := v.(civogo.KubernetesVersion) + if kv.ClusterType == clusterType { + switch kv.Type { + case "stable": + stableVersions = append(stableVersions, kv.Version) + case "development": + developmentVersions = append(developmentVersions, kv.Version) + } + } + } + + isValidVersion := false + switch clusterType { + case "k3s": + isValidVersion = k3sVersionRegex.MatchString(version) + if !isValidVersion { + return fmt.Errorf("invalid Kubernetes version format: '%s' for cluster type '%s'.\n\n"+ + "Please ensure your version matches the expected format, e.g., 'X.Y.Z-k3s1'.\n\n"+ + "Available versions for '%s':\n- Stable: %v\n- Development: %v", + version, clusterType, clusterType, stableVersions, developmentVersions) + } + case "talos": + isValidVersion = talosVersionRegex.MatchString(version) + if !isValidVersion { + return fmt.Errorf("invalid Kubernetes version format: '%s' for cluster type '%s'.\n\n"+ + "Please ensure your version matches the expected format, e.g., 'X.Y.Z'.\n\n"+ + "Available versions for '%s':\n- Stable: %v", + version, clusterType, clusterType, stableVersions) + } + } + } + if d.Id() != "" { if d.HasChange("write_kubeconfig") { err := d.SetNewComputed("kubeconfig")