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

Add gcs volume type to Cloud Run v2 beta provider #7102

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/9746.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
cloudrunv2: support mounting Cloud Storage buckets using GCSFuse in Jobs (beta).
```
85 changes: 85 additions & 0 deletions google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,26 @@ A duration in seconds with up to nine fractional digits, ending with 's'. Exampl
},
},
},
"gcs": {
Type: schema.TypeList,
Optional: true,
Description: `Cloud Storage bucket mounted as a volume using GCSFuse. This feature requires the launch stage to be set to ALPHA or BETA.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"bucket": {
Type: schema.TypeString,
Required: true,
Description: `Name of the cloud storage bucket to back the volume. The resource service account must have permission to access the bucket.`,
},
"read_only": {
Type: schema.TypeBool,
Optional: true,
Description: `If true, mount this volume as read-only in all mounts. If false, mount this volume as read-write.`,
},
},
},
},
"secret": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -1551,6 +1571,7 @@ func flattenCloudRunV2JobTemplateTemplateVolumes(v interface{}, d *schema.Resour
"secret": flattenCloudRunV2JobTemplateTemplateVolumesSecret(original["secret"], d, config),
"cloud_sql_instance": flattenCloudRunV2JobTemplateTemplateVolumesCloudSqlInstance(original["cloudSqlInstance"], d, config),
"empty_dir": flattenCloudRunV2JobTemplateTemplateVolumesEmptyDir(original["emptyDir"], d, config),
"gcs": flattenCloudRunV2JobTemplateTemplateVolumesGcs(original["gcs"], d, config),
})
}
return transformed
Expand Down Expand Up @@ -1682,6 +1703,29 @@ func flattenCloudRunV2JobTemplateTemplateVolumesEmptyDirSizeLimit(v interface{},
return v
}

func flattenCloudRunV2JobTemplateTemplateVolumesGcs(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["bucket"] =
flattenCloudRunV2JobTemplateTemplateVolumesGcsBucket(original["bucket"], d, config)
transformed["read_only"] =
flattenCloudRunV2JobTemplateTemplateVolumesGcsReadOnly(original["readOnly"], d, config)
return []interface{}{transformed}
}
func flattenCloudRunV2JobTemplateTemplateVolumesGcsBucket(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenCloudRunV2JobTemplateTemplateVolumesGcsReadOnly(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenCloudRunV2JobTemplateTemplateTimeout(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
Expand Down Expand Up @@ -2497,6 +2541,13 @@ func expandCloudRunV2JobTemplateTemplateVolumes(v interface{}, d tpgresource.Ter
transformed["emptyDir"] = transformedEmptyDir
}

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

req = append(req, transformed)
}
return req, nil
Expand Down Expand Up @@ -2652,6 +2703,40 @@ func expandCloudRunV2JobTemplateTemplateVolumesEmptyDirSizeLimit(v interface{},
return v, nil
}

func expandCloudRunV2JobTemplateTemplateVolumesGcs(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{})

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

transformedReadOnly, err := expandCloudRunV2JobTemplateTemplateVolumesGcsReadOnly(original["read_only"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedReadOnly); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["readOnly"] = transformedReadOnly
}

return transformed, nil
}

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

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

func expandCloudRunV2JobTemplateTemplateTimeout(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,89 @@ func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context map[string]in
}
`, context)
}

func TestAccCloudRunV2Job_cloudrunv2JobWithGcsUpdate(t *testing.T) {
t.Parallel()

jobName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10))
context := map[string]interface{}{
"job_name": jobName,
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context),
},
{
ResourceName: "google_cloud_run_v2_job.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "launch_stage"},
},
{
Config: testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context),
},
{
ResourceName: "google_cloud_run_v2_job.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "launch_stage"},
},
},
})
}

func testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_job" "default" {
name = "%{job_name}"
location = "us-central1"
launch_stage = "BETA"
template {
template {
containers {
image = "us-docker.pkg.dev/cloudrun/container/job"
}
}
}

lifecycle {
ignore_changes = [
launch_stage,
]
}
}
`, context)
}

func testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_job" "default" {
name = "%{job_name}"
location = "us-central1"
launch_stage = "BETA"
template {
template {
containers {
image = "us-docker.pkg.dev/cloudrun/container/job"
volume_mounts {
name = "gcs"
mount_path = "/mnt/gcs"
}
}
volumes {
name = "gcs"
gcs {
bucket = "gcp-public-data-landsat"
read_only = true
}
}
}
}
}
`, context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ A duration in seconds with up to nine fractional digits, ending with 's'. Exampl
"gcs": {
Type: schema.TypeList,
Optional: true,
Description: `Represents a GCS Bucket mounted as a volume.`,
Description: `Cloud Storage bucket mounted as a volume using GCSFuse. This feature is only supported in the gen2 execution environment and requires launch-stage to be set to ALPHA or BETA.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ resource "google_service_account" "service_account" {
}
`, context)
}

func testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_cloud_run_v2_service" "default" {
Expand Down Expand Up @@ -209,7 +208,106 @@ resource "google_compute_network" "custom_test" {
}
`, context)
}
func TestAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(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_cloudrunv2ServiceGcsVolume(context),
},
{
ResourceName: "google_cloud_run_v2_service.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"},
},
},
})
}

func testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(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 {
labels = {
label-1 = "value-1"
}
timeout = "300s"
service_account = google_service_account.service_account.email
execution_environment = "EXECUTION_ENVIRONMENT_GEN2"
scaling {
max_instance_count = 3
min_instance_count = 1
}
annotations = {
generated-by = "magic-modules"
}
volumes {
name = "gcs"
gcs {
bucket = "gcp-public-data-landsat"
read_only = true
}
}
containers {
name = "container-1"
image = "us-docker.pkg.dev/cloudrun/container/hello"
env {
name = "SOURCE"
value = "remote"
}
env {
name = "TARGET"
value = "home"
}
ports {
name = "h2c"
container_port = 8080
}
volume_mounts {
name = "gcs"
mount_path = "/mnt/landsat"
}
resources {
cpu_idle = true
startup_cpu_boost = true
limits = {
cpu = "4"
memory = "2Gi"
}
}
}
session_affinity = false
}
}

resource "google_service_account" "service_account" {
account_id = "tf-test-my-account%{random_suffix}"
display_name = "Test Service Account"
}
`, context)
}
func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) {
t.Parallel()

Expand Down
15 changes: 15 additions & 0 deletions website/docs/r/cloud_run_v2_job.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,11 @@ The following arguments are supported:
Ephemeral storage used as a shared volume.
Structure is [documented below](#nested_empty_dir).

* `gcs` -
(Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
Cloud Storage bucket mounted as a volume using GCSFuse. This feature requires the launch stage to be set to ALPHA or BETA.
Structure is [documented below](#nested_gcs).


<a name="nested_secret"></a>The `secret` block supports:

Expand Down Expand Up @@ -605,6 +610,16 @@ The following arguments are supported:
(Optional)
Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir.

<a name="nested_gcs"></a>The `gcs` block supports:

* `bucket` -
(Required)
Name of the cloud storage bucket to back the volume. The resource service account must have permission to access the bucket.

* `read_only` -
(Optional)
If true, mount this volume as read-only in all mounts. If false, mount this volume as read-write.

<a name="nested_vpc_access"></a>The `vpc_access` block supports:

* `connector` -
Expand Down
2 changes: 1 addition & 1 deletion website/docs/r/cloud_run_v2_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ The following arguments are supported:

* `gcs` -
(Optional)
Represents a GCS Bucket mounted as a volume.
Cloud Storage bucket mounted as a volume using GCSFuse. This feature is only supported in the gen2 execution environment and requires launch-stage to be set to ALPHA or BETA.
Structure is [documented below](#nested_gcs).

* `nfs` -
Expand Down
Loading