From de5448d9197b3135786928e9e816615921079cc5 Mon Sep 17 00:00:00 2001 From: The Magician Date: Wed, 13 Mar 2019 08:45:54 -0700 Subject: [PATCH] Add a method for converting structs -> maps when bridging MM -> TF (#3223) /cc @rileykarson --- google/convert.go | 20 ++++++++++++ google/resource_google_folder.go | 13 ++++++-- google/resource_google_project.go | 7 +++- google/resource_manager_operation.go | 46 ++++++++++++++++++++++++++ google/resourcemanager_operation.go | 48 ---------------------------- 5 files changed, 83 insertions(+), 51 deletions(-) create mode 100644 google/resource_manager_operation.go delete mode 100644 google/resourcemanager_operation.go diff --git a/google/convert.go b/google/convert.go index 2b0d8980..75e49852 100644 --- a/google/convert.go +++ b/google/convert.go @@ -28,6 +28,26 @@ func Convert(item, out interface{}) error { return nil } +// When converting to a map, we can't use setOmittedFields because FieldByName +// fails. Luckily, we don't use the omitted fields anymore with generated +// resources, and this function is used to bridge from handwritten -> generated. +// Since this is a known type, we can create it inline instead of needing to +// pass an object in. +func ConvertToMap(item interface{}) (map[string]interface{}, error) { + out := make(map[string]interface{}) + bytes, err := json.Marshal(item) + if err != nil { + return nil, err + } + + err = json.Unmarshal(bytes, &out) + if err != nil { + return nil, err + } + + return out, nil +} + func setOmittedFields(item, out interface{}) { // Both inputs must be pointers, see https://blog.golang.org/laws-of-reflection: // "To modify a reflection object, the value must be settable." diff --git a/google/resource_google_folder.go b/google/resource_google_folder.go index fac9bc8e..1fbb7e2c 100644 --- a/google/resource_google_folder.go +++ b/google/resource_google_folder.go @@ -63,8 +63,12 @@ func resourceGoogleFolderCreate(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error creating folder '%s' in '%s': %s", displayName, parent, err) } - err = resourceManagerV2Beta1OperationWait(config.clientResourceManager, op, "creating folder") + opAsMap, err := ConvertToMap(op) + if err != nil { + return err + } + err = resourceManagerOperationWaitTime(config, opAsMap, "", "creating folder", int(d.Timeout(schema.TimeoutCreate).Minutes())) if err != nil { return fmt.Errorf("Error creating folder '%s' in '%s': %s", displayName, parent, err) } @@ -132,7 +136,12 @@ func resourceGoogleFolderUpdate(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error moving folder '%s' to '%s': %s", displayName, newParent, err) } - err = resourceManagerV2Beta1OperationWait(config.clientResourceManager, op, "move folder") + opAsMap, err := ConvertToMap(op) + if err != nil { + return err + } + + err = resourceManagerOperationWaitTime(config, opAsMap, "", "move folder", int(d.Timeout(schema.TimeoutCreate).Minutes())) if err != nil { return fmt.Errorf("Error moving folder '%s' to '%s': %s", displayName, newParent, err) } diff --git a/google/resource_google_project.go b/google/resource_google_project.go index f64ceaf3..dfa27ce6 100644 --- a/google/resource_google_project.go +++ b/google/resource_google_project.go @@ -227,7 +227,12 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error d.SetId(pid) // Wait for the operation to complete - waitErr := resourceManagerOperationWait(config.clientResourceManager, op, "project to create") + opAsMap, err := ConvertToMap(op) + if err != nil { + return err + } + + waitErr := resourceManagerOperationWaitTime(config, opAsMap, "", "creating folder", int(d.Timeout(schema.TimeoutCreate).Minutes())) if waitErr != nil { // The resource wasn't actually created d.SetId("") diff --git a/google/resource_manager_operation.go b/google/resource_manager_operation.go new file mode 100644 index 00000000..e140278b --- /dev/null +++ b/google/resource_manager_operation.go @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- +package google + +import ( + "fmt" +) + +type ResourceManagerOperationWaiter struct { + Config *Config + CommonOperationWaiter +} + +func (w *ResourceManagerOperationWaiter) QueryOp() (interface{}, error) { + if w == nil { + return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") + } + // Returns the proper get. + url := fmt.Sprintf("https://cloudresourcemanager.googleapis.com/v1/%s", w.CommonOperationWaiter.Op.Name) + return sendRequest(w.Config, "GET", url, nil) +} + +func resourceManagerOperationWaitTime(config *Config, op map[string]interface{}, project, activity string, timeoutMinutes int) error { + if val, ok := op["name"]; !ok || val == "" { + // This was a synchronous call - there is no operation to wait for. + return nil + } + w := &ResourceManagerOperationWaiter{ + Config: config, + } + if err := w.CommonOperationWaiter.SetOp(op); err != nil { + return err + } + return OperationWait(w, activity, timeoutMinutes) +} diff --git a/google/resourcemanager_operation.go b/google/resourcemanager_operation.go deleted file mode 100644 index 55444041..00000000 --- a/google/resourcemanager_operation.go +++ /dev/null @@ -1,48 +0,0 @@ -package google - -import ( - "fmt" - - "google.golang.org/api/cloudresourcemanager/v1" - resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1" -) - -type ResourceManagerOperationWaiter struct { - Service *cloudresourcemanager.Service - CommonOperationWaiter -} - -func (w *ResourceManagerOperationWaiter) QueryOp() (interface{}, error) { - if w == nil { - return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") - } - return w.Service.Operations.Get(w.Op.Name).Do() -} - -func resourceManagerOperationWaitTime(service *cloudresourcemanager.Service, op *cloudresourcemanager.Operation, activity string, timeoutMin int) error { - w := &ResourceManagerOperationWaiter{ - Service: service, - } - if err := w.SetOp(op); err != nil { - return err - } - return OperationWait(w, activity, timeoutMin) -} - -func resourceManagerOperationWait(service *cloudresourcemanager.Service, op *cloudresourcemanager.Operation, activity string) error { - return resourceManagerOperationWaitTime(service, op, activity, 4) -} - -func resourceManagerV2Beta1OperationWait(service *cloudresourcemanager.Service, op *resourceManagerV2Beta1.Operation, activity string) error { - return resourceManagerV2Beta1OperationWaitTime(service, op, activity, 4) -} - -func resourceManagerV2Beta1OperationWaitTime(service *cloudresourcemanager.Service, op *resourceManagerV2Beta1.Operation, activity string, timeoutMin int) error { - opV1 := &cloudresourcemanager.Operation{} - err := Convert(op, opV1) - if err != nil { - return err - } - - return resourceManagerOperationWaitTime(service, opV1, activity, timeoutMin) -}