Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support service-level min instances in Cloud Run v2 services. #7053

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
3 changes: 3 additions & 0 deletions .changelog/10083.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
cloudrunv2: added support for `scaling.min_instance_count` in `google_cloud_run_v2_service`.
```
83 changes: 83 additions & 0 deletions google-beta/services/cloudrunv2/resource_cloud_run_v2_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,21 @@ If no value is specified, GA is assumed. Set the launch stage to a preview stage

For example, if ALPHA is provided as input, but only BETA and GA-level features are used, this field will be BETA on output. Possible values: ["UNIMPLEMENTED", "PRELAUNCH", "EARLY_ACCESS", "ALPHA", "BETA", "GA", "DEPRECATED"]`,
},
"scaling": {
Type: schema.TypeList,
Optional: true,
Description: `Scaling settings that apply to the whole service`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"min_instance_count": {
Type: schema.TypeInt,
Optional: true,
Description: `Minimum number of instances for the service, to be divided among all revisions receiving traffic.`,
},
},
},
},
"traffic": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -1176,6 +1191,12 @@ func resourceCloudRunV2ServiceCreate(d *schema.ResourceData, meta interface{}) e
} else if v, ok := d.GetOkExists("custom_audiences"); !tpgresource.IsEmptyValue(reflect.ValueOf(customAudiencesProp)) && (ok || !reflect.DeepEqual(v, customAudiencesProp)) {
obj["customAudiences"] = customAudiencesProp
}
scalingProp, err := expandCloudRunV2ServiceScaling(d.Get("scaling"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("scaling"); !tpgresource.IsEmptyValue(reflect.ValueOf(scalingProp)) && (ok || !reflect.DeepEqual(v, scalingProp)) {
obj["scaling"] = scalingProp
}
templateProp, err := expandCloudRunV2ServiceTemplate(d.Get("template"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -1356,6 +1377,9 @@ func resourceCloudRunV2ServiceRead(d *schema.ResourceData, meta interface{}) err
if err := d.Set("custom_audiences", flattenCloudRunV2ServiceCustomAudiences(res["customAudiences"], d, config)); err != nil {
return fmt.Errorf("Error reading Service: %s", err)
}
if err := d.Set("scaling", flattenCloudRunV2ServiceScaling(res["scaling"], d, config)); err != nil {
return fmt.Errorf("Error reading Service: %s", err)
}
if err := d.Set("template", flattenCloudRunV2ServiceTemplate(res["template"], d, config)); err != nil {
return fmt.Errorf("Error reading Service: %s", err)
}
Expand Down Expand Up @@ -1460,6 +1484,12 @@ func resourceCloudRunV2ServiceUpdate(d *schema.ResourceData, meta interface{}) e
} else if v, ok := d.GetOkExists("custom_audiences"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, customAudiencesProp)) {
obj["customAudiences"] = customAudiencesProp
}
scalingProp, err := expandCloudRunV2ServiceScaling(d.Get("scaling"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("scaling"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, scalingProp)) {
obj["scaling"] = scalingProp
}
templateProp, err := expandCloudRunV2ServiceTemplate(d.Get("template"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -1706,6 +1736,36 @@ func flattenCloudRunV2ServiceCustomAudiences(v interface{}, d *schema.ResourceDa
return v
}

func flattenCloudRunV2ServiceScaling(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["min_instance_count"] =
flattenCloudRunV2ServiceScalingMinInstanceCount(original["minInstanceCount"], d, config)
return []interface{}{transformed}
}
func flattenCloudRunV2ServiceScalingMinInstanceCount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
return intVal
}
}

// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}

return v // let terraform core handle it otherwise
}

func flattenCloudRunV2ServiceTemplate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
Expand Down Expand Up @@ -3075,6 +3135,29 @@ func expandCloudRunV2ServiceCustomAudiences(v interface{}, d tpgresource.Terrafo
return v, nil
}

func expandCloudRunV2ServiceScaling(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedMinInstanceCount, err := expandCloudRunV2ServiceScalingMinInstanceCount(original["min_instance_count"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedMinInstanceCount); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["minInstanceCount"] = transformedMinInstanceCount
}

return transformed, nil
}

func expandCloudRunV2ServiceScalingMinInstanceCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandCloudRunV2ServiceTemplate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,104 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceAttributionLabel(t *testing.T) {
})
}

func TestAccCloudRunV2Service_cloudrunv2ServiceWithServiceMinInstances(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_cloudrunv2ServiceWithMinInstances(context),
},
{
ResourceName: "google_cloud_run_v2_service.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"},
},
{
Config: testAccCloudRunV2Service_cloudrunv2ServiceWithNoMinInstances(context),
},
{
ResourceName: "google_cloud_run_v2_service.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"},
},
},
})
}

func testAccCloudRunV2Service_cloudrunv2ServiceWithNoMinInstances(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_service" "default" {
name = "tf-test-cloudrun-service%{random_suffix}"
description = "description creating"
location = "us-central1"
launch_stage = "BETA"
annotations = {
generated-by = "magic-modules"
}
ingress = "INGRESS_TRAFFIC_ALL"
labels = {
label-1 = "value-1"
}
client = "client-1"
client_version = "client-version-1"
template {
containers {
name = "container-1"
image = "us-docker.pkg.dev/cloudrun/container/hello"
}
}
lifecycle {
ignore_changes = [
launch_stage,
]
}
}

`, context)
}
func testAccCloudRunV2Service_cloudrunv2ServiceWithMinInstances(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_service" "default" {
name = "tf-test-cloudrun-service%{random_suffix}"
description = "description creating"
location = "us-central1"
launch_stage = "BETA"
annotations = {
generated-by = "magic-modules"
}
ingress = "INGRESS_TRAFFIC_ALL"
labels = {
label-1 = "value-1"
}
client = "client-1"
client_version = "client-version-1"
scaling {
min_instance_count = 1
}
template {
containers {
name = "container-1"
image = "us-docker.pkg.dev/cloudrun/container/hello"
}
}
lifecycle {
ignore_changes = [
launch_stage,
]
}
}

`, context)
}

func testAccCloudRunV2Service_cloudrunv2ServiceWithAttributionLabel(context map[string]interface{}) string {
return acctest.Nprintf(`
provider "google" {
Expand Down
11 changes: 11 additions & 0 deletions website/docs/r/cloud_run_v2_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,11 @@ The following arguments are supported:
One or more custom audiences that you want this service to support. Specify each custom audience as the full URL in a string. The custom audiences are encoded in the token and used to authenticate requests.
For more information, see https://cloud.google.com/run/docs/configuring/custom-audiences.

* `scaling` -
(Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
Scaling settings that apply to the whole service
Structure is [documented below](#nested_scaling).

* `traffic` -
(Optional)
Specifies how to distribute traffic over a collection of Revisions belonging to the Service. If traffic is empty or not provided, defaults to 100% traffic to the latest Ready Revision.
Expand All @@ -1082,6 +1087,12 @@ The following arguments are supported:
(Optional)
If True, indicates to use the default project's binary authorization policy. If False, binary authorization will be disabled.

<a name="nested_scaling"></a>The `scaling` block supports:

* `min_instance_count` -
(Optional)
Minimum number of instances for the service, to be divided among all revisions receiving traffic.

<a name="nested_traffic"></a>The `traffic` block supports:

* `type` -
Expand Down
Loading