Skip to content

Commit bc3986d

Browse files
committed
Merge commit 'bc5def9f8136003836911e78567dc8849a39be6d' into sync-main-FEATURE-BRANCH-6.0.0
* commit 'bc5def9f8136003836911e78567dc8849a39be6d': Fix test `TestAccSecurityCenterManagementOrganizationEventThreatDetectionCustomModule` (GoogleCloudPlatform#11469) Promoted labelFingerprint field to GA (GoogleCloudPlatform#11504) Revert "Prevent Dataflow options in parameters" (GoogleCloudPlatform#11485) Support Undelete for Vmwareengine Private Cloud (GoogleCloudPlatform#11480)
2 parents 93bcf85 + bc5def9 commit bc3986d

16 files changed

+356
-136
lines changed

mmv1/products/compute/GlobalAddress.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ properties:
100100
internally during updates.
101101
update_url: 'projects/{{project}}/global/addresses/{{name}}/setLabels'
102102
update_verb: :POST
103-
min_version: beta
104103
- !ruby/object:Api::Type::Enum
105104
name: 'ipVersion'
106105
description: |

mmv1/products/vmwareengine/PrivateCloud.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ autogen_async: true
4747
custom_code: !ruby/object:Provider::Terraform::CustomCode
4848
constants: templates/terraform/constants/vmwareengine_private_cloud.go.erb
4949
decoder: "templates/terraform/decoders/private_cloud.go.erb"
50+
pre_create: templates/terraform/pre_create/vmwareengine_private_cloud.go.erb
5051
pre_delete: templates/terraform/pre_delete/vmwareengine_private_cloud.go.erb
5152
post_delete: "templates/terraform/post_delete/private_cloud.go.erb"
5253
post_update: "templates/terraform/post_update/private_cloud.go.erb"

mmv1/templates/terraform/constants/vmwareengine_private_cloud.go.erb

+46
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,49 @@ func isMultiNodePrivateCloud(d *schema.ResourceData) bool {
3131
}
3232
return false
3333
}
34+
35+
func isPrivateCloudInDeletedState(config *transport_tpg.Config, d *schema.ResourceData, billingProject string, userAgent string) (bool, error) {
36+
baseurl, err := tpgresource.ReplaceVars(d, config, "{{<%=object.__product.name-%>BasePath}}<%=object.self_link_uri-%>")
37+
if err != nil {
38+
return false, err
39+
}
40+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
41+
Config: config,
42+
Method: "GET",
43+
Project: billingProject,
44+
RawURL: baseurl,
45+
UserAgent: userAgent,
46+
})
47+
if err != nil {
48+
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
49+
log.Printf("[DEBUG] No existing private cloud found")
50+
return false, nil
51+
}
52+
return false, err
53+
}
54+
// if resource exists but is marked for deletion
55+
v, ok := res["state"]
56+
if ok && v.(string) == "DELETED" {
57+
log.Printf("[DEBUG] The Private cloud exists and is marked for deletion.")
58+
return true, nil
59+
}
60+
return false, nil
61+
}
62+
63+
// Check if private cloud is absent or if it exists in a deleted state.
64+
func pollCheckForPrivateCloudAbsence(resp map[string]interface{}, respErr error) transport_tpg.PollResult {
65+
if respErr != nil {
66+
if transport_tpg.IsGoogleApiErrorWithCode(respErr, 404) {
67+
return transport_tpg.SuccessPollResult()
68+
}
69+
return transport_tpg.ErrorPollResult(respErr)
70+
}
71+
// if resource exists but is marked for deletion
72+
log.Printf("[DEBUG] Fetching state of the private cloud.")
73+
v, ok := resp["state"]
74+
if ok && v.(string) == "DELETED" {
75+
log.Printf("[DEBUG] The Private cloud has been successfully marked for delayed deletion.")
76+
return transport_tpg.SuccessPollResult()
77+
}
78+
return transport_tpg.PendingStatusPollResult("found")
79+
}

mmv1/templates/terraform/post_delete/private_cloud.go.erb

+2-9
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,11 @@ privateCloudPollRead := func(d *schema.ResourceData, meta interface{}) transport
2929
if err != nil {
3030
return res, err
3131
}
32-
// if resource exists but is marked for deletion
33-
log.Printf("[DEBUG] Fetching state of the private cloud.")
34-
v, ok := res["state"]
35-
if ok && v.(string) == "DELETED" {
36-
log.Printf("[DEBUG] The Private cloud has been successfully marked for delayed deletion.")
37-
return nil, nil
38-
}
3932
return res, nil
4033
}
4134
}
4235

