Repository: digitalocean/doctl
Pull request #1654 (2025-02-04 21:34:30)

k8s: fix autoscaler integration test cases
Fixes the broken projects list test for the K8s resource, and adds a new k8s cluster get test to check for the newly added autoscaler fields.

This should fix the test failures introduced in #1649 

bentranter: > 👍 LGTM!
> 
> Do we understand how the test failure was only found after merging to main?

Yeah, it looks like it's from caching the integration test runs between commits in the same PR. Here's a screenshot from the integration test run on the PR that introduced the failure:
<img width="485" alt="image" src="https://github.com/user-attachments/assets/3a940ab9-1810-403a-a4a5-b174e8a52034" />

Patch:
diff --git a/commands/displayers/kubernetes.go b/commands/displayers/kubernetes.go
index 32f846fe..3fe4020d 100644
--- a/commands/displayers/kubernetes.go
+++ b/commands/displayers/kubernetes.go
@@ -100,26 +100,32 @@ func (clusters *KubernetesClusters) KV() []map[string]any {
 		}
 
 		o := map[string]any{
-			"ID":             cluster.ID,
-			"Name":           cluster.Name,
-			"Region":         cluster.RegionSlug,
-			"Version":        cluster.VersionSlug,
-			"AutoUpgrade":    cluster.AutoUpgrade,
-			"HAControlPlane": cluster.HA,
-			"ClusterSubnet":  cluster.ClusterSubnet,
-			"ServiceSubnet":  cluster.ServiceSubnet,
-			"IPv4":           cluster.IPv4,
-			"Endpoint":       cluster.Endpoint,
-			"Tags":           tags,
-			"Status":         cluster.Status.State,
-			"Created":        cluster.CreatedAt,
-			"Updated":        cluster.UpdatedAt,
-			"NodePools":      strings.Join(nodePools, " "),
+			"ID":                              cluster.ID,
+			"Name":                            cluster.Name,
+			"Region":                          cluster.RegionSlug,
+			"Version":                         cluster.VersionSlug,
+			"AutoUpgrade":                     cluster.AutoUpgrade,
+			"HAControlPlane":                  cluster.HA,
+			"ClusterSubnet":                   cluster.ClusterSubnet,
+			"ServiceSubnet":                   cluster.ServiceSubnet,
+			"IPv4":                            cluster.IPv4,
+			"Endpoint":                        cluster.Endpoint,
+			"Tags":                            tags,
+			"Status":                          cluster.Status.State,
+			"Created":                         cluster.CreatedAt,
+			"Updated":                         cluster.UpdatedAt,
+			"NodePools":                       strings.Join(nodePools, " "),
+			"Autoscaler.UtilizationThreshold": "",
+			"Autoscaler.UnneededTime":         "",
 		}
 
 		if cfg := cluster.ClusterAutoscalerConfiguration; cfg != nil {
-			o["Autoscaler.UtilizationThreshold"] = fmt.Sprintf("%d%%", int(*cfg.ScaleDownUtilizationThreshold*100))
-			o["Autoscaler.UnneededTime"] = *cfg.ScaleDownUnneededTime
+			if cluster.ClusterAutoscalerConfiguration.ScaleDownUtilizationThreshold != nil {
+				o["Autoscaler.UtilizationThreshold"] = fmt.Sprintf("%d%%", int(*cfg.ScaleDownUtilizationThreshold*100))
+			}
+			if cluster.ClusterAutoscalerConfiguration.ScaleDownUnneededTime != nil {
+				o["Autoscaler.UnneededTime"] = *cfg.ScaleDownUnneededTime
+			}
 		}
 
 		out = append(out, o)


