Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mmv1/products/cloudrunv2/Service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ properties:
description: |-
Only memory, CPU, and nvidia.com/gpu are supported. Use key `cpu` for CPU limit, `memory` for memory limit, `nvidia.com/gpu` for gpu limit. Note: The only supported values for CPU are '1', '2', '4', '6' and '8'. Setting 4 CPU requires at least 2Gi of memory, setting 6 or more CPU requires at least 4Gi of memory. The values of the map is string form of the 'quantity' k8s type: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go
default_from_api: true
diff_suppress_func: 'cloudRunV2ServiceResourceLimitsDiffSuppress'
- name: 'cpuIdle'
type: Boolean
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2082,3 +2082,60 @@ resource "google_cloud_run_v2_service" "default" {
}
`, context)
}

// TestAccCloudRunV2Service_noPermadiffWithMemoryLimitOnly verifies that setting
// only the memory key in template.containers.resources.limits does not produce a
// perpetual diff. The API automatically adds a default cpu limit which should be
// silently accepted. Regression test for:
// https://github.com/hashicorp/terraform-provider-google/issues/20399
func TestAccCloudRunV2Service_noPermadiffWithMemoryLimitOnly(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckCloudRunV2ServiceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccCloudRunV2Service_memoryLimitOnly(context),
},
{
ResourceName: "google_cloud_run_v2_service.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "deletion_protection"},
},
// Second plan must produce no diff (no permadiff on cpu limit key).
{
Config: testAccCloudRunV2Service_memoryLimitOnly(context),
PlanOnly: true,
},
},
})
}

func testAccCloudRunV2Service_memoryLimitOnly(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_service" "default" {
name = "tf-test-cloudrun-service%{random_suffix}"
location = "us-central1"
deletion_protection = false
ingress = "INGRESS_TRAFFIC_ALL"

template {
containers {
image = "us-docker.pkg.dev/cloudrun/container/hello"
resources {
limits = {
memory = "1Gi"
}
}
}
}
}
`, context)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cloudrunv2

import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// cloudRunV2ServiceResourceLimitsDiffSuppress suppresses diffs for the `cpu`
// key in the container resources.limits map when it was added by the API but
// not specified in the user's config. When only `memory` is set, the Cloud Run
// API automatically populates a default `cpu` value. Without this suppression
// the provider would produce a perpetual diff trying to clear that API-set key.
//
// Only the `cpu` key is suppressed because it is the only key the API
// auto-populates. Other keys such as `nvidia.com/gpu` must never be suppressed
// so that intentional removals (e.g. switching from GPU to non-GPU) are applied.
func cloudRunV2ServiceResourceLimitsDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
// Only suppress the auto-populated cpu key, not user-set keys like nvidia.com/gpu.
if !strings.HasSuffix(k, "limits.cpu") {
return false
}
// Suppress when the user did not set cpu (new == "") but the API populated it (old != "").
return new == "" && old != ""
}
Loading