43-
err = transport_tpg.PollingWaitTime(privateCloudPollRead(d, meta), transport_tpg.PollCheckForAbsence, "Deleting <%= object.name -%>", d.Timeout(schema.TimeoutDelete), 10)
36+
err = transport_tpg.PollingWaitTime(privateCloudPollRead(d, meta), pollCheckForPrivateCloudAbsence, "Deleting <%= object.name -%>", d.Timeout(schema.TimeoutDelete), 10)
4437
if err != nil {
4538
return fmt.Errorf("Error waiting to delete PrivateCloud: %s", err)
46-
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Check if the project exists in a deleted state
2+
pcMarkedForDeletion, err := isPrivateCloudInDeletedState(config, d, billingProject, userAgent)
3+
if err != nil {
4+
return fmt.Errorf("Error checking if Private Cloud exists and is marked for deletion: %s", err)
5+
}
6+
if pcMarkedForDeletion {
7+
log.Printf("[DEBUG] Private Cloud exists and is marked for deletion. Triggering UNDELETE of the Private Cloud.\n")
8+
url, err = tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}projects/{{project}}/locations/{{location}}/privateClouds/{{name}}:undelete")
9+
if err != nil {
10+
return err
11+
}
12+
obj = make(map[string]interface{})
13+
} else {
14+
log.Printf("[DEBUG] Private Cloud is not found to be marked for deletion. Triggering CREATE of the Private Cloud.\n")
15+
}

mmv1/third_party/terraform/acctest/resource_test_utils.go

+23
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
11
package acctest
22

33
import (
4+
"context"
5+
"errors"
46
"fmt"
7+
"slices"
58
"testing"
69
"time"
710

11+
tfjson "github.com/hashicorp/terraform-json"
812
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
13+
"github.com/hashicorp/terraform-plugin-testing/plancheck"
914
"github.com/hashicorp/terraform-plugin-testing/terraform"
1015
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
1116
)
1217

1318
// General test utils
1419

20+
var _ plancheck.PlanCheck = expectNoDelete{}
21+
22+
type expectNoDelete struct{}
23+
24+
func (e expectNoDelete) CheckPlan(ctx context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) {
25+
var result error
26+
for _, rc := range req.Plan.ResourceChanges {
27+
if slices.Contains(rc.Change.Actions, tfjson.ActionDelete) {
28+
result = errors.Join(result, fmt.Errorf("expected no deletion of resources, but %s has planned deletion", rc.Address))
29+
}
30+
}
31+
resp.Error = result
32+
}
33+
34+
func ExpectNoDelete() plancheck.PlanCheck {
35+
return expectNoDelete{}
36+
}
37+
1538
// TestExtractResourceAttr navigates a test's state to find the specified resource (or data source) attribute and makes the value
1639
// accessible via the attributeValue string pointer.
1740
func TestExtractResourceAttr(resourceName string, attributeName string, attributeValue *string) resource.TestCheckFunc {

mmv1/third_party/terraform/services/compute/resource_compute_global_address_test.go.erb

+84
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,48 @@ import (
77
"github.com/hashicorp/terraform-provider-google/google/acctest"
88

99
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-testing/plancheck"
1011
)
1112

13+
func TestAccComputeGlobalAddress_update(t *testing.T) {
14+
t.Parallel()
15+
16+
context := map[string]interface{}{
17+
"random_suffix": acctest.RandString(t, 10),
18+
}
19+
20+
acctest.VcrTest(t, resource.TestCase{
21+
PreCheck: func() { acctest.AccTestPreCheck(t) },
22+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
23+
CheckDestroy: testAccCheckComputeGlobalAddressDestroyProducer(t),
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccComputeGlobalAddress_update1(context),
27+
},
28+
{
29+
ResourceName: "google_compute_global_address.foobar",
30+
ImportState: true,
31+
ImportStateVerify: true,
32+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
33+
},
34+
{
35+
Config: testAccComputeGlobalAddress_update2(context),
36+
ConfigPlanChecks: resource.ConfigPlanChecks{
37+
PreApply: []plancheck.PlanCheck{
38+
acctest.ExpectNoDelete(),
39+
},
40+
},
41+
},
42+
{
43+
ResourceName: "google_compute_global_address.foobar",
44+
ImportState: true,
45+
ImportStateVerify: true,
46+
ImportStateVerifyIgnore: []string{"labels", "terraform_labels"},
47+
},
48+
},
49+
})
50+
}
51+
1252
func TestAccComputeGlobalAddress_ipv6(t *testing.T) {
1353
t.Parallel()
1454

@@ -75,3 +115,47 @@ resource "google_compute_global_address" "foobar" {
75115
}
76116
`, networkName, addressName)
77117
}
118+
119+
func testAccComputeGlobalAddress_update1(context map[string]interface{}) string {
120+
return acctest.Nprintf(`
121+
resource "google_compute_network" "foobar" {
122+
name = "tf-test-address-%{random_suffix}"
123+
}
124+
125+
resource "google_compute_global_address" "foobar" {
126+
address = "172.20.181.0"
127+
description = "Description"
128+
name = "tf-test-address-%{random_suffix}"
129+
labels = {
130+
foo = "bar"
131+
}
132+
ip_version = "IPV4"
133+
prefix_length = 24
134+
address_type = "INTERNAL"
135+
purpose = "VPC_PEERING"
136+
network = google_compute_network.foobar.self_link
137+
}
138+
`, context)
139+
}
140+
141+
func testAccComputeGlobalAddress_update2(context map[string]interface{}) string {
142+
return acctest.Nprintf(`
143+
resource "google_compute_network" "foobar" {
144+
name = "tf-test-address-%{random_suffix}"
145+
}
146+
147+
resource "google_compute_global_address" "foobar" {
148+
address = "172.20.181.0"
149+
description = "Description"
150+
name = "tf-test-address-%{random_suffix}"
151+
labels = {
152+
foo = "baz"
153+
}
154+
ip_version = "IPV4"
155+
prefix_length = 24
156+
address_type = "INTERNAL"
157+
purpose = "VPC_PEERING"
158+
network = google_compute_network.foobar.self_link
159+
}
160+
`, context)
161+
}

mmv1/third_party/terraform/services/dataflow/go/resource_dataflow_flex_template_job.go.tmpl

+43-55
Original file line numberDiff line numberDiff line change
@@ -310,23 +310,38 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac
310310
func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_tpg.Config) (dataflow.FlexTemplateRuntimeEnvironment, map[string]string, error) {
311311

312312
updatedParameters := tpgresource.ExpandStringMap(d, "parameters")
313-
if err := hasIllegalParametersErr(d); err != nil {
314-
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, err
315-
}
316313

317314
additionalExperiments := tpgresource.ConvertStringSet(d.Get("additional_experiments").(*schema.Set))
318315

319316
var autoscalingAlgorithm string
320317
autoscalingAlgorithm, updatedParameters = dataflowFlexJobTypeTransferVar("autoscaling_algorithm", "autoscalingAlgorithm", updatedParameters, d)
321318

322-
numWorkers, err := parseInt64("num_workers", d)
323-
if err != nil {
324-
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, err
319+
var numWorkers int
320+
if p, ok := d.GetOk("parameters.numWorkers"); ok {
321+
number, err := strconv.Atoi(p.(string))
322+
if err != nil {
323+
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.numWorkers must have a valid integer assigned to it, current value is %s", p.(string))
324+
}
325+
delete(updatedParameters, "numWorkers")
326+
numWorkers = number
327+
} else {
328+
if v, ok := d.GetOk("num_workers"); ok {
329+
numWorkers = v.(int)
330+
}
325331
}
326332

327-
maxNumWorkers, err := parseInt64("max_workers", d)
328-
if err != nil {
329-
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, err
333+
var maxNumWorkers int
334+
if p, ok := d.GetOk("parameters.maxNumWorkers"); ok {
335+
number, err := strconv.Atoi(p.(string))
336+
if err != nil {
337+
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string))
338+
}
339+
delete(updatedParameters, "maxNumWorkers")
340+
maxNumWorkers = number
341+
} else {
342+
if v, ok := d.GetOk("max_workers"); ok {
343+
maxNumWorkers = v.(int)
344+
}
330345
}
331346

332347
network, updatedParameters := dataflowFlexJobTypeTransferVar("network", "network", updatedParameters, d)
@@ -345,10 +360,23 @@ func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_t
345360

346361
ipConfiguration, updatedParameters := dataflowFlexJobTypeTransferVar("ip_configuration", "ipConfiguration", updatedParameters, d)
347362

348-
enableStreamingEngine, err := parseBool("enable_streaming_engine", d)
349-
if err != nil {
350-
return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, err
351-
}
363+
var enableStreamingEngine bool
364+
if p, ok := d.GetOk("parameters.enableStreamingEngine"); ok {
365+
delete(updatedParameters, "enableStreamingEngine")
366+
e := strings.ToLower(p.(string))
367+
switch e {
368+
case "true":
369+
enableStreamingEngine = true
370+
case "false":
371+
enableStreamingEngine = false
372+
default:
373+
return dataflow.FlexTemplateRuntimeEnvironment{}, nil, fmt.Errorf("error when handling parameters.enableStreamingEngine value: expected value to be true or false but got value `%s`", e)
374+
}
375+
} else {
376+
if v, ok := d.GetOk("enable_streaming_engine"); ok {
377+
enableStreamingEngine = v.(bool)
378+
}
379+
}
352380

353381
sdkContainerImage, updatedParameters := dataflowFlexJobTypeTransferVar("sdk_container_image", "sdkContainerImage", updatedParameters, d)
354382

@@ -357,8 +385,8 @@ func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_t
357385
env := dataflow.FlexTemplateRuntimeEnvironment{
358386
AdditionalUserLabels: tpgresource.ExpandStringMap(d, "effective_labels"),
359387
AutoscalingAlgorithm: autoscalingAlgorithm,
360-
NumWorkers: numWorkers,
361-
MaxWorkers: maxNumWorkers,
388+
NumWorkers: int64(numWorkers),
389+
MaxWorkers: int64(maxNumWorkers),
362390
Network: network,
363391
ServiceAccountEmail: serviceAccountEmail,
364392
Subnetwork: subnetwork,
@@ -812,44 +840,4 @@ func dataflowFlexJobTypeParameterOverride(ename, pname string, d *schema.Resourc
812840
return nil
813841
}
814842

815-
func hasIllegalParametersErr(d *schema.ResourceData) error {
816-
pKey := "parameters"
817-
errFmt := "%s must not include Dataflow options, found: %s"
818-
for k := range ResourceDataflowFlexTemplateJob().Schema {
819-
if _, notOk := d.GetOk(fmt.Sprintf("%s.%s", pKey, k)); notOk {
820-
return fmt.Errorf(errFmt, pKey, k)
821-
}
822-
kk := tpgresource.SnakeToPascalCase(k)
823-
kk = strings.ToLower(kk)
824-
if _, notOk := d.GetOk(fmt.Sprintf("%s.%s", pKey, kk)); notOk {
825-
return fmt.Errorf(errFmt, pKey, kk)
826-
}
827-
}
828-
return nil
829-
}
830-
831-
func parseInt64(name string, d *schema.ResourceData) (int64, error) {
832-
v, ok := d.GetOk(name)
833-
if !ok {
834-
return 0, nil
835-
}
836-
vv, err := strconv.ParseInt(fmt.Sprint(v), 10, 64)
837-
if err != nil {
838-
return 0, fmt.Errorf("illegal value assigned to %s, got: %s", name, v)
839-
}
840-
return vv, nil
841-
}
842-
843-
func parseBool(name string, d *schema.ResourceData) (bool, error) {
844-
v, ok := d.GetOk(name)
845-
if !ok {
846-
return false, nil
847-
}
848-
vv, err := strconv.ParseBool(fmt.Sprint(v))
849-
if err != nil {
850-
return false, fmt.Errorf("illegal value assigned to %s, got: %s", name, v)
851-
}
852-
return vv, nil
853-
}
854-
855843
{{ end }}

mmv1/third_party/terraform/services/dataflow/go/resource_dataflow_flex_template_job_test.go.tmpl

+10-2
Original file line numberDiff line numberDiff line change
@@ -581,12 +581,20 @@ func TestAccDataflowFlexTemplateJob_enableStreamingEngine(t *testing.T) {
581581
CheckDestroy: testAccCheckDataflowJobDestroyProducer(t),
582582
Steps: []resource.TestStep{
583583
{
584-
Config: testAccDataflowFlexTemplateJob_enableStreamingEngine_param(job, bucket, topic),
585-
ExpectError: regexp.MustCompile("must not include Dataflow options"),
584+
Config: testAccDataflowFlexTemplateJob_enableStreamingEngine_param(job, bucket, topic),
585+
Check: resource.ComposeTestCheckFunc(
586+
// Is set
587+
resource.TestCheckResourceAttr("google_dataflow_flex_template_job.flex_job", "parameters.enableStreamingEngine", "true"),
588+
// Is not set
589+
resource.TestCheckNoResourceAttr("google_dataflow_flex_template_job.flex_job", "enable_streaming_engine"),
590+
),
586591
},
587592
{
588593
Config: testAccDataflowFlexTemplateJob_enableStreamingEngine_field(job, bucket, topic),
589594
Check: resource.ComposeTestCheckFunc(
595+
// Now is unset
596+
resource.TestCheckNoResourceAttr("google_dataflow_flex_template_job.flex_job", "parameters.enableStreamingEngine"),
597+
// Now is set
590598
resource.TestCheckResourceAttr("google_dataflow_flex_template_job.flex_job", "enable_streaming_engine", "true"),
591599
),
592600
},

0 commit comments

Comments
 (0)