Test patch:
diff --git a/integration/kubernetes_clusters_get_test.go b/integration/kubernetes_clusters_get_test.go
new file mode 100644
index 00000000..1ec040a2
--- /dev/null
+++ b/integration/kubernetes_clusters_get_test.go
@@ -0,0 +1,121 @@
+package integration
+
+import (
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"net/http/httputil"
+	"os/exec"
+	"strings"
+	"testing"
+
+	"github.com/sclevine/spec"
+	"github.com/stretchr/testify/require"
+)
+
+var _ = suite("kubernetes/clusters/get", func(t *testing.T, when spec.G, it spec.S) {
+	var (
+		expect *require.Assertions
+		server *httptest.Server
+		cmd    *exec.Cmd
+	)
+
+	it.Before(func() {
+		expect = require.New(t)
+
+		server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+			switch req.URL.Path {
+			case "/v2/kubernetes/clusters":
+				auth := req.Header.Get("Authorization")
+				if auth != "Bearer some-magic-token" {
+					w.WriteHeader(http.StatusUnauthorized)
+					return
+				}
+
+				if req.Method != http.MethodGet {
+					w.WriteHeader(http.StatusMethodNotAllowed)
+					return
+				}
+
+				w.Write([]byte(k8sGetResponse))
+			default:
+				dump, err := httputil.DumpRequest(req, true)
+				if err != nil {
+					t.Fatal("failed to dump request")
+				}
+
+				t.Fatalf("received unknown request: %s", dump)
+			}
+		}))
+	})
+
+	when("command is get", func() {
+		it("gets the kubernetes cluster", func() {
+			cmd = exec.Command(builtBinaryPath,
+				"-t", "some-magic-token",
+				"-u", server.URL,
+				"kubernetes",
+				"cluster",
+				"get",
+				"some-cluster-id",
+			)
+
+			output, err := cmd.CombinedOutput()
+			expect.NoError(err, fmt.Sprintf("received error output: %s", output))
+			expect.Equal(strings.TrimSpace(k8sGetOutput), strings.TrimSpace(string(output)))
+		})
+	})
+
+	when("command is g", func() {
+		it("gets the kubernetes cluster", func() {
+			cmd = exec.Command(builtBinaryPath,
+				"-t", "some-magic-token",
+				"-u", server.URL,
+				"kubernetes",
+				"cluster",
+				"g",
+				"some-cluster-id",
+			)
+
+			output, err := cmd.CombinedOutput()
+			expect.NoError(err, fmt.Sprintf("received error output: %s", output))
+			expect.Equal(strings.TrimSpace(k8sGetOutput), strings.TrimSpace(string(output)))
+		})
+	})
+})
+
+var (
+	k8sGetResponse = `
+{
+  "kubernetes_clusters": [
+	{
+		"id": "some-cluster-id",
+		"name": "some-cluster-id",
+		"region": "nyc3",
+		"version": "some-kube-version",
+		"tags": ["production"],
+		"auto_upgrade": true,
+		"node_pools": [
+		{
+			"name": "frontend-pool"
+		}
+		],
+		"status": {
+		"state": "running",
+		"message": "yes"
+		},
+		"cluster_autoscaler_configuration": {
+    		"scale_down_utilization_threshold": 0.5,
+    		"scale_down_unneeded_time": "1m30s"
+    	},
+		"created_at": "2018-11-15T16:00:11Z",
+		"updated_at": "2018-11-15T16:00:11Z"
+	}
+  ]
+}
+`
+
+	k8sGetOutput = `ID                 Name               Region    Version              Auto Upgrade    HA Control Plane    Status     Endpoint    IPv4    Cluster Subnet    Service Subnet    Tags          Created At                       Updated At                       Node Pools       Autoscaler Scale Down Utilization    Autoscaler Scale Down Unneeded Time
+some-cluster-id    some-cluster-id    nyc3      some-kube-version    true            false               running                                                            production    2018-11-15 16:00:11 +0000 UTC    2018-11-15 16:00:11 +0000 UTC    frontend-pool    50%                                  1m30s
+`
+)
diff --git a/integration/projects_resources_get_test.go b/integration/projects_resources_get_test.go
index 67e2c08b..95f3a2ab 100644
--- a/integration/projects_resources_get_test.go
+++ b/integration/projects_resources_get_test.go
@@ -343,7 +343,7 @@ ID                                      Name       Size      Region    Filesyste
 }
 `
 	projectsResourcesGetKubernetesOutput = `
-ID    Name    Region    Version    Auto Upgrade    HA Control Plane    Status          Endpoint    IPv4    Cluster Subnet    Service Subnet    Tags    Created At                       Updated At                       Node Pools
+ID    Name    Region    Version    Auto Upgrade    HA Control Plane    Status          Endpoint    IPv4    Cluster Subnet    Service Subnet    Tags    Created At                       Updated At                       Node Pools    Autoscaler Scale Down Utilization    Autoscaler Scale Down Unneeded Time
       1111                         false           false               provisioning                                                            k8s     2021-01-29 16:02:02 +0000 UTC    0001-01-01 00:00:00 +0000 UTC    pool-test
 `
 	projectsResourcesListKubernetesOutput = `