From 434ead5e301e4f55b53eaeb922e3ac96acdc4b8d Mon Sep 17 00:00:00 2001 From: Aleksandr Rybolovlev Date: Thu, 19 Dec 2024 15:08:49 +0100 Subject: [PATCH] Handle scenario when HPA metric type is Pods and target average value becomes mandatory --- ...netes_horizontal_pod_autoscaler_v2_test.go | 136 ++++++++++++++++++ .../structure_horizontal_pod_autoscaler_v2.go | 22 ++- 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_v2_test.go b/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_v2_test.go index 265f80f248..dafcd3f33e 100644 --- a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_v2_test.go +++ b/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_v2_test.go @@ -226,6 +226,63 @@ func TestAccKubernetesHorizontalPodAutoscalerV2_containerResource(t *testing.T) }) } +func TestAccKubernetesHorizontalPodAutoscalerV2_MetricsPods(t *testing.T) { + name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) + resourceName := "kubernetes_horizontal_pod_autoscaler_v2.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + skipIfClusterVersionLessThan(t, "1.23.0") + }, + IDRefreshName: resourceName, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckKubernetesHorizontalPodAutoscalerV2Destroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesHorizontalPodAutoscalerV2Config_MetricsPods(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckKubernetesHorizontalPodAutoscalerV2Exists(resourceName), + resource.TestCheckResourceAttr(resourceName, "metadata.0.name", name), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"), + resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"), + resource.TestCheckResourceAttr(resourceName, "spec.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.behavior.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.max_replicas", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.min_replicas", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.scale_target_ref.#", "1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.scale_target_ref.0.kind", "Deployment"), + resource.TestCheckResourceAttr(resourceName, "spec.0.scale_target_ref.0.name", "TerraformAccTest"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.#", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.0.type", "Pods"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.0.pods.0.metric.0.name", "Value_value_average_value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.0.pods.0.target.0.type", "Value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.0.pods.0.target.0.value", "10"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.0.pods.0.target.0.average_value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.1.type", "Pods"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.1.pods.0.metric.0.name", "Value_average_value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.1.pods.0.target.0.type", "Value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.1.pods.0.target.0.average_value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.2.type", "Pods"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.2.pods.0.metric.0.name", "AverageValue_average_value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.2.pods.0.target.0.type", "AverageValue"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.2.pods.0.target.0.average_value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.3.type", "Pods"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.3.pods.0.metric.0.name", "Utilization_average_utilization_average_value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.3.pods.0.target.0.type", "Utilization"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.3.pods.0.target.0.average_utilization", "15"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.3.pods.0.target.0.average_value", "5"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.4.type", "Pods"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.4.pods.0.metric.0.name", "Utilization_average_value"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.4.pods.0.target.0.type", "Utilization"), + resource.TestCheckResourceAttr(resourceName, "spec.0.metric.4.pods.0.target.0.average_value", "5"), + ), + }, + }, + }) +} + func testAccCheckKubernetesHorizontalPodAutoscalerV2Destroy(s *terraform.State) error { conn, err := testAccProvider.Meta().(KubeClientsets).MainClientset() @@ -537,3 +594,82 @@ func testAccKubernetesHorizontalPodAutoscalerV2Config_containerResource(name str } `, name) } + +func testAccKubernetesHorizontalPodAutoscalerV2Config_MetricsPods(name string) string { + return fmt.Sprintf(`resource "kubernetes_horizontal_pod_autoscaler_v2" "test" { + metadata { + name = %q + } + + spec { + max_replicas = 2 + scale_target_ref { + kind = "Deployment" + name = "TerraformAccTest" + } + metric { + type = "Pods" + pods { + metric { + name = "Value_value_average_value" + } + target { + type = "Value" + value = "10" + average_value = "5" + } + } + } + metric { + type = "Pods" + pods { + metric { + name = "Value_average_value" + } + target { + type = "Value" + average_value = "5" + } + } + } + metric { + type = "Pods" + pods { + metric { + name = "AverageValue_average_value" + } + target { + type = "AverageValue" + average_value = "5" + } + } + } + metric { + type = "Pods" + pods { + metric { + name = "Utilization_average_utilization_average_value" + } + target { + type = "Utilization" + average_utilization = "15" + average_value = "5" + } + } + } + metric { + type = "Pods" + pods { + metric { + name = "Utilization_average_value" + } + target { + type = "Utilization" + average_value = "5" + } + } + } + } +} +`, name) +} diff --git a/kubernetes/structure_horizontal_pod_autoscaler_v2.go b/kubernetes/structure_horizontal_pod_autoscaler_v2.go index 10545faddb..d43b3f105f 100644 --- a/kubernetes/structure_horizontal_pod_autoscaler_v2.go +++ b/kubernetes/structure_horizontal_pod_autoscaler_v2.go @@ -71,11 +71,19 @@ func expandV2MetricTarget(m map[string]interface{}) autoscalingv2.MetricTarget { if v, ok := m["average_utilization"].(int); ok && v > 0 { target.AverageUtilization = ptr.To(int32(v)) } + if v, ok := m["average_value"].(string); ok && v != "0" && v != "" { + q := resource.MustParse(v) + target.AverageValue = &q + } case autoscalingv2.ValueMetricType: if v, ok := m["value"].(string); ok && v != "0" && v != "" { q := resource.MustParse(v) target.Value = &q } + if v, ok := m["average_value"].(string); ok && v != "0" && v != "" { + q := resource.MustParse(v) + target.AverageValue = &q + } } return target @@ -302,9 +310,19 @@ func flattenV2MetricTarget(target autoscalingv2.MetricTarget) []interface{} { case autoscalingv2.AverageValueMetricType: m["average_value"] = target.AverageValue.String() case autoscalingv2.UtilizationMetricType: - m["average_utilization"] = *target.AverageUtilization + if target.AverageUtilization != nil { + m["average_utilization"] = *target.AverageUtilization + } + if target.AverageValue != nil { + m["average_value"] = target.AverageValue.String() + } case autoscalingv2.ValueMetricType: - m["value"] = target.Value.String() + if target.Value != nil { + m["value"] = target.Value.String() + } + if target.AverageValue != nil { + m["average_value"] = target.AverageValue.String() + } } return []interface{}{m}