diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook.go b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook.go index 2161cc78555e..0e5477303694 100644 --- a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook.go +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook.go @@ -102,7 +102,8 @@ func resourceApigeeFlowhookCreate(d *schema.ResourceData, meta interface{}) erro continue_on_errorProp, err := expandApigeeFlowhookContinueOnError(d.Get("continue_on_error"), d, config) if err != nil { return err - } else if v, ok := d.GetOkExists("continue_on_error"); !tpgresource.IsEmptyValue(reflect.ValueOf(continue_on_errorProp)) && (ok || !reflect.DeepEqual(v, continue_on_errorProp)) { + } else if v, ok := d.GetOkExists("continue_on_error"); ok || !reflect.DeepEqual(v, continue_on_errorProp) { + // Preserve explicitly configured false values when send_empty_value behavior is desired. obj["continueOnError"] = continue_on_errorProp } diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_meta.yaml b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_meta.yaml index d14117eb09f0..0e00935ffec6 100644 --- a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_meta.yaml +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_meta.yaml @@ -5,6 +5,7 @@ api_version: 'v1' api_resource_type_kind: 'FlowHook' fields: - api_field: 'continueOnError' + send_empty_value: true - api_field: 'description' - field: 'environment' - api_field: 'flowHookPoint' diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_test.go b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_test.go index 76b615867862..b8f3f3cae7b0 100644 --- a/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_test.go +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_flowhook_test.go @@ -23,9 +23,10 @@ func TestAccApigeeFlowhook_apigeeFlowhookTestExample(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "org_id": envvar.GetTestOrgFromEnv(t), - "billing_account": envvar.GetTestBillingAccountFromEnv(t), - "random_suffix": acctest.RandString(t, 10), + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "continue_on_error": true, } acctest.VcrTest(t, resource.TestCase{ @@ -49,6 +50,42 @@ func TestAccApigeeFlowhook_apigeeFlowhookTestExample(t *testing.T) { }) } +func TestAccApigeeFlowhook_continueOnErrorFalse(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "continue_on_error": false, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckApigeeFlowhookDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApigeeFlowhook_apigeeFlowhookTestExample(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_apigee_flowhook.flowhook_test", "continue_on_error", "false"), + testAccCheckApigeeFlowhookContinueOnError(t, "google_apigee_flowhook.flowhook_test", false), + ), + }, + { + ResourceName: "google_apigee_flowhook.flowhook_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{}, + }, + }, + }) +} + func testAccApigeeFlowhook_apigeeFlowhookTestExample(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_project" "project" { @@ -140,11 +177,55 @@ resource "google_apigee_flowhook" "flowhook_test" { flow_hook_point = "PreProxyFlowHook" sharedflow = google_apigee_sharedflow.test_apigee_sharedflow.name description = "test flowhook" - continue_on_error = true + continue_on_error = %{continue_on_error} } `, context) } +// Verifies continue_on_error is correctly persisted when explicitly set. +// Verify continueOnError is returned by the API with the expected value. +func testAccCheckApigeeFlowhookContinueOnError(t *testing.T, resourceName string, expected bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, transport_tpg.BaseUrl(apigee.Product, config)+"organizations/{{org_id}}/environments/{{environment}}/flowhooks/{{flow_hook_point}}") + if err != nil { + return err + } + + billingProject := "" + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return fmt.Errorf("error reading flowhook at %s: %s", url, err) + } + + got, ok := res["continueOnError"].(bool) + if !ok { + return fmt.Errorf("continueOnError missing or not a bool in API response for %s", url) + } + if got != expected { + return fmt.Errorf("continueOnError = %t, want %t at %s", got, expected, url) + } + + return nil + } +} + func testAccCheckApigeeFlowhookDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources {