From ea07e4a34a0a00019b12aaf85de3ffd093fd7975 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Tue, 21 Apr 2020 10:57:52 -0700 Subject: [PATCH] Add transformation of SQL DB read error so handlenotfound works --- overrides/terraform/resource_override.rb | 8 +++++++- products/sql/terraform.yaml | 1 + templates/terraform/resource.erb | 4 ++++ third_party/terraform/utils/sql_utils.go | 26 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 third_party/terraform/utils/sql_utils.go diff --git a/overrides/terraform/resource_override.rb b/overrides/terraform/resource_override.rb index b009b7e2b5bc..e3639962df60 100644 --- a/overrides/terraform/resource_override.rb +++ b/overrides/terraform/resource_override.rb @@ -75,7 +75,12 @@ def self.attributes # This enables resources that get their project via a reference to a different resource # instead of a project field to use User Project Overrides - :supports_indirect_user_project_override + :supports_indirect_user_project_override, + + # Function to transform a read error so that handleNotFound recognises + # it as a 404. This should be added as a handwritten fn that takes in + # an error and returns one. + :read_error_transform ] end @@ -108,6 +113,7 @@ def validate check :skip_sweeper, type: :boolean, default: false check :skip_delete, type: :boolean, default: false check :supports_indirect_user_project_override, type: :boolean, default: false + check :read_error_transform, type: String end def apply(resource) diff --git a/products/sql/terraform.yaml b/products/sql/terraform.yaml index 9d64768e49be..e0cac2542390 100644 --- a/products/sql/terraform.yaml +++ b/products/sql/terraform.yaml @@ -16,6 +16,7 @@ client_name: 'SqlAdmin' overrides: !ruby/object:Overrides::ResourceOverrides Database: !ruby/object:Overrides::Terraform::ResourceOverride mutex: "google-sql-database-instance-{{project}}-{{instance}}" + read_error_transform: "transformSQLDatabaseReadError" import_format: ["projects/{{project}}/instances/{{instance}}/databases/{{name}}", "{{project}}/{{instance}}/{{name}}", "instances/{{instance}}/databases/{{name}}", diff --git a/templates/terraform/resource.erb b/templates/terraform/resource.erb index 8cb9edaa4f9c..1fb4a62ba978 100644 --- a/templates/terraform/resource.erb +++ b/templates/terraform/resource.erb @@ -407,7 +407,11 @@ func resource<%= resource_name -%>Read(d *schema.ResourceData, meta interface{}) <% end -%> res, err := sendRequest(config, "<%= object.read_verb.to_s.upcase -%>", <% if has_project || object.supports_indirect_user_project_override %>project<% else %>""<% end %>, url, nil<%= object.error_retry_predicates ? ", " + object.error_retry_predicates.join(',') : "" -%>) if err != nil { +<% if object.read_error_transform -%> + return handleNotFoundError(<%= object.read_error_transform %>(err), d, fmt.Sprintf("<%= resource_name -%> %q", d.Id())) +<% else -%> return handleNotFoundError(err, d, fmt.Sprintf("<%= resource_name -%> %q", d.Id())) +<% end -%> } <% if object.nested_query -%> diff --git a/third_party/terraform/utils/sql_utils.go b/third_party/terraform/utils/sql_utils.go new file mode 100644 index 000000000000..1924b4952fdd --- /dev/null +++ b/third_party/terraform/utils/sql_utils.go @@ -0,0 +1,26 @@ +package google + +import ( + "log" + "strings" + + "github.com/hashicorp/errwrap" + "google.golang.org/api/googleapi" +) + +func transformSQLDatabaseReadError(err error) error { + if gErr, ok := errwrap.GetType(err, &googleapi.Error{}).(*googleapi.Error); ok { + if gErr.Code == 400 && strings.Contains(gErr.Message, "Invalid request since instance is not running") { + // This error occurs when attempting a GET after deleting the sql database and sql instance. It leads to to + // inconsistent behavior as handleNotFoundError(...) expects an error code of 404 when a resource does not + // exist. To get the desired behavior from handleNotFoundError, modify the return code to 404 so that + // handleNotFoundError(...) will treat this as a NotFound error + gErr.Code = 404 + } + + log.Printf("[DEBUG] Transformed SQLDatabase error") + return gErr + } + + return err +}