Skip to content

Commit b2f7d13

Browse files
Add support for GPU fields in Cloud Run v2 Job (GA) (#14423) (#23586)
[upstream:39be39fee22bcda170fd422fb86a76f26d2c90f4] Signed-off-by: Modular Magician <[email protected]>
1 parent 0b6c1f8 commit b2f7d13

File tree

6 files changed

+184
-2
lines changed

6 files changed

+184
-2
lines changed

.changelog/14423.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
cloudrunv2: promoted field `node_selector` in `google_cloud_run_v2_job` resource to GA
3+
```

google/services/cloudrunv2/resource_cloud_run_v2_job.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,21 @@ Must be smaller than periodSeconds.`,
344344
Description: `Number of retries allowed per Task, before marking this Task failed. Defaults to 3. Minimum value is 0.`,
345345
Default: 3,
346346
},
347+
"node_selector": {
348+
Type: schema.TypeList,
349+
Optional: true,
350+
Description: `Node Selector describes the hardware requirements of the resources.`,
351+
MaxItems: 1,
352+
Elem: &schema.Resource{
353+
Schema: map[string]*schema.Schema{
354+
"accelerator": {
355+
Type: schema.TypeString,
356+
Required: true,
357+
Description: `The GPU to attach to an instance. See https://cloud.google.com/run/docs/configuring/jobs/gpu for configuring GPU.`,
358+
},
359+
},
360+
},
361+
},
347362
"service_account": {
348363
Type: schema.TypeString,
349364
Computed: true,
@@ -1564,6 +1579,8 @@ func flattenCloudRunV2JobTemplateTemplate(v interface{}, d *schema.ResourceData,
15641579
flattenCloudRunV2JobTemplateTemplateVpcAccess(original["vpcAccess"], d, config)
15651580
transformed["max_retries"] =
15661581
flattenCloudRunV2JobTemplateTemplateMaxRetries(original["maxRetries"], d, config)
1582+
transformed["node_selector"] =
1583+
flattenCloudRunV2JobTemplateTemplateNodeSelector(original["nodeSelector"], d, config)
15671584
return []interface{}{transformed}
15681585
}
15691586
func flattenCloudRunV2JobTemplateTemplateContainers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
@@ -2273,6 +2290,23 @@ func flattenCloudRunV2JobTemplateTemplateMaxRetries(v interface{}, d *schema.Res
22732290
return v // let terraform core handle it otherwise
22742291
}
22752292

2293+
func flattenCloudRunV2JobTemplateTemplateNodeSelector(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
2294+
if v == nil {
2295+
return nil
2296+
}
2297+
original := v.(map[string]interface{})
2298+
if len(original) == 0 {
2299+
return nil
2300+
}
2301+
transformed := make(map[string]interface{})
2302+
transformed["accelerator"] =
2303+
flattenCloudRunV2JobTemplateTemplateNodeSelectorAccelerator(original["accelerator"], d, config)
2304+
return []interface{}{transformed}
2305+
}
2306+
func flattenCloudRunV2JobTemplateTemplateNodeSelectorAccelerator(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
2307+
return v
2308+
}
2309+
22762310
func flattenCloudRunV2JobObservedGeneration(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
22772311
return v
22782312
}
@@ -2669,6 +2703,13 @@ func expandCloudRunV2JobTemplateTemplate(v interface{}, d tpgresource.TerraformR
26692703
transformed["maxRetries"] = transformedMaxRetries
26702704
}
26712705

2706+
transformedNodeSelector, err := expandCloudRunV2JobTemplateTemplateNodeSelector(original["node_selector"], d, config)
2707+
if err != nil {
2708+
return nil, err
2709+
} else if val := reflect.ValueOf(transformedNodeSelector); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2710+
transformed["nodeSelector"] = transformedNodeSelector
2711+
}
2712+
26722713
return transformed, nil
26732714
}
26742715

@@ -3612,6 +3653,29 @@ func expandCloudRunV2JobTemplateTemplateMaxRetries(v interface{}, d tpgresource.
36123653
return v, nil
36133654
}
36143655

3656+
func expandCloudRunV2JobTemplateTemplateNodeSelector(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
3657+
l := v.([]interface{})
3658+
if len(l) == 0 || l[0] == nil {
3659+
return nil, nil
3660+
}
3661+
raw := l[0]
3662+
original := raw.(map[string]interface{})
3663+
transformed := make(map[string]interface{})
3664+
3665+
transformedAccelerator, err := expandCloudRunV2JobTemplateTemplateNodeSelectorAccelerator(original["accelerator"], d, config)
3666+
if err != nil {
3667+
return nil, err
3668+
} else if val := reflect.ValueOf(transformedAccelerator); val.IsValid() && !tpgresource.IsEmptyValue(val) {
3669+
transformed["accelerator"] = transformedAccelerator
3670+
}
3671+
3672+
return transformed, nil
3673+
}
3674+
3675+
func expandCloudRunV2JobTemplateTemplateNodeSelectorAccelerator(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
3676+
return v, nil
3677+
}
3678+
36153679
func expandCloudRunV2JobEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
36163680
if v == nil {
36173681
return map[string]string{}, nil

google/services/cloudrunv2/resource_cloud_run_v2_job_generated_meta.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ fields:
7777
- field: 'template.template.encryption_key'
7878
- field: 'template.template.execution_environment'
7979
- field: 'template.template.max_retries'
80+
- field: 'template.template.node_selector.accelerator'
8081
- field: 'template.template.service_account'
8182
- field: 'template.template.timeout'
8283
- field: 'template.template.volumes.cloud_sql_instance.instances'

google/services/cloudrunv2/resource_cloud_run_v2_job_generated_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,52 @@ resource "google_cloud_run_v2_job" "default" {
534534
`, context)
535535
}
536536

537+
func TestAccCloudRunV2Job_cloudrunv2JobGpuExample(t *testing.T) {
538+
t.Parallel()
539+
540+
context := map[string]interface{}{
541+
"random_suffix": acctest.RandString(t, 10),
542+
}
543+
544+
acctest.VcrTest(t, resource.TestCase{
545+
PreCheck: func() { acctest.AccTestPreCheck(t) },
546+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
547+
CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t),
548+
Steps: []resource.TestStep{
549+
{
550+
Config: testAccCloudRunV2Job_cloudrunv2JobGpuExample(context),
551+
},
552+
{
553+
ResourceName: "google_cloud_run_v2_job.default",
554+
ImportState: true,
555+
ImportStateVerify: true,
556+
ImportStateVerifyIgnore: []string{"annotations", "deletion_protection", "labels", "location", "name", "terraform_labels"},
557+
},
558+
},
559+
})
560+
}
561+
562+
func testAccCloudRunV2Job_cloudrunv2JobGpuExample(context map[string]interface{}) string {
563+
return acctest.Nprintf(`
564+
resource "google_cloud_run_v2_job" "default" {
565+
name = "tf-test-cloudrun-job%{random_suffix}"
566+
location = "us-central1"
567+
deletion_protection = false
568+
launch_stage = "BETA"
569+
template {
570+
template {
571+
containers {
572+
image = "us-docker.pkg.dev/cloudrun/container/job"
573+
}
574+
node_selector {
575+
accelerator = "nvidia-l4"
576+
}
577+
}
578+
}
579+
}
580+
`, context)
581+
}
582+
537583
func testAccCheckCloudRunV2JobDestroyProducer(t *testing.T) func(s *terraform.State) error {
538584
return func(s *terraform.State) error {
539585
for name, rs := range s.RootModule().Resources {

google/services/cloudrunv2/resource_cloud_run_v2_job_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,3 +891,72 @@ resource "google_cloud_run_v2_job" "default" {
891891
}
892892
`, context)
893893
}
894+
895+
func TestAccCloudRunV2Job_cloudrunv2JobWithGpuUpdate(t *testing.T) {
896+
acctest.SkipIfVcr(t)
897+
t.Parallel()
898+
899+
jobName := fmt.Sprintf("tf-test-cloudrun-job-gpu%s", acctest.RandString(t, 10))
900+
context := map[string]interface{}{
901+
"job_name": jobName,
902+
}
903+
904+
acctest.VcrTest(t, resource.TestCase{
905+
PreCheck: func() { acctest.AccTestPreCheck(t) },
906+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
907+
CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t),
908+
Steps: []resource.TestStep{
909+
{
910+
Config: testAccCloudRunV2Job_cloudrunv2BasicJob(context),
911+
},
912+
{
913+
ResourceName: "google_cloud_run_v2_job.default",
914+
ImportState: true,
915+
ImportStateVerify: true,
916+
ImportStateVerifyIgnore: []string{"location", "launch_stage", "deletion_protection"},
917+
},
918+
{
919+
Config: testAccCloudRunV2Job_cloudrunv2JobWithGpu(context),
920+
},
921+
{
922+
ResourceName: "google_cloud_run_v2_job.default",
923+
ImportState: true,
924+
ImportStateVerify: true,
925+
ImportStateVerifyIgnore: []string{"location", "launch_stage", "deletion_protection"},
926+
},
927+
},
928+
})
929+
}
930+
931+
func testAccCloudRunV2Job_cloudrunv2JobWithGpu(context map[string]interface{}) string {
932+
return acctest.Nprintf(`
933+
resource "google_cloud_run_v2_job" "default" {
934+
name = "%{job_name}"
935+
location = "us-central1"
936+
launch_stage = "BETA"
937+
deletion_protection = false
938+
template {
939+
template {
940+
containers {
941+
image = "us-docker.pkg.dev/cloudrun/container/job"
942+
resources {
943+
limits = {
944+
"cpu" = "4"
945+
"memory" = "16Gi"
946+
"nvidia.com/gpu" = "1"
947+
}
948+
}
949+
}
950+
node_selector {
951+
accelerator = "nvidia-l4"
952+
}
953+
}
954+
}
955+
lifecycle {
956+
ignore_changes = [
957+
launch_stage,
958+
]
959+
}
960+
}
961+
`, context)
962+
}

website/docs/r/cloud_run_v2_job.html.markdown

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ resource "google_cloud_run_v2_job" "default" {
407407

408408
```hcl
409409
resource "google_cloud_run_v2_job" "default" {
410-
provider = google-beta
411410
name = "cloudrun-job"
412411
location = "us-central1"
413412
deletion_protection = false
@@ -575,7 +574,7 @@ When the field is set to false, deleting the job is allowed.
575574
Number of retries allowed per Task, before marking this Task failed. Defaults to 3. Minimum value is 0.
576575

577576
* `node_selector` -
578-
(Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html))
577+
(Optional)
579578
Node Selector describes the hardware requirements of the resources.
580579
Structure is [documented below](#nested_template_template_node_selector).
581580

0 commit comments

Comments
 (0)