From 85dface1af034bfe556d43bfbd5066056220e774 Mon Sep 17 00:00:00 2001 From: Nathan McKinley Date: Fri, 7 Feb 2020 12:01:42 -0800 Subject: [PATCH] Switch to creating a new method - this was getting too complicated to port old code over to. --- templates/terraform/operation.go.erb | 28 +++++++++--- templates/terraform/resource.erb | 45 +++++++++++-------- .../terraform/utils/appengine_operation.go | 22 +++++++++ 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/templates/terraform/operation.go.erb b/templates/terraform/operation.go.erb index 55a39e6cae18..048ce1be3eec 100644 --- a/templates/terraform/operation.go.erb +++ b/templates/terraform/operation.go.erb @@ -26,10 +26,10 @@ func (w *<%= product_name -%>OperationWaiter) QueryOp() (interface{}, error) { return sendRequest(w.Config, "GET", <% if has_project %>w.Project<% else %>""<% end %>, url, nil<%= object.error_retry_predicates ? ", " + object.error_retry_predicates.join(',') : "" -%>) } -func <%= product_name.camelize(:lower) -%>OperationWaitTime(config *Config, op map[string]interface{},<% if async.result.resource_inside_response -%> response *map[string]interface{},<% end -%> <% if has_project -%> project,<% end -%> activity string, timeoutMinutes int) error { +func create<%= product_name %>Waiter(config *Config, op map[string]interface{}, <% if has_project -%> project, <% end -%> activity string) (*<%=product_name%>OperationWaiter, error) { if val, ok := op["name"]; !ok || val == "" { // This was a synchronous call - there is no operation to wait for. - return nil + return nil, nil } w := &<%= product_name -%>OperationWaiter{ Config: config, @@ -38,14 +38,30 @@ func <%= product_name.camelize(:lower) -%>OperationWaitTime(config *Config, op m <% end -%> } if err := w.CommonOperationWaiter.SetOp(op); err != nil { - return err + return nil, err + } + return w, nil +} + +<% if async.result.resource_inside_response -%> +func <%= product_name.camelize(:lower) -%>OperationWaitTimeWithResponse(config *Config, op map[string]interface{}, response *map[string]interface{},<% if has_project -%> project,<% end -%> activity string, timeoutMinutes int) error { + w, err := create<%= product_name %>Waiter(config, op, <% if has_project -%> project, <%end-%> activity) + if err != nil || w == nil { + // If w is nil, the op was synchronous. + return err } - <% if async.result.resource_inside_response -%> if err := OperationWait(w, activity, timeoutMinutes); err != nil { return err } return json.Unmarshal([]byte(w.CommonOperationWaiter.Op.Response), response) - <% else -%> +} +<% end -%> + +func <%= product_name.camelize(:lower) -%>OperationWaitTime(config *Config, op map[string]interface{}, <% if has_project -%> project,<% end -%> activity string, timeoutMinutes int) error { + w, err := create<%= product_name %>Waiter(config, op, <% if has_project -%> project, <%end-%> activity) + if err != nil || w == nil { + // If w is nil, the op was synchronous. + return err + } return OperationWait(w, activity, timeoutMinutes) - <% end -%> } diff --git a/templates/terraform/resource.erb b/templates/terraform/resource.erb index 899feb475d22..56bf5a5d2608 100644 --- a/templates/terraform/resource.erb +++ b/templates/terraform/resource.erb @@ -234,11 +234,10 @@ func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{ } <% end -%> <% if object.async.is_a? Api::OpAsync -%> - <% if object.async.result.resource_inside_response -%> + <% if object.async.result.resource_inside_response and not object.identity.empty? -%> var response map[string]interface{} - <% end -%> - err = <%= client_name_camel -%>OperationWaitTime( - config, res,<% if object.async.result.resource_inside_response -%> &response,<% end -%> <% if has_project -%> project, <% end -%> "Creating <%= object.name -%>", + err = <%= client_name_camel -%>OperationWaitTimeWithResponse( + config, res, &response, <% if has_project -%> project, <% end -%> "Creating <%= object.name -%>", int(d.Timeout(schema.TimeoutCreate).Minutes())) if err != nil { @@ -249,7 +248,6 @@ func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{ d.SetId("") return fmt.Errorf("Error waiting to create <%= object.name -%>: %s", err) } - <% if object.async.result.resource_inside_response -%> <% object.gettable_properties.each do |prop| -%> <% if object.identity.include?(prop) -%> if err := d.Set("<%= prop.name.underscore -%>", flatten<%= resource_name -%><%= titlelize_property(prop) -%>(response["<%= prop.api_name -%>"], d, config)); err != nil { @@ -258,10 +256,30 @@ func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{ <% end -%> <% end -%> - <% end -%> + // This may have caused the ID to update - update it if so. + id, err = replaceVars(d, config, "<%= id_format(object) -%>") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + <% else -%> + err = <%= client_name_camel -%>OperationWaitTime( + config, res, <% if has_project -%> project, <% end -%> "Creating <%= object.name -%>", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if err != nil { +<% if object.custom_code.post_create_failure -%> + resource<%= resource_name -%>PostCreateFailure(d, meta) +<% end -%> + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create <%= object.name -%>: %s", err) + } <% end -%> +<% end -%> <% end -%> log.Printf("[DEBUG] Finished creating <%= object.name -%> %q: %#v", d.Id(), res) @@ -492,11 +510,8 @@ if <%= props.map { |prop| "d.HasChange(\"#{prop.name.underscore}\")" }.join ' || } <% end -%> <% if object.async.is_a? Api::OpAsync -%> - <% if object.async.result.resource_inside_response -%> - var response map[string]interface{} - <% end -%> err = <%= client_name_camel -%>OperationWaitTime( - config, res,<% if object.async.result.resource_inside_response -%> &response,<% end -%> <% if has_project -%> project, <% end -%> "Updating <%= object.name -%>", + config, res, <% if has_project -%> project, <% end -%> "Updating <%= object.name -%>", int(d.Timeout(schema.TimeoutUpdate).Minutes())) if err != nil { return err @@ -597,11 +612,8 @@ if <%= props.map { |prop| "d.HasChange(\"#{prop.name.underscore}\")" }.join ' || } <% end -%> <% if object.async.is_a? Api::OpAsync -%> - <% if object.async.result.resource_inside_response -%> - var response map[string]interface{} - <% end -%> err = <%= client_name_camel -%>OperationWaitTime( - config, res,<% if object.async.result.resource_inside_response -%> &response,<% end -%> <% if has_project -%> project, <% end -%> "Updating <%= object.name -%>", + config, res, <% if has_project -%> project, <% end -%> "Updating <%= object.name -%>", int(d.Timeout(schema.TimeoutUpdate).Minutes())) if err != nil { @@ -673,11 +685,8 @@ func resource<%= resource_name -%>Delete(d *schema.ResourceData, meta interface{ } <% if !object.async.nil? && object.async.allow?('delete') -%> - <% if object.async.result.resource_inside_response -%> - var response map[string]interface{} - <% end -%> err = <%= client_name_camel -%>OperationWaitTime( - config, res,<% if object.async.result.resource_inside_response -%> &response,<% end -%> <% if has_project -%> project, <% end -%> "Deleting <%= object.name -%>", + config, res, <% if has_project -%> project, <% end -%> "Deleting <%= object.name -%>", int(d.Timeout(schema.TimeoutDelete).Minutes())) if err != nil { diff --git a/third_party/terraform/utils/appengine_operation.go b/third_party/terraform/utils/appengine_operation.go index 0e96a21110cb..11ebc12f9c79 100644 --- a/third_party/terraform/utils/appengine_operation.go +++ b/third_party/terraform/utils/appengine_operation.go @@ -1,6 +1,7 @@ package google import ( + "encoding/json" "fmt" "regexp" @@ -32,6 +33,27 @@ func appEngineOperationWait(config *Config, res interface{}, appId, activity str return appEngineOperationWaitTime(config, res, appId, activity, 4) } +func appEngineOperationWaitTimeWithResponse(config *Config, res interface{}, response *map[string]interface{}, appId, activity string, timeoutMinutes int) error { + op := &appengine.Operation{} + err := Convert(res, op) + if err != nil { + return err + } + + w := &AppEngineOperationWaiter{ + Service: config.clientAppEngine, + AppId: appId, + } + + if err := w.SetOp(op); err != nil { + return err + } + if err := OperationWait(w, activity, timeoutMinutes); err != nil { + return err + } + return json.Unmarshal([]byte(w.CommonOperationWaiter.Op.Response), response) +} + func appEngineOperationWaitTime(config *Config, res interface{}, appId, activity string, timeoutMinutes int) error { op := &appengine.Operation{} err := Convert(res, op)