diff --git a/.changelog/3312.txt b/.changelog/3312.txt new file mode 100644 index 0000000000..f4e6f49022 --- /dev/null +++ b/.changelog/3312.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_bigquery_dataset_access` +``` diff --git a/google-beta/provider.go b/google-beta/provider.go index a524f1ace4..25716495c2 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -595,9 +595,9 @@ func Provider() terraform.ResourceProvider { return provider } -// Generated resources: 137 +// Generated resources: 138 // Generated IAM resources: 54 -// Total generated resources: 191 +// Total generated resources: 192 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -617,6 +617,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_app_engine_application_url_dispatch_rules": resourceAppEngineApplicationUrlDispatchRules(), "google_app_engine_service_split_traffic": resourceAppEngineServiceSplitTraffic(), "google_bigquery_dataset": resourceBigQueryDataset(), + "google_bigquery_dataset_access": resourceBigQueryDatasetAccess(), "google_bigquery_data_transfer_config": resourceBigqueryDataTransferConfig(), "google_bigquery_reservation": resourceBigqueryReservationReservation(), "google_bigtable_app_profile": resourceBigtableAppProfile(), diff --git a/google-beta/resource_access_context_manager_service_perimeter_resource.go b/google-beta/resource_access_context_manager_service_perimeter_resource.go index aaa46ef4d2..af24742c56 100644 --- a/google-beta/resource_access_context_manager_service_perimeter_resource.go +++ b/google-beta/resource_access_context_manager_service_perimeter_resource.go @@ -63,7 +63,7 @@ func resourceAccessContextManagerServicePerimeterResourceCreate(d *schema.Resour config := meta.(*Config) obj := make(map[string]interface{}) - resourceProp, err := expandAccessContextManagerServicePerimeterResourceResource(d.Get("resource"), d, config) + resourceProp, err := expandNestedAccessContextManagerServicePerimeterResourceResource(d.Get("resource"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("resource"); !isEmptyValue(reflect.ValueOf(resourceProp)) && (ok || !reflect.DeepEqual(v, resourceProp)) { @@ -126,7 +126,7 @@ func resourceAccessContextManagerServicePerimeterResourceCreate(d *schema.Resour return fmt.Errorf("Error decoding response from operation, could not find nested object") } } - if err := d.Set("resource", flattenAccessContextManagerServicePerimeterResourceResource(opRes["resource"], d, config)); err != nil { + if err := d.Set("resource", flattenNestedAccessContextManagerServicePerimeterResourceResource(opRes["resource"], d, config)); err != nil { return err } @@ -167,7 +167,7 @@ func resourceAccessContextManagerServicePerimeterResourceRead(d *schema.Resource return nil } - if err := d.Set("resource", flattenAccessContextManagerServicePerimeterResourceResource(res["resource"], d, config)); err != nil { + if err := d.Set("resource", flattenNestedAccessContextManagerServicePerimeterResourceResource(res["resource"], d, config)); err != nil { return fmt.Errorf("Error reading ServicePerimeterResource: %s", err) } @@ -232,11 +232,11 @@ func resourceAccessContextManagerServicePerimeterResourceImport(d *schema.Resour return []*schema.ResourceData{d}, nil } -func flattenAccessContextManagerServicePerimeterResourceResource(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedAccessContextManagerServicePerimeterResourceResource(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandAccessContextManagerServicePerimeterResourceResource(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedAccessContextManagerServicePerimeterResourceResource(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -275,10 +275,11 @@ func flattenNestedAccessContextManagerServicePerimeterResource(d *schema.Resourc } func resourceAccessContextManagerServicePerimeterResourceFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedResource, err := expandAccessContextManagerServicePerimeterResourceResource(d.Get("resource"), d, meta.(*Config)) + expectedResource, err := expandNestedAccessContextManagerServicePerimeterResourceResource(d.Get("resource"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedResource := flattenNestedAccessContextManagerServicePerimeterResourceResource(expectedResource, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -290,9 +291,10 @@ func resourceAccessContextManagerServicePerimeterResourceFindNestedObjectInList( "resource": itemRaw, } - itemResource := flattenAccessContextManagerServicePerimeterResourceResource(item["resource"], d, meta.(*Config)) - if !reflect.DeepEqual(itemResource, expectedResource) { - log.Printf("[DEBUG] Skipping item with resource= %#v, looking for %#v)", itemResource, expectedResource) + itemResource := flattenNestedAccessContextManagerServicePerimeterResourceResource(item["resource"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemResource)) && isEmptyValue(reflect.ValueOf(expectedFlattenedResource))) && !reflect.DeepEqual(itemResource, expectedFlattenedResource) { + log.Printf("[DEBUG] Skipping item with resource= %#v, looking for %#v)", itemResource, expectedFlattenedResource) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_big_query_dataset_access.go b/google-beta/resource_big_query_dataset_access.go new file mode 100644 index 0000000000..6f4add4a50 --- /dev/null +++ b/google-beta/resource_big_query_dataset_access.go @@ -0,0 +1,670 @@ +// ---------------------------------------------------------------------------- +// +// *** 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" + "log" + "reflect" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "google.golang.org/api/googleapi" +) + +func resourceBigQueryDatasetAccess() *schema.Resource { + return &schema.Resource{ + Create: resourceBigQueryDatasetAccessCreate, + Read: resourceBigQueryDatasetAccessRead, + Delete: resourceBigQueryDatasetAccessDelete, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(4 * time.Minute), + Delete: schema.DefaultTimeout(4 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "dataset_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `A unique ID for this dataset, without the project name. The ID +must contain only letters (a-z, A-Z), numbers (0-9), or +underscores (_). The maximum length is 1,024 characters.`, + }, + "domain": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `A domain to grant access to. Any users signed in with the +domain specified will be granted the specified access`, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "group_by_email": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `An email address of a Google Group to grant access to.`, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "iam_member": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Some other type of member that appears in the IAM Policy but isn't a user, +group, domain, or special group. For example: 'allUsers'`, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "role": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Describes the rights granted to the user specified by the other +member of the access object. Primitive, Predefined and custom +roles are supported. Predefined roles that have equivalent +primitive roles are swapped by the API to their Primitive +counterparts, and will show a diff post-create. See +[official docs](https://cloud.google.com/bigquery/docs/access-control).`, + }, + "special_group": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `A special group to grant access to. Possible values include: + + +* 'projectOwners': Owners of the enclosing project. + + +* 'projectReaders': Readers of the enclosing project. + + +* 'projectWriters': Writers of the enclosing project. + + +* 'allAuthenticatedUsers': All authenticated BigQuery users.`, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "user_by_email": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `An email address of a user to grant access to. For example: +fred@example.com`, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "view": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `A view from a different dataset to grant access to. Queries +executed against that view will have read access to tables in +this dataset. The role field is not required when this field is +set. If that view is updated by any user, access to the view +needs to be granted again via an update operation.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dataset_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The ID of the dataset containing this table.`, + }, + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The ID of the project containing this table.`, + }, + "table_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The ID of the table. The ID must contain only letters (a-z, +A-Z), numbers (0-9), or underscores (_). The maximum length +is 1,024 characters.`, + }, + }, + }, + ExactlyOneOf: []string{"user_by_email", "group_by_email", "domain", "special_group", "iam_member", "view"}, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } +} + +func resourceBigQueryDatasetAccessCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + datasetIdProp, err := expandNestedBigQueryDatasetAccessDatasetId(d.Get("dataset_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("dataset_id"); !isEmptyValue(reflect.ValueOf(datasetIdProp)) && (ok || !reflect.DeepEqual(v, datasetIdProp)) { + obj["datasetId"] = datasetIdProp + } + roleProp, err := expandNestedBigQueryDatasetAccessRole(d.Get("role"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("role"); !isEmptyValue(reflect.ValueOf(roleProp)) && (ok || !reflect.DeepEqual(v, roleProp)) { + obj["role"] = roleProp + } + userByEmailProp, err := expandNestedBigQueryDatasetAccessUserByEmail(d.Get("user_by_email"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("user_by_email"); !isEmptyValue(reflect.ValueOf(userByEmailProp)) && (ok || !reflect.DeepEqual(v, userByEmailProp)) { + obj["userByEmail"] = userByEmailProp + } + groupByEmailProp, err := expandNestedBigQueryDatasetAccessGroupByEmail(d.Get("group_by_email"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("group_by_email"); !isEmptyValue(reflect.ValueOf(groupByEmailProp)) && (ok || !reflect.DeepEqual(v, groupByEmailProp)) { + obj["groupByEmail"] = groupByEmailProp + } + domainProp, err := expandNestedBigQueryDatasetAccessDomain(d.Get("domain"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("domain"); !isEmptyValue(reflect.ValueOf(domainProp)) && (ok || !reflect.DeepEqual(v, domainProp)) { + obj["domain"] = domainProp + } + specialGroupProp, err := expandNestedBigQueryDatasetAccessSpecialGroup(d.Get("special_group"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("special_group"); !isEmptyValue(reflect.ValueOf(specialGroupProp)) && (ok || !reflect.DeepEqual(v, specialGroupProp)) { + obj["specialGroup"] = specialGroupProp + } + iamMemberProp, err := expandNestedBigQueryDatasetAccessIamMember(d.Get("iam_member"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("iam_member"); !isEmptyValue(reflect.ValueOf(iamMemberProp)) && (ok || !reflect.DeepEqual(v, iamMemberProp)) { + obj["iamMember"] = iamMemberProp + } + viewProp, err := expandNestedBigQueryDatasetAccessView(d.Get("view"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("view"); !isEmptyValue(reflect.ValueOf(viewProp)) && (ok || !reflect.DeepEqual(v, viewProp)) { + obj["view"] = viewProp + } + + lockName, err := replaceVars(d, config, "{{dataset_id}}") + if err != nil { + return err + } + mutexKV.Lock(lockName) + defer mutexKV.Unlock(lockName) + + url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new DatasetAccess: %#v", obj) + + obj, err = resourceBigQueryDatasetAccessPatchCreateEncoder(d, meta, obj) + if err != nil { + return err + } + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "PATCH", project, url, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating DatasetAccess: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating DatasetAccess %q: %#v", d.Id(), res) + + return resourceBigQueryDatasetAccessRead(d, meta) +} + +func resourceBigQueryDatasetAccessRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("BigQueryDatasetAccess %q", d.Id())) + } + + res, err = flattenNestedBigQueryDatasetAccess(d, meta, res) + if err != nil { + return err + } + + if res == nil { + // Object isn't there any more - remove it from the state. + log.Printf("[DEBUG] Removing BigQueryDatasetAccess because it couldn't be matched.") + d.SetId("") + return nil + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + + if err := d.Set("role", flattenNestedBigQueryDatasetAccessRole(res["role"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("user_by_email", flattenNestedBigQueryDatasetAccessUserByEmail(res["userByEmail"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("group_by_email", flattenNestedBigQueryDatasetAccessGroupByEmail(res["groupByEmail"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("domain", flattenNestedBigQueryDatasetAccessDomain(res["domain"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("special_group", flattenNestedBigQueryDatasetAccessSpecialGroup(res["specialGroup"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("iam_member", flattenNestedBigQueryDatasetAccessIamMember(res["iamMember"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + if err := d.Set("view", flattenNestedBigQueryDatasetAccessView(res["view"], d, config)); err != nil { + return fmt.Errorf("Error reading DatasetAccess: %s", err) + } + + return nil +} + +func resourceBigQueryDatasetAccessDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + lockName, err := replaceVars(d, config, "{{dataset_id}}") + if err != nil { + return err + } + mutexKV.Lock(lockName) + defer mutexKV.Unlock(lockName) + + url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + obj, err = resourceBigQueryDatasetAccessPatchDeleteEncoder(d, meta, obj) + if err != nil { + return handleNotFoundError(err, d, "DatasetAccess") + } + log.Printf("[DEBUG] Deleting DatasetAccess %q", d.Id()) + + res, err := sendRequestWithTimeout(config, "PATCH", project, url, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "DatasetAccess") + } + + log.Printf("[DEBUG] Finished deleting DatasetAccess %q: %#v", d.Id(), res) + return nil +} + +func flattenNestedBigQueryDatasetAccessRole(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessUserByEmail(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessGroupByEmail(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessDomain(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessSpecialGroup(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessIamMember(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessView(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["dataset_id"] = + flattenNestedBigQueryDatasetAccessViewDatasetId(original["datasetId"], d, config) + transformed["project_id"] = + flattenNestedBigQueryDatasetAccessViewProjectId(original["projectId"], d, config) + transformed["table_id"] = + flattenNestedBigQueryDatasetAccessViewTableId(original["tableId"], d, config) + return []interface{}{transformed} +} +func flattenNestedBigQueryDatasetAccessViewDatasetId(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessViewProjectId(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNestedBigQueryDatasetAccessViewTableId(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandNestedBigQueryDatasetAccessDatasetId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessRole(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessUserByEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessGroupByEmail(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessDomain(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessSpecialGroup(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessIamMember(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessView(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDatasetId, err := expandNestedBigQueryDatasetAccessViewDatasetId(original["dataset_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDatasetId); val.IsValid() && !isEmptyValue(val) { + transformed["datasetId"] = transformedDatasetId + } + + transformedProjectId, err := expandNestedBigQueryDatasetAccessViewProjectId(original["project_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProjectId); val.IsValid() && !isEmptyValue(val) { + transformed["projectId"] = transformedProjectId + } + + transformedTableId, err := expandNestedBigQueryDatasetAccessViewTableId(original["table_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTableId); val.IsValid() && !isEmptyValue(val) { + transformed["tableId"] = transformedTableId + } + + return transformed, nil +} + +func expandNestedBigQueryDatasetAccessViewDatasetId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessViewProjectId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNestedBigQueryDatasetAccessViewTableId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func flattenNestedBigQueryDatasetAccess(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { + var v interface{} + var ok bool + + v, ok = res["access"] + if !ok || v == nil { + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res + } + + switch v.(type) { + case []interface{}: + break + case map[string]interface{}: + // Construct list out of single nested resource + v = []interface{}{v} + default: + return nil, fmt.Errorf("expected list or map for value access. Actual value: %v", v) + } + + _, item, err := resourceBigQueryDatasetAccessFindNestedObjectInList(d, meta, v.([]interface{})) + if err != nil { + return nil, err + } + return item, nil +} + +func resourceBigQueryDatasetAccessFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { + expectedRole, err := expandNestedBigQueryDatasetAccessRole(d.Get("role"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedRole := flattenNestedBigQueryDatasetAccessRole(expectedRole, d, meta.(*Config)) + expectedUserByEmail, err := expandNestedBigQueryDatasetAccessUserByEmail(d.Get("user_by_email"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedUserByEmail := flattenNestedBigQueryDatasetAccessUserByEmail(expectedUserByEmail, d, meta.(*Config)) + expectedGroupByEmail, err := expandNestedBigQueryDatasetAccessGroupByEmail(d.Get("group_by_email"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedGroupByEmail := flattenNestedBigQueryDatasetAccessGroupByEmail(expectedGroupByEmail, d, meta.(*Config)) + expectedDomain, err := expandNestedBigQueryDatasetAccessDomain(d.Get("domain"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedDomain := flattenNestedBigQueryDatasetAccessDomain(expectedDomain, d, meta.(*Config)) + expectedSpecialGroup, err := expandNestedBigQueryDatasetAccessSpecialGroup(d.Get("special_group"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedSpecialGroup := flattenNestedBigQueryDatasetAccessSpecialGroup(expectedSpecialGroup, d, meta.(*Config)) + expectedIamMember, err := expandNestedBigQueryDatasetAccessIamMember(d.Get("iam_member"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedIamMember := flattenNestedBigQueryDatasetAccessIamMember(expectedIamMember, d, meta.(*Config)) + expectedView, err := expandNestedBigQueryDatasetAccessView(d.Get("view"), d, meta.(*Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedView := flattenNestedBigQueryDatasetAccessView(expectedView, d, meta.(*Config)) + + // Search list for this resource. + for idx, itemRaw := range items { + if itemRaw == nil { + continue + } + item := itemRaw.(map[string]interface{}) + + itemRole := flattenNestedBigQueryDatasetAccessRole(item["role"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemRole)) && isEmptyValue(reflect.ValueOf(expectedFlattenedRole))) && !reflect.DeepEqual(itemRole, expectedFlattenedRole) { + log.Printf("[DEBUG] Skipping item with role= %#v, looking for %#v)", itemRole, expectedFlattenedRole) + continue + } + itemUserByEmail := flattenNestedBigQueryDatasetAccessUserByEmail(item["userByEmail"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemUserByEmail)) && isEmptyValue(reflect.ValueOf(expectedFlattenedUserByEmail))) && !reflect.DeepEqual(itemUserByEmail, expectedFlattenedUserByEmail) { + log.Printf("[DEBUG] Skipping item with userByEmail= %#v, looking for %#v)", itemUserByEmail, expectedFlattenedUserByEmail) + continue + } + itemGroupByEmail := flattenNestedBigQueryDatasetAccessGroupByEmail(item["groupByEmail"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemGroupByEmail)) && isEmptyValue(reflect.ValueOf(expectedFlattenedGroupByEmail))) && !reflect.DeepEqual(itemGroupByEmail, expectedFlattenedGroupByEmail) { + log.Printf("[DEBUG] Skipping item with groupByEmail= %#v, looking for %#v)", itemGroupByEmail, expectedFlattenedGroupByEmail) + continue + } + itemDomain := flattenNestedBigQueryDatasetAccessDomain(item["domain"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemDomain)) && isEmptyValue(reflect.ValueOf(expectedFlattenedDomain))) && !reflect.DeepEqual(itemDomain, expectedFlattenedDomain) { + log.Printf("[DEBUG] Skipping item with domain= %#v, looking for %#v)", itemDomain, expectedFlattenedDomain) + continue + } + itemSpecialGroup := flattenNestedBigQueryDatasetAccessSpecialGroup(item["specialGroup"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemSpecialGroup)) && isEmptyValue(reflect.ValueOf(expectedFlattenedSpecialGroup))) && !reflect.DeepEqual(itemSpecialGroup, expectedFlattenedSpecialGroup) { + log.Printf("[DEBUG] Skipping item with specialGroup= %#v, looking for %#v)", itemSpecialGroup, expectedFlattenedSpecialGroup) + continue + } + itemIamMember := flattenNestedBigQueryDatasetAccessIamMember(item["iamMember"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemIamMember)) && isEmptyValue(reflect.ValueOf(expectedFlattenedIamMember))) && !reflect.DeepEqual(itemIamMember, expectedFlattenedIamMember) { + log.Printf("[DEBUG] Skipping item with iamMember= %#v, looking for %#v)", itemIamMember, expectedFlattenedIamMember) + continue + } + itemView := flattenNestedBigQueryDatasetAccessView(item["view"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemView)) && isEmptyValue(reflect.ValueOf(expectedFlattenedView))) && !reflect.DeepEqual(itemView, expectedFlattenedView) { + log.Printf("[DEBUG] Skipping item with view= %#v, looking for %#v)", itemView, expectedFlattenedView) + continue + } + log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) + return idx, item, nil + } + return -1, nil, nil +} + +// PatchCreateEncoder handles creating request data to PATCH parent resource +// with list including new object. +func resourceBigQueryDatasetAccessPatchCreateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + currItems, err := resourceBigQueryDatasetAccessListForPatch(d, meta) + if err != nil { + return nil, err + } + + _, found, err := resourceBigQueryDatasetAccessFindNestedObjectInList(d, meta, currItems) + if err != nil { + return nil, err + } + + // Return error if item already created. + if found != nil { + return nil, fmt.Errorf("Unable to create DatasetAccess, existing object already found: %+v", found) + } + + // Return list with the resource to create appended + res := map[string]interface{}{ + "access": append(currItems, obj), + } + + return res, nil +} + +// PatchDeleteEncoder handles creating request data to PATCH parent resource +// with list excluding object to delete. +func resourceBigQueryDatasetAccessPatchDeleteEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + currItems, err := resourceBigQueryDatasetAccessListForPatch(d, meta) + if err != nil { + return nil, err + } + + idx, item, err := resourceBigQueryDatasetAccessFindNestedObjectInList(d, meta, currItems) + if err != nil { + return nil, err + } + if item == nil { + // Spoof 404 error for proper handling by Delete (i.e. no-op) + return nil, &googleapi.Error{ + Code: 404, + Message: "DatasetAccess not found in list", + } + } + + updatedItems := append(currItems[:idx], currItems[idx+1:]...) + res := map[string]interface{}{ + "access": updatedItems, + } + + return res, nil +} + +// ListForPatch handles making API request to get parent resource and +// extracting list of objects. +func resourceBigQueryDatasetAccessListForPatch(d *schema.ResourceData, meta interface{}) ([]interface{}, error) { + config := meta.(*Config) + url, err := replaceVars(d, config, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return nil, err + } + project, err := getProject(d, config) + if err != nil { + return nil, err + } + res, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return nil, err + } + + var v interface{} + var ok bool + + v, ok = res["access"] + if ok && v != nil { + ls, lsOk := v.([]interface{}) + if !lsOk { + return nil, fmt.Errorf(`expected list for nested field "access"`) + } + return ls, nil + } + return nil, nil +} diff --git a/google-beta/resource_bigquery_dataset_access_test.go b/google-beta/resource_bigquery_dataset_access_test.go new file mode 100644 index 0000000000..d631739f73 --- /dev/null +++ b/google-beta/resource_bigquery_dataset_access_test.go @@ -0,0 +1,227 @@ +package google + +import ( + "fmt" + "reflect" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccBigQueryDatasetAccess_basic(t *testing.T) { + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(10)) + saID := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + expected := map[string]interface{}{ + "role": "OWNER", + "userByEmail": fmt.Sprintf("%s@%s.iam.gserviceaccount.com", saID, getTestProjectFromEnv()), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDatasetAccess_basic(datasetID, saID), + Check: testAccCheckBigQueryDatasetAccessPresent("google_bigquery_dataset.dataset", expected), + }, + { + // Destroy step instead of CheckDestroy so we can check the access is removed without deleting the dataset + Config: testAccBigQueryDatasetAccess_destroy(datasetID, "dataset"), + Check: testAccCheckBigQueryDatasetAccessAbsent("google_bigquery_dataset.dataset", expected), + }, + }, + }) +} + +func TestAccBigQueryDatasetAccess_view(t *testing.T) { + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(10)) + datasetID2 := fmt.Sprintf("tf_test_%s", acctest.RandString(10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(10)) + + expected := map[string]interface{}{ + "view": map[string]interface{}{ + "projectId": getTestProjectFromEnv(), + "datasetId": datasetID2, + "tableId": tableID, + }, + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDatasetAccess_view(datasetID, datasetID2, tableID), + Check: testAccCheckBigQueryDatasetAccessPresent("google_bigquery_dataset.private", expected), + }, + { + Config: testAccBigQueryDatasetAccess_destroy(datasetID, "private"), + Check: testAccCheckBigQueryDatasetAccessAbsent("google_bigquery_dataset.private", expected), + }, + }, + }) +} + +func TestAccBigQueryDatasetAccess_multiple(t *testing.T) { + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(10)) + + expected1 := map[string]interface{}{ + "role": "WRITER", + "domain": "google.com", + } + + expected2 := map[string]interface{}{ + "role": "READER", + "specialGroup": "projectWriters", + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDatasetAccess_multiple(datasetID), + Check: resource.ComposeTestCheckFunc( + testAccCheckBigQueryDatasetAccessPresent("google_bigquery_dataset.dataset", expected1), + testAccCheckBigQueryDatasetAccessPresent("google_bigquery_dataset.dataset", expected2), + ), + }, + { + // Destroy step instead of CheckDestroy so we can check the access is removed without deleting the dataset + Config: testAccBigQueryDatasetAccess_destroy(datasetID, "dataset"), + Check: resource.ComposeTestCheckFunc( + testAccCheckBigQueryDatasetAccessAbsent("google_bigquery_dataset.dataset", expected1), + testAccCheckBigQueryDatasetAccessAbsent("google_bigquery_dataset.dataset", expected2), + ), + }, + }, + }) +} + +func testAccCheckBigQueryDatasetAccessPresent(n string, expected map[string]interface{}) resource.TestCheckFunc { + return testAccCheckBigQueryDatasetAccess(n, expected, true) +} + +func testAccCheckBigQueryDatasetAccessAbsent(n string, expected map[string]interface{}) resource.TestCheckFunc { + return testAccCheckBigQueryDatasetAccess(n, expected, false) +} + +func testAccCheckBigQueryDatasetAccess(n string, expected map[string]interface{}, expectPresent bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + config := testAccProvider.Meta().(*Config) + url, err := replaceVarsForTest(config, rs, "{{BigQueryBasePath}}projects/{{project}}/datasets/{{dataset_id}}") + if err != nil { + return err + } + + ds, err := sendRequest(config, "GET", "", url, nil) + if err != nil { + return err + } + access := ds["access"].([]interface{}) + for _, a := range access { + if reflect.DeepEqual(a, expected) { + if !expectPresent { + return fmt.Errorf("Found access %+v, expected not present", expected) + } + return nil + } + } + if expectPresent { + return fmt.Errorf("Did not find access %+v, expected present", expected) + } + return nil + } +} + +func testAccBigQueryDatasetAccess_destroy(datasetID, rs string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "%s" { + dataset_id = "%s" +} +`, rs, datasetID) +} + +func testAccBigQueryDatasetAccess_basic(datasetID, saID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "OWNER" + user_by_email = google_service_account.bqowner.email +} + +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} + +resource "google_service_account" "bqowner" { + account_id = "%s" +} +`, datasetID, saID) +} + +func testAccBigQueryDatasetAccess_view(datasetID, datasetID2, tableID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.private.dataset_id + view { + project_id = google_bigquery_table.public.project + dataset_id = google_bigquery_dataset.public.dataset_id + table_id = google_bigquery_table.public.table_id + } +} + +resource "google_bigquery_dataset" "private" { + dataset_id = "%s" +} + +resource "google_bigquery_dataset" "public" { + dataset_id = "%s" +} + +resource "google_bigquery_table" "public" { + dataset_id = google_bigquery_dataset.public.dataset_id + table_id = "%s" + + view { + query = "%s" + use_legacy_sql = false + } +} + +`, datasetID, datasetID2, tableID, "SELECT state FROM `lookerdata.cdc.project_tycho_reports`") +} + +func testAccBigQueryDatasetAccess_multiple(datasetID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "WRITER" + domain = "google.com" +} + +resource "google_bigquery_dataset_access" "access2" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "READER" + special_group = "projectWriters" +} + +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} +`, datasetID) +} diff --git a/google-beta/resource_compute_backend_bucket_signed_url_key.go b/google-beta/resource_compute_backend_bucket_signed_url_key.go index c3c49903f0..9f72f66e83 100644 --- a/google-beta/resource_compute_backend_bucket_signed_url_key.go +++ b/google-beta/resource_compute_backend_bucket_signed_url_key.go @@ -71,19 +71,19 @@ func resourceComputeBackendBucketSignedUrlKeyCreate(d *schema.ResourceData, meta config := meta.(*Config) obj := make(map[string]interface{}) - keyNameProp, err := expandComputeBackendBucketSignedUrlKeyName(d.Get("name"), d, config) + keyNameProp, err := expandNestedComputeBackendBucketSignedUrlKeyName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(keyNameProp)) && (ok || !reflect.DeepEqual(v, keyNameProp)) { obj["keyName"] = keyNameProp } - keyValueProp, err := expandComputeBackendBucketSignedUrlKeyKeyValue(d.Get("key_value"), d, config) + keyValueProp, err := expandNestedComputeBackendBucketSignedUrlKeyKeyValue(d.Get("key_value"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("key_value"); !isEmptyValue(reflect.ValueOf(keyValueProp)) && (ok || !reflect.DeepEqual(v, keyValueProp)) { obj["keyValue"] = keyValueProp } - backendBucketProp, err := expandComputeBackendBucketSignedUrlKeyBackendBucket(d.Get("backend_bucket"), d, config) + backendBucketProp, err := expandNestedComputeBackendBucketSignedUrlKeyBackendBucket(d.Get("backend_bucket"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("backend_bucket"); !isEmptyValue(reflect.ValueOf(backendBucketProp)) && (ok || !reflect.DeepEqual(v, backendBucketProp)) { @@ -167,7 +167,7 @@ func resourceComputeBackendBucketSignedUrlKeyRead(d *schema.ResourceData, meta i return fmt.Errorf("Error reading BackendBucketSignedUrlKey: %s", err) } - if err := d.Set("name", flattenComputeBackendBucketSignedUrlKeyName(res["keyName"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeBackendBucketSignedUrlKeyName(res["keyName"], d, config)); err != nil { return fmt.Errorf("Error reading BackendBucketSignedUrlKey: %s", err) } @@ -214,19 +214,19 @@ func resourceComputeBackendBucketSignedUrlKeyDelete(d *schema.ResourceData, meta return nil } -func flattenComputeBackendBucketSignedUrlKeyName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeBackendBucketSignedUrlKeyName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeBackendBucketSignedUrlKeyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendBucketSignedUrlKeyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeBackendBucketSignedUrlKeyKeyValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendBucketSignedUrlKeyKeyValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeBackendBucketSignedUrlKeyBackendBucket(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendBucketSignedUrlKeyBackendBucket(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { f, err := parseGlobalFieldValue("backendBuckets", v.(string), "project", d, config, true) if err != nil { return nil, fmt.Errorf("Invalid value for backend_bucket: %s", err) @@ -269,10 +269,11 @@ func flattenNestedComputeBackendBucketSignedUrlKey(d *schema.ResourceData, meta } func resourceComputeBackendBucketSignedUrlKeyFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeBackendBucketSignedUrlKeyName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeBackendBucketSignedUrlKeyName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeBackendBucketSignedUrlKeyName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -284,9 +285,10 @@ func resourceComputeBackendBucketSignedUrlKeyFindNestedObjectInList(d *schema.Re "keyName": itemRaw, } - itemName := flattenComputeBackendBucketSignedUrlKeyName(item["keyName"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with keyName= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeBackendBucketSignedUrlKeyName(item["keyName"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with keyName= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_backend_service_signed_url_key.go b/google-beta/resource_compute_backend_service_signed_url_key.go index 28030c576a..f3fb23cfb2 100644 --- a/google-beta/resource_compute_backend_service_signed_url_key.go +++ b/google-beta/resource_compute_backend_service_signed_url_key.go @@ -71,19 +71,19 @@ func resourceComputeBackendServiceSignedUrlKeyCreate(d *schema.ResourceData, met config := meta.(*Config) obj := make(map[string]interface{}) - keyNameProp, err := expandComputeBackendServiceSignedUrlKeyName(d.Get("name"), d, config) + keyNameProp, err := expandNestedComputeBackendServiceSignedUrlKeyName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(keyNameProp)) && (ok || !reflect.DeepEqual(v, keyNameProp)) { obj["keyName"] = keyNameProp } - keyValueProp, err := expandComputeBackendServiceSignedUrlKeyKeyValue(d.Get("key_value"), d, config) + keyValueProp, err := expandNestedComputeBackendServiceSignedUrlKeyKeyValue(d.Get("key_value"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("key_value"); !isEmptyValue(reflect.ValueOf(keyValueProp)) && (ok || !reflect.DeepEqual(v, keyValueProp)) { obj["keyValue"] = keyValueProp } - backendServiceProp, err := expandComputeBackendServiceSignedUrlKeyBackendService(d.Get("backend_service"), d, config) + backendServiceProp, err := expandNestedComputeBackendServiceSignedUrlKeyBackendService(d.Get("backend_service"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("backend_service"); !isEmptyValue(reflect.ValueOf(backendServiceProp)) && (ok || !reflect.DeepEqual(v, backendServiceProp)) { @@ -167,7 +167,7 @@ func resourceComputeBackendServiceSignedUrlKeyRead(d *schema.ResourceData, meta return fmt.Errorf("Error reading BackendServiceSignedUrlKey: %s", err) } - if err := d.Set("name", flattenComputeBackendServiceSignedUrlKeyName(res["keyName"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeBackendServiceSignedUrlKeyName(res["keyName"], d, config)); err != nil { return fmt.Errorf("Error reading BackendServiceSignedUrlKey: %s", err) } @@ -214,19 +214,19 @@ func resourceComputeBackendServiceSignedUrlKeyDelete(d *schema.ResourceData, met return nil } -func flattenComputeBackendServiceSignedUrlKeyName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeBackendServiceSignedUrlKeyName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeBackendServiceSignedUrlKeyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendServiceSignedUrlKeyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeBackendServiceSignedUrlKeyKeyValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendServiceSignedUrlKeyKeyValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeBackendServiceSignedUrlKeyBackendService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeBackendServiceSignedUrlKeyBackendService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { f, err := parseGlobalFieldValue("backendServices", v.(string), "project", d, config, true) if err != nil { return nil, fmt.Errorf("Invalid value for backend_service: %s", err) @@ -269,10 +269,11 @@ func flattenNestedComputeBackendServiceSignedUrlKey(d *schema.ResourceData, meta } func resourceComputeBackendServiceSignedUrlKeyFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeBackendServiceSignedUrlKeyName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeBackendServiceSignedUrlKeyName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeBackendServiceSignedUrlKeyName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -284,9 +285,10 @@ func resourceComputeBackendServiceSignedUrlKeyFindNestedObjectInList(d *schema.R "keyName": itemRaw, } - itemName := flattenComputeBackendServiceSignedUrlKeyName(item["keyName"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with keyName= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeBackendServiceSignedUrlKeyName(item["keyName"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with keyName= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_disk_resource_policy_attachment.go b/google-beta/resource_compute_disk_resource_policy_attachment.go index 8e28046cb3..b83744eb61 100644 --- a/google-beta/resource_compute_disk_resource_policy_attachment.go +++ b/google-beta/resource_compute_disk_resource_policy_attachment.go @@ -75,7 +75,7 @@ func resourceComputeDiskResourcePolicyAttachmentCreate(d *schema.ResourceData, m config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) + nameProp, err := expandNestedComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { @@ -169,7 +169,7 @@ func resourceComputeDiskResourcePolicyAttachmentRead(d *schema.ResourceData, met return fmt.Errorf("Error reading DiskResourcePolicyAttachment: %s", err) } - if err := d.Set("name", flattenComputeDiskResourcePolicyAttachmentName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeDiskResourcePolicyAttachmentName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading DiskResourcePolicyAttachment: %s", err) } @@ -208,7 +208,7 @@ func resourceComputeDiskResourcePolicyAttachmentDelete(d *schema.ResourceData, m return fmt.Errorf("invalid zone %q, unable to infer region from zone", zone) } - name, err := expandComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) + name, err := expandNestedComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(name)) && (ok || !reflect.DeepEqual(v, name)) { @@ -254,11 +254,11 @@ func resourceComputeDiskResourcePolicyAttachmentImport(d *schema.ResourceData, m return []*schema.ResourceData{d}, nil } -func flattenComputeDiskResourcePolicyAttachmentName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeDiskResourcePolicyAttachmentName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeDiskResourcePolicyAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeDiskResourcePolicyAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -319,10 +319,11 @@ func flattenNestedComputeDiskResourcePolicyAttachment(d *schema.ResourceData, me } func resourceComputeDiskResourcePolicyAttachmentFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeDiskResourcePolicyAttachmentName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -340,9 +341,10 @@ func resourceComputeDiskResourcePolicyAttachmentFindNestedObjectInList(d *schema return -1, nil, err } - itemName := flattenComputeDiskResourcePolicyAttachmentName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeDiskResourcePolicyAttachmentName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_instance_group_named_port.go b/google-beta/resource_compute_instance_group_named_port.go index 1f5603faca..dbad070fdd 100644 --- a/google-beta/resource_compute_instance_group_named_port.go +++ b/google-beta/resource_compute_instance_group_named_port.go @@ -83,13 +83,13 @@ func resourceComputeInstanceGroupNamedPortCreate(d *schema.ResourceData, meta in config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeInstanceGroupNamedPortName(d.Get("name"), d, config) + nameProp, err := expandNestedComputeInstanceGroupNamedPortName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { obj["name"] = nameProp } - portProp, err := expandComputeInstanceGroupNamedPortPort(d.Get("port"), d, config) + portProp, err := expandNestedComputeInstanceGroupNamedPortPort(d.Get("port"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("port"); !isEmptyValue(reflect.ValueOf(portProp)) && (ok || !reflect.DeepEqual(v, portProp)) { @@ -183,10 +183,10 @@ func resourceComputeInstanceGroupNamedPortRead(d *schema.ResourceData, meta inte return fmt.Errorf("Error reading InstanceGroupNamedPort: %s", err) } - if err := d.Set("name", flattenComputeInstanceGroupNamedPortName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeInstanceGroupNamedPortName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading InstanceGroupNamedPort: %s", err) } - if err := d.Set("port", flattenComputeInstanceGroupNamedPortPort(res["port"], d, config)); err != nil { + if err := d.Set("port", flattenNestedComputeInstanceGroupNamedPortPort(res["port"], d, config)); err != nil { return fmt.Errorf("Error reading InstanceGroupNamedPort: %s", err) } @@ -259,11 +259,11 @@ func resourceComputeInstanceGroupNamedPortImport(d *schema.ResourceData, meta in return []*schema.ResourceData{d}, nil } -func flattenComputeInstanceGroupNamedPortName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeInstanceGroupNamedPortName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeInstanceGroupNamedPortPort(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeInstanceGroupNamedPortPort(v interface{}, d *schema.ResourceData, config *Config) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -280,11 +280,11 @@ func flattenComputeInstanceGroupNamedPortPort(v interface{}, d *schema.ResourceD return v // let terraform core handle it otherwise } -func expandComputeInstanceGroupNamedPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeInstanceGroupNamedPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeInstanceGroupNamedPortPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeInstanceGroupNamedPortPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -331,14 +331,16 @@ func flattenNestedComputeInstanceGroupNamedPort(d *schema.ResourceData, meta int } func resourceComputeInstanceGroupNamedPortFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedPort, err := expandComputeInstanceGroupNamedPortPort(d.Get("port"), d, meta.(*Config)) + expectedPort, err := expandNestedComputeInstanceGroupNamedPortPort(d.Get("port"), d, meta.(*Config)) if err != nil { return -1, nil, err } - expectedName, err := expandComputeInstanceGroupNamedPortName(d.Get("name"), d, meta.(*Config)) + expectedFlattenedPort := flattenNestedComputeInstanceGroupNamedPortPort(expectedPort, d, meta.(*Config)) + expectedName, err := expandNestedComputeInstanceGroupNamedPortName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeInstanceGroupNamedPortName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -347,14 +349,16 @@ func resourceComputeInstanceGroupNamedPortFindNestedObjectInList(d *schema.Resou } item := itemRaw.(map[string]interface{}) - itemPort := flattenComputeInstanceGroupNamedPortPort(item["port"], d, meta.(*Config)) - if !reflect.DeepEqual(itemPort, expectedPort) { - log.Printf("[DEBUG] Skipping item with port= %#v, looking for %#v)", itemPort, expectedPort) + itemPort := flattenNestedComputeInstanceGroupNamedPortPort(item["port"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemPort)) && isEmptyValue(reflect.ValueOf(expectedFlattenedPort))) && !reflect.DeepEqual(itemPort, expectedFlattenedPort) { + log.Printf("[DEBUG] Skipping item with port= %#v, looking for %#v)", itemPort, expectedFlattenedPort) continue } - itemName := flattenComputeInstanceGroupNamedPortName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeInstanceGroupNamedPortName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_network_endpoint.go b/google-beta/resource_compute_network_endpoint.go index 4ffbbcd285..8b0f5f2038 100644 --- a/google-beta/resource_compute_network_endpoint.go +++ b/google-beta/resource_compute_network_endpoint.go @@ -91,19 +91,19 @@ func resourceComputeNetworkEndpointCreate(d *schema.ResourceData, meta interface config := meta.(*Config) obj := make(map[string]interface{}) - instanceProp, err := expandComputeNetworkEndpointInstance(d.Get("instance"), d, config) + instanceProp, err := expandNestedComputeNetworkEndpointInstance(d.Get("instance"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("instance"); !isEmptyValue(reflect.ValueOf(instanceProp)) && (ok || !reflect.DeepEqual(v, instanceProp)) { obj["instance"] = instanceProp } - portProp, err := expandComputeNetworkEndpointPort(d.Get("port"), d, config) + portProp, err := expandNestedComputeNetworkEndpointPort(d.Get("port"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("port"); !isEmptyValue(reflect.ValueOf(portProp)) && (ok || !reflect.DeepEqual(v, portProp)) { obj["port"] = portProp } - ipAddressProp, err := expandComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, config) + ipAddressProp, err := expandNestedComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("ip_address"); !isEmptyValue(reflect.ValueOf(ipAddressProp)) && (ok || !reflect.DeepEqual(v, ipAddressProp)) { @@ -204,13 +204,13 @@ func resourceComputeNetworkEndpointRead(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error reading NetworkEndpoint: %s", err) } - if err := d.Set("instance", flattenComputeNetworkEndpointInstance(res["instance"], d, config)); err != nil { + if err := d.Set("instance", flattenNestedComputeNetworkEndpointInstance(res["instance"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkEndpoint: %s", err) } - if err := d.Set("port", flattenComputeNetworkEndpointPort(res["port"], d, config)); err != nil { + if err := d.Set("port", flattenNestedComputeNetworkEndpointPort(res["port"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkEndpoint: %s", err) } - if err := d.Set("ip_address", flattenComputeNetworkEndpointIpAddress(res["ipAddress"], d, config)); err != nil { + if err := d.Set("ip_address", flattenNestedComputeNetworkEndpointIpAddress(res["ipAddress"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkEndpoint: %s", err) } @@ -239,19 +239,19 @@ func resourceComputeNetworkEndpointDelete(d *schema.ResourceData, meta interface var obj map[string]interface{} toDelete := make(map[string]interface{}) - instanceProp, err := expandComputeNetworkEndpointInstance(d.Get("instance"), d, config) + instanceProp, err := expandNestedComputeNetworkEndpointInstance(d.Get("instance"), d, config) if err != nil { return err } toDelete["instance"] = instanceProp - portProp, err := expandComputeNetworkEndpointPort(d.Get("port"), d, config) + portProp, err := expandNestedComputeNetworkEndpointPort(d.Get("port"), d, config) if err != nil { return err } toDelete["port"] = portProp - ipAddressProp, err := expandComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, config) + ipAddressProp, err := expandNestedComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, config) if err != nil { return err } @@ -300,14 +300,14 @@ func resourceComputeNetworkEndpointImport(d *schema.ResourceData, meta interface return []*schema.ResourceData{d}, nil } -func flattenComputeNetworkEndpointInstance(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkEndpointInstance(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return ConvertSelfLinkToV1(v.(string)) } -func flattenComputeNetworkEndpointPort(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkEndpointPort(v interface{}, d *schema.ResourceData, config *Config) interface{} { // Handles int given in float64 format if floatVal, ok := v.(float64); ok { return int(floatVal) @@ -315,19 +315,19 @@ func flattenComputeNetworkEndpointPort(v interface{}, d *schema.ResourceData, co return v } -func flattenComputeNetworkEndpointIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkEndpointIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeNetworkEndpointInstance(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkEndpointInstance(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return GetResourceNameFromSelfLink(v.(string)), nil } -func expandComputeNetworkEndpointPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkEndpointPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeNetworkEndpointIpAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkEndpointIpAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -370,18 +370,21 @@ func flattenNestedComputeNetworkEndpoint(d *schema.ResourceData, meta interface{ } func resourceComputeNetworkEndpointFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedInstance, err := expandComputeNetworkEndpointInstance(d.Get("instance"), d, meta.(*Config)) + expectedInstance, err := expandNestedComputeNetworkEndpointInstance(d.Get("instance"), d, meta.(*Config)) if err != nil { return -1, nil, err } - expectedIpAddress, err := expandComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, meta.(*Config)) + expectedFlattenedInstance := flattenNestedComputeNetworkEndpointInstance(expectedInstance, d, meta.(*Config)) + expectedIpAddress, err := expandNestedComputeNetworkEndpointIpAddress(d.Get("ip_address"), d, meta.(*Config)) if err != nil { return -1, nil, err } - expectedPort, err := expandComputeNetworkEndpointPort(d.Get("port"), d, meta.(*Config)) + expectedFlattenedIpAddress := flattenNestedComputeNetworkEndpointIpAddress(expectedIpAddress, d, meta.(*Config)) + expectedPort, err := expandNestedComputeNetworkEndpointPort(d.Get("port"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedPort := flattenNestedComputeNetworkEndpointPort(expectedPort, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -396,19 +399,22 @@ func resourceComputeNetworkEndpointFindNestedObjectInList(d *schema.ResourceData return -1, nil, err } - itemInstance := flattenComputeNetworkEndpointInstance(item["instance"], d, meta.(*Config)) - if !reflect.DeepEqual(itemInstance, expectedInstance) { - log.Printf("[DEBUG] Skipping item with instance= %#v, looking for %#v)", itemInstance, expectedInstance) + itemInstance := flattenNestedComputeNetworkEndpointInstance(item["instance"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemInstance)) && isEmptyValue(reflect.ValueOf(expectedFlattenedInstance))) && !reflect.DeepEqual(itemInstance, expectedFlattenedInstance) { + log.Printf("[DEBUG] Skipping item with instance= %#v, looking for %#v)", itemInstance, expectedFlattenedInstance) continue } - itemIpAddress := flattenComputeNetworkEndpointIpAddress(item["ipAddress"], d, meta.(*Config)) - if !reflect.DeepEqual(itemIpAddress, expectedIpAddress) { - log.Printf("[DEBUG] Skipping item with ipAddress= %#v, looking for %#v)", itemIpAddress, expectedIpAddress) + itemIpAddress := flattenNestedComputeNetworkEndpointIpAddress(item["ipAddress"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemIpAddress)) && isEmptyValue(reflect.ValueOf(expectedFlattenedIpAddress))) && !reflect.DeepEqual(itemIpAddress, expectedFlattenedIpAddress) { + log.Printf("[DEBUG] Skipping item with ipAddress= %#v, looking for %#v)", itemIpAddress, expectedFlattenedIpAddress) continue } - itemPort := flattenComputeNetworkEndpointPort(item["port"], d, meta.(*Config)) - if !reflect.DeepEqual(itemPort, expectedPort) { - log.Printf("[DEBUG] Skipping item with port= %#v, looking for %#v)", itemPort, expectedPort) + itemPort := flattenNestedComputeNetworkEndpointPort(item["port"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemPort)) && isEmptyValue(reflect.ValueOf(expectedFlattenedPort))) && !reflect.DeepEqual(itemPort, expectedFlattenedPort) { + log.Printf("[DEBUG] Skipping item with port= %#v, looking for %#v)", itemPort, expectedFlattenedPort) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_network_peering_routes_config.go b/google-beta/resource_compute_network_peering_routes_config.go index d396109262..20aee31c82 100644 --- a/google-beta/resource_compute_network_peering_routes_config.go +++ b/google-beta/resource_compute_network_peering_routes_config.go @@ -76,19 +76,19 @@ func resourceComputeNetworkPeeringRoutesConfigCreate(d *schema.ResourceData, met config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, config) + nameProp, err := expandNestedComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("peering"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { obj["name"] = nameProp } - exportCustomRoutesProp, err := expandComputeNetworkPeeringRoutesConfigExportCustomRoutes(d.Get("export_custom_routes"), d, config) + exportCustomRoutesProp, err := expandNestedComputeNetworkPeeringRoutesConfigExportCustomRoutes(d.Get("export_custom_routes"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("export_custom_routes"); !isEmptyValue(reflect.ValueOf(exportCustomRoutesProp)) && (ok || !reflect.DeepEqual(v, exportCustomRoutesProp)) { obj["exportCustomRoutes"] = exportCustomRoutesProp } - importCustomRoutesProp, err := expandComputeNetworkPeeringRoutesConfigImportCustomRoutes(d.Get("import_custom_routes"), d, config) + importCustomRoutesProp, err := expandNestedComputeNetworkPeeringRoutesConfigImportCustomRoutes(d.Get("import_custom_routes"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("import_custom_routes"); !isEmptyValue(reflect.ValueOf(importCustomRoutesProp)) && (ok || !reflect.DeepEqual(v, importCustomRoutesProp)) { @@ -177,13 +177,13 @@ func resourceComputeNetworkPeeringRoutesConfigRead(d *schema.ResourceData, meta return fmt.Errorf("Error reading NetworkPeeringRoutesConfig: %s", err) } - if err := d.Set("peering", flattenComputeNetworkPeeringRoutesConfigPeering(res["name"], d, config)); err != nil { + if err := d.Set("peering", flattenNestedComputeNetworkPeeringRoutesConfigPeering(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkPeeringRoutesConfig: %s", err) } - if err := d.Set("export_custom_routes", flattenComputeNetworkPeeringRoutesConfigExportCustomRoutes(res["exportCustomRoutes"], d, config)); err != nil { + if err := d.Set("export_custom_routes", flattenNestedComputeNetworkPeeringRoutesConfigExportCustomRoutes(res["exportCustomRoutes"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkPeeringRoutesConfig: %s", err) } - if err := d.Set("import_custom_routes", flattenComputeNetworkPeeringRoutesConfigImportCustomRoutes(res["importCustomRoutes"], d, config)); err != nil { + if err := d.Set("import_custom_routes", flattenNestedComputeNetworkPeeringRoutesConfigImportCustomRoutes(res["importCustomRoutes"], d, config)); err != nil { return fmt.Errorf("Error reading NetworkPeeringRoutesConfig: %s", err) } @@ -199,19 +199,19 @@ func resourceComputeNetworkPeeringRoutesConfigUpdate(d *schema.ResourceData, met } obj := make(map[string]interface{}) - nameProp, err := expandComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, config) + nameProp, err := expandNestedComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("peering"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { obj["name"] = nameProp } - exportCustomRoutesProp, err := expandComputeNetworkPeeringRoutesConfigExportCustomRoutes(d.Get("export_custom_routes"), d, config) + exportCustomRoutesProp, err := expandNestedComputeNetworkPeeringRoutesConfigExportCustomRoutes(d.Get("export_custom_routes"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("export_custom_routes"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, exportCustomRoutesProp)) { obj["exportCustomRoutes"] = exportCustomRoutesProp } - importCustomRoutesProp, err := expandComputeNetworkPeeringRoutesConfigImportCustomRoutes(d.Get("import_custom_routes"), d, config) + importCustomRoutesProp, err := expandNestedComputeNetworkPeeringRoutesConfigImportCustomRoutes(d.Get("import_custom_routes"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("import_custom_routes"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, importCustomRoutesProp)) { @@ -282,27 +282,27 @@ func resourceComputeNetworkPeeringRoutesConfigImport(d *schema.ResourceData, met return []*schema.ResourceData{d}, nil } -func flattenComputeNetworkPeeringRoutesConfigPeering(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkPeeringRoutesConfigPeering(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeNetworkPeeringRoutesConfigExportCustomRoutes(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkPeeringRoutesConfigExportCustomRoutes(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeNetworkPeeringRoutesConfigImportCustomRoutes(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeNetworkPeeringRoutesConfigImportCustomRoutes(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeNetworkPeeringRoutesConfigPeering(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkPeeringRoutesConfigPeering(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeNetworkPeeringRoutesConfigExportCustomRoutes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkPeeringRoutesConfigExportCustomRoutes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeNetworkPeeringRoutesConfigImportCustomRoutes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeNetworkPeeringRoutesConfigImportCustomRoutes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -343,10 +343,11 @@ func flattenNestedComputeNetworkPeeringRoutesConfig(d *schema.ResourceData, meta } func resourceComputeNetworkPeeringRoutesConfigFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedPeering, err := expandComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, meta.(*Config)) + expectedPeering, err := expandNestedComputeNetworkPeeringRoutesConfigPeering(d.Get("peering"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedPeering := flattenNestedComputeNetworkPeeringRoutesConfigPeering(expectedPeering, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -355,9 +356,10 @@ func resourceComputeNetworkPeeringRoutesConfigFindNestedObjectInList(d *schema.R } item := itemRaw.(map[string]interface{}) - itemPeering := flattenComputeNetworkPeeringRoutesConfigPeering(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemPeering, expectedPeering) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemPeering, expectedPeering) + itemPeering := flattenNestedComputeNetworkPeeringRoutesConfigPeering(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemPeering)) && isEmptyValue(reflect.ValueOf(expectedFlattenedPeering))) && !reflect.DeepEqual(itemPeering, expectedFlattenedPeering) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemPeering, expectedFlattenedPeering) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_region_disk_resource_policy_attachment.go b/google-beta/resource_compute_region_disk_resource_policy_attachment.go index 54abf96ab1..2d33c2a054 100644 --- a/google-beta/resource_compute_region_disk_resource_policy_attachment.go +++ b/google-beta/resource_compute_region_disk_resource_policy_attachment.go @@ -75,7 +75,7 @@ func resourceComputeRegionDiskResourcePolicyAttachmentCreate(d *schema.ResourceD config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeRegionDiskResourcePolicyAttachmentName(d.Get("name"), d, config) + nameProp, err := expandNestedComputeRegionDiskResourcePolicyAttachmentName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { @@ -169,7 +169,7 @@ func resourceComputeRegionDiskResourcePolicyAttachmentRead(d *schema.ResourceDat return fmt.Errorf("Error reading RegionDiskResourcePolicyAttachment: %s", err) } - if err := d.Set("name", flattenComputeRegionDiskResourcePolicyAttachmentName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeRegionDiskResourcePolicyAttachmentName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading RegionDiskResourcePolicyAttachment: %s", err) } @@ -200,7 +200,7 @@ func resourceComputeRegionDiskResourcePolicyAttachmentDelete(d *schema.ResourceD return fmt.Errorf("region must be non-empty - set in resource or at provider-level") } - name, err := expandComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) + name, err := expandNestedComputeDiskResourcePolicyAttachmentName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(name)) && (ok || !reflect.DeepEqual(v, name)) { @@ -246,11 +246,11 @@ func resourceComputeRegionDiskResourcePolicyAttachmentImport(d *schema.ResourceD return []*schema.ResourceData{d}, nil } -func flattenComputeRegionDiskResourcePolicyAttachmentName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRegionDiskResourcePolicyAttachmentName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeRegionDiskResourcePolicyAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRegionDiskResourcePolicyAttachmentName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -303,10 +303,11 @@ func flattenNestedComputeRegionDiskResourcePolicyAttachment(d *schema.ResourceDa } func resourceComputeRegionDiskResourcePolicyAttachmentFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeRegionDiskResourcePolicyAttachmentName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeRegionDiskResourcePolicyAttachmentName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeRegionDiskResourcePolicyAttachmentName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -324,9 +325,10 @@ func resourceComputeRegionDiskResourcePolicyAttachmentFindNestedObjectInList(d * return -1, nil, err } - itemName := flattenComputeRegionDiskResourcePolicyAttachmentName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeRegionDiskResourcePolicyAttachmentName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_router_bgp_peer.go b/google-beta/resource_compute_router_bgp_peer.go index a6594052fb..63875c398f 100644 --- a/google-beta/resource_compute_router_bgp_peer.go +++ b/google-beta/resource_compute_router_bgp_peer.go @@ -186,49 +186,49 @@ func resourceComputeRouterBgpPeerCreate(d *schema.ResourceData, meta interface{} config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeRouterBgpPeerName(d.Get("name"), d, config) + nameProp, err := expandNestedComputeRouterBgpPeerName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { obj["name"] = nameProp } - interfaceNameProp, err := expandComputeRouterBgpPeerInterface(d.Get("interface"), d, config) + interfaceNameProp, err := expandNestedComputeRouterBgpPeerInterface(d.Get("interface"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("interface"); !isEmptyValue(reflect.ValueOf(interfaceNameProp)) && (ok || !reflect.DeepEqual(v, interfaceNameProp)) { obj["interfaceName"] = interfaceNameProp } - peerIpAddressProp, err := expandComputeRouterBgpPeerPeerIpAddress(d.Get("peer_ip_address"), d, config) + peerIpAddressProp, err := expandNestedComputeRouterBgpPeerPeerIpAddress(d.Get("peer_ip_address"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("peer_ip_address"); !isEmptyValue(reflect.ValueOf(peerIpAddressProp)) && (ok || !reflect.DeepEqual(v, peerIpAddressProp)) { obj["peerIpAddress"] = peerIpAddressProp } - peerAsnProp, err := expandComputeRouterBgpPeerPeerAsn(d.Get("peer_asn"), d, config) + peerAsnProp, err := expandNestedComputeRouterBgpPeerPeerAsn(d.Get("peer_asn"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("peer_asn"); !isEmptyValue(reflect.ValueOf(peerAsnProp)) && (ok || !reflect.DeepEqual(v, peerAsnProp)) { obj["peerAsn"] = peerAsnProp } - advertisedRoutePriorityProp, err := expandComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) + advertisedRoutePriorityProp, err := expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertised_route_priority"); !isEmptyValue(reflect.ValueOf(advertisedRoutePriorityProp)) && (ok || !reflect.DeepEqual(v, advertisedRoutePriorityProp)) { obj["advertisedRoutePriority"] = advertisedRoutePriorityProp } - advertiseModeProp, err := expandComputeRouterBgpPeerAdvertiseMode(d.Get("advertise_mode"), d, config) + advertiseModeProp, err := expandNestedComputeRouterBgpPeerAdvertiseMode(d.Get("advertise_mode"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertise_mode"); !isEmptyValue(reflect.ValueOf(advertiseModeProp)) && (ok || !reflect.DeepEqual(v, advertiseModeProp)) { obj["advertiseMode"] = advertiseModeProp } - advertisedGroupsProp, err := expandComputeRouterBgpPeerAdvertisedGroups(d.Get("advertised_groups"), d, config) + advertisedGroupsProp, err := expandNestedComputeRouterBgpPeerAdvertisedGroups(d.Get("advertised_groups"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertised_groups"); ok || !reflect.DeepEqual(v, advertisedGroupsProp) { obj["advertisedGroups"] = advertisedGroupsProp } - advertisedIpRangesProp, err := expandComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) + advertisedIpRangesProp, err := expandNestedComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) { @@ -317,34 +317,34 @@ func resourceComputeRouterBgpPeerRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("name", flattenComputeRouterBgpPeerName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeRouterBgpPeerName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("interface", flattenComputeRouterBgpPeerInterface(res["interfaceName"], d, config)); err != nil { + if err := d.Set("interface", flattenNestedComputeRouterBgpPeerInterface(res["interfaceName"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("ip_address", flattenComputeRouterBgpPeerIpAddress(res["ipAddress"], d, config)); err != nil { + if err := d.Set("ip_address", flattenNestedComputeRouterBgpPeerIpAddress(res["ipAddress"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("peer_ip_address", flattenComputeRouterBgpPeerPeerIpAddress(res["peerIpAddress"], d, config)); err != nil { + if err := d.Set("peer_ip_address", flattenNestedComputeRouterBgpPeerPeerIpAddress(res["peerIpAddress"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("peer_asn", flattenComputeRouterBgpPeerPeerAsn(res["peerAsn"], d, config)); err != nil { + if err := d.Set("peer_asn", flattenNestedComputeRouterBgpPeerPeerAsn(res["peerAsn"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("advertised_route_priority", flattenComputeRouterBgpPeerAdvertisedRoutePriority(res["advertisedRoutePriority"], d, config)); err != nil { + if err := d.Set("advertised_route_priority", flattenNestedComputeRouterBgpPeerAdvertisedRoutePriority(res["advertisedRoutePriority"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("advertise_mode", flattenComputeRouterBgpPeerAdvertiseMode(res["advertiseMode"], d, config)); err != nil { + if err := d.Set("advertise_mode", flattenNestedComputeRouterBgpPeerAdvertiseMode(res["advertiseMode"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("advertised_groups", flattenComputeRouterBgpPeerAdvertisedGroups(res["advertisedGroups"], d, config)); err != nil { + if err := d.Set("advertised_groups", flattenNestedComputeRouterBgpPeerAdvertisedGroups(res["advertisedGroups"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("advertised_ip_ranges", flattenComputeRouterBgpPeerAdvertisedIpRanges(res["advertisedIpRanges"], d, config)); err != nil { + if err := d.Set("advertised_ip_ranges", flattenNestedComputeRouterBgpPeerAdvertisedIpRanges(res["advertisedIpRanges"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } - if err := d.Set("management_type", flattenComputeRouterBgpPeerManagementType(res["managementType"], d, config)); err != nil { + if err := d.Set("management_type", flattenNestedComputeRouterBgpPeerManagementType(res["managementType"], d, config)); err != nil { return fmt.Errorf("Error reading RouterBgpPeer: %s", err) } @@ -360,13 +360,13 @@ func resourceComputeRouterBgpPeerUpdate(d *schema.ResourceData, meta interface{} } obj := make(map[string]interface{}) - advertisedRoutePriorityProp, err := expandComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) + advertisedRoutePriorityProp, err := expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertised_route_priority"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, advertisedRoutePriorityProp)) { obj["advertisedRoutePriority"] = advertisedRoutePriorityProp } - advertisedIpRangesProp, err := expandComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) + advertisedIpRangesProp, err := expandNestedComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) { @@ -474,23 +474,23 @@ func resourceComputeRouterBgpPeerImport(d *schema.ResourceData, meta interface{} return []*schema.ResourceData{d}, nil } -func flattenComputeRouterBgpPeerName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerInterface(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerInterface(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerPeerIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerPeerIpAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerPeerAsn(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerPeerAsn(v interface{}, d *schema.ResourceData, config *Config) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -507,7 +507,7 @@ func flattenComputeRouterBgpPeerPeerAsn(v interface{}, d *schema.ResourceData, c return v // let terraform core handle it otherwise } -func flattenComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d *schema.ResourceData, config *Config) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -524,15 +524,15 @@ func flattenComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d *schema return v // let terraform core handle it otherwise } -func flattenComputeRouterBgpPeerAdvertiseMode(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertiseMode(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerAdvertisedGroups(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertisedGroups(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } @@ -545,53 +545,53 @@ func flattenComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d *schema.Reso continue } transformed = append(transformed, map[string]interface{}{ - "range": flattenComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config), - "description": flattenComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config), + "range": flattenNestedComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config), + "description": flattenNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config), }) } return transformed } -func flattenComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterBgpPeerManagementType(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterBgpPeerManagementType(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeRouterBgpPeerName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerInterface(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerInterface(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerPeerIpAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerPeerIpAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerPeerAsn(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerPeerAsn(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerAdvertiseMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertiseMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerAdvertisedGroups(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertisedGroups(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -601,14 +601,14 @@ func expandComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d TerraformReso original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedRange, err := expandComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config) + transformedRange, err := expandNestedComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedRange); val.IsValid() && !isEmptyValue(val) { transformed["range"] = transformedRange } - transformedDescription, err := expandComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config) + transformedDescription, err := expandNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config) if err != nil { return nil, err } else { @@ -620,11 +620,11 @@ func expandComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d TerraformReso return req, nil } -func expandComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -657,10 +657,11 @@ func flattenNestedComputeRouterBgpPeer(d *schema.ResourceData, meta interface{}, } func resourceComputeRouterBgpPeerFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeRouterBgpPeerName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeRouterBgpPeerName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeRouterBgpPeerName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -669,9 +670,10 @@ func resourceComputeRouterBgpPeerFindNestedObjectInList(d *schema.ResourceData, } item := itemRaw.(map[string]interface{}) - itemName := flattenComputeRouterBgpPeerName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeRouterBgpPeerName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_compute_router_nat.go b/google-beta/resource_compute_router_nat.go index 13eca45c03..7101eee9cf 100644 --- a/google-beta/resource_compute_router_nat.go +++ b/google-beta/resource_compute_router_nat.go @@ -304,73 +304,73 @@ func resourceComputeRouterNatCreate(d *schema.ResourceData, meta interface{}) er config := meta.(*Config) obj := make(map[string]interface{}) - nameProp, err := expandComputeRouterNatName(d.Get("name"), d, config) + nameProp, err := expandNestedComputeRouterNatName(d.Get("name"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { obj["name"] = nameProp } - natIpAllocateOptionProp, err := expandComputeRouterNatNatIpAllocateOption(d.Get("nat_ip_allocate_option"), d, config) + natIpAllocateOptionProp, err := expandNestedComputeRouterNatNatIpAllocateOption(d.Get("nat_ip_allocate_option"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("nat_ip_allocate_option"); !isEmptyValue(reflect.ValueOf(natIpAllocateOptionProp)) && (ok || !reflect.DeepEqual(v, natIpAllocateOptionProp)) { obj["natIpAllocateOption"] = natIpAllocateOptionProp } - natIpsProp, err := expandComputeRouterNatNatIps(d.Get("nat_ips"), d, config) + natIpsProp, err := expandNestedComputeRouterNatNatIps(d.Get("nat_ips"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("nat_ips"); ok || !reflect.DeepEqual(v, natIpsProp) { obj["natIps"] = natIpsProp } - drainNatIpsProp, err := expandComputeRouterNatDrainNatIps(d.Get("drain_nat_ips"), d, config) + drainNatIpsProp, err := expandNestedComputeRouterNatDrainNatIps(d.Get("drain_nat_ips"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("drain_nat_ips"); ok || !reflect.DeepEqual(v, drainNatIpsProp) { obj["drainNatIps"] = drainNatIpsProp } - sourceSubnetworkIpRangesToNatProp, err := expandComputeRouterNatSourceSubnetworkIpRangesToNat(d.Get("source_subnetwork_ip_ranges_to_nat"), d, config) + sourceSubnetworkIpRangesToNatProp, err := expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat(d.Get("source_subnetwork_ip_ranges_to_nat"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("source_subnetwork_ip_ranges_to_nat"); !isEmptyValue(reflect.ValueOf(sourceSubnetworkIpRangesToNatProp)) && (ok || !reflect.DeepEqual(v, sourceSubnetworkIpRangesToNatProp)) { obj["sourceSubnetworkIpRangesToNat"] = sourceSubnetworkIpRangesToNatProp } - subnetworksProp, err := expandComputeRouterNatSubnetwork(d.Get("subnetwork"), d, config) + subnetworksProp, err := expandNestedComputeRouterNatSubnetwork(d.Get("subnetwork"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("subnetwork"); ok || !reflect.DeepEqual(v, subnetworksProp) { obj["subnetworks"] = subnetworksProp } - minPortsPerVmProp, err := expandComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config) + minPortsPerVmProp, err := expandNestedComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("min_ports_per_vm"); !isEmptyValue(reflect.ValueOf(minPortsPerVmProp)) && (ok || !reflect.DeepEqual(v, minPortsPerVmProp)) { obj["minPortsPerVm"] = minPortsPerVmProp } - udpIdleTimeoutSecProp, err := expandComputeRouterNatUdpIdleTimeoutSec(d.Get("udp_idle_timeout_sec"), d, config) + udpIdleTimeoutSecProp, err := expandNestedComputeRouterNatUdpIdleTimeoutSec(d.Get("udp_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("udp_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(udpIdleTimeoutSecProp)) && (ok || !reflect.DeepEqual(v, udpIdleTimeoutSecProp)) { obj["udpIdleTimeoutSec"] = udpIdleTimeoutSecProp } - icmpIdleTimeoutSecProp, err := expandComputeRouterNatIcmpIdleTimeoutSec(d.Get("icmp_idle_timeout_sec"), d, config) + icmpIdleTimeoutSecProp, err := expandNestedComputeRouterNatIcmpIdleTimeoutSec(d.Get("icmp_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("icmp_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(icmpIdleTimeoutSecProp)) && (ok || !reflect.DeepEqual(v, icmpIdleTimeoutSecProp)) { obj["icmpIdleTimeoutSec"] = icmpIdleTimeoutSecProp } - tcpEstablishedIdleTimeoutSecProp, err := expandComputeRouterNatTcpEstablishedIdleTimeoutSec(d.Get("tcp_established_idle_timeout_sec"), d, config) + tcpEstablishedIdleTimeoutSecProp, err := expandNestedComputeRouterNatTcpEstablishedIdleTimeoutSec(d.Get("tcp_established_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("tcp_established_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(tcpEstablishedIdleTimeoutSecProp)) && (ok || !reflect.DeepEqual(v, tcpEstablishedIdleTimeoutSecProp)) { obj["tcpEstablishedIdleTimeoutSec"] = tcpEstablishedIdleTimeoutSecProp } - tcpTransitoryIdleTimeoutSecProp, err := expandComputeRouterNatTcpTransitoryIdleTimeoutSec(d.Get("tcp_transitory_idle_timeout_sec"), d, config) + tcpTransitoryIdleTimeoutSecProp, err := expandNestedComputeRouterNatTcpTransitoryIdleTimeoutSec(d.Get("tcp_transitory_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("tcp_transitory_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(tcpTransitoryIdleTimeoutSecProp)) && (ok || !reflect.DeepEqual(v, tcpTransitoryIdleTimeoutSecProp)) { obj["tcpTransitoryIdleTimeoutSec"] = tcpTransitoryIdleTimeoutSecProp } - logConfigProp, err := expandComputeRouterNatLogConfig(d.Get("log_config"), d, config) + logConfigProp, err := expandNestedComputeRouterNatLogConfig(d.Get("log_config"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("log_config"); !isEmptyValue(reflect.ValueOf(logConfigProp)) && (ok || !reflect.DeepEqual(v, logConfigProp)) { @@ -459,40 +459,40 @@ func resourceComputeRouterNatRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("name", flattenComputeRouterNatName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedComputeRouterNatName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("nat_ip_allocate_option", flattenComputeRouterNatNatIpAllocateOption(res["natIpAllocateOption"], d, config)); err != nil { + if err := d.Set("nat_ip_allocate_option", flattenNestedComputeRouterNatNatIpAllocateOption(res["natIpAllocateOption"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("nat_ips", flattenComputeRouterNatNatIps(res["natIps"], d, config)); err != nil { + if err := d.Set("nat_ips", flattenNestedComputeRouterNatNatIps(res["natIps"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("drain_nat_ips", flattenComputeRouterNatDrainNatIps(res["drainNatIps"], d, config)); err != nil { + if err := d.Set("drain_nat_ips", flattenNestedComputeRouterNatDrainNatIps(res["drainNatIps"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("source_subnetwork_ip_ranges_to_nat", flattenComputeRouterNatSourceSubnetworkIpRangesToNat(res["sourceSubnetworkIpRangesToNat"], d, config)); err != nil { + if err := d.Set("source_subnetwork_ip_ranges_to_nat", flattenNestedComputeRouterNatSourceSubnetworkIpRangesToNat(res["sourceSubnetworkIpRangesToNat"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("subnetwork", flattenComputeRouterNatSubnetwork(res["subnetworks"], d, config)); err != nil { + if err := d.Set("subnetwork", flattenNestedComputeRouterNatSubnetwork(res["subnetworks"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("min_ports_per_vm", flattenComputeRouterNatMinPortsPerVm(res["minPortsPerVm"], d, config)); err != nil { + if err := d.Set("min_ports_per_vm", flattenNestedComputeRouterNatMinPortsPerVm(res["minPortsPerVm"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("udp_idle_timeout_sec", flattenComputeRouterNatUdpIdleTimeoutSec(res["udpIdleTimeoutSec"], d, config)); err != nil { + if err := d.Set("udp_idle_timeout_sec", flattenNestedComputeRouterNatUdpIdleTimeoutSec(res["udpIdleTimeoutSec"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("icmp_idle_timeout_sec", flattenComputeRouterNatIcmpIdleTimeoutSec(res["icmpIdleTimeoutSec"], d, config)); err != nil { + if err := d.Set("icmp_idle_timeout_sec", flattenNestedComputeRouterNatIcmpIdleTimeoutSec(res["icmpIdleTimeoutSec"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("tcp_established_idle_timeout_sec", flattenComputeRouterNatTcpEstablishedIdleTimeoutSec(res["tcpEstablishedIdleTimeoutSec"], d, config)); err != nil { + if err := d.Set("tcp_established_idle_timeout_sec", flattenNestedComputeRouterNatTcpEstablishedIdleTimeoutSec(res["tcpEstablishedIdleTimeoutSec"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("tcp_transitory_idle_timeout_sec", flattenComputeRouterNatTcpTransitoryIdleTimeoutSec(res["tcpTransitoryIdleTimeoutSec"], d, config)); err != nil { + if err := d.Set("tcp_transitory_idle_timeout_sec", flattenNestedComputeRouterNatTcpTransitoryIdleTimeoutSec(res["tcpTransitoryIdleTimeoutSec"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } - if err := d.Set("log_config", flattenComputeRouterNatLogConfig(res["logConfig"], d, config)); err != nil { + if err := d.Set("log_config", flattenNestedComputeRouterNatLogConfig(res["logConfig"], d, config)); err != nil { return fmt.Errorf("Error reading RouterNat: %s", err) } @@ -508,67 +508,67 @@ func resourceComputeRouterNatUpdate(d *schema.ResourceData, meta interface{}) er } obj := make(map[string]interface{}) - natIpAllocateOptionProp, err := expandComputeRouterNatNatIpAllocateOption(d.Get("nat_ip_allocate_option"), d, config) + natIpAllocateOptionProp, err := expandNestedComputeRouterNatNatIpAllocateOption(d.Get("nat_ip_allocate_option"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("nat_ip_allocate_option"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, natIpAllocateOptionProp)) { obj["natIpAllocateOption"] = natIpAllocateOptionProp } - natIpsProp, err := expandComputeRouterNatNatIps(d.Get("nat_ips"), d, config) + natIpsProp, err := expandNestedComputeRouterNatNatIps(d.Get("nat_ips"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("nat_ips"); ok || !reflect.DeepEqual(v, natIpsProp) { obj["natIps"] = natIpsProp } - drainNatIpsProp, err := expandComputeRouterNatDrainNatIps(d.Get("drain_nat_ips"), d, config) + drainNatIpsProp, err := expandNestedComputeRouterNatDrainNatIps(d.Get("drain_nat_ips"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("drain_nat_ips"); ok || !reflect.DeepEqual(v, drainNatIpsProp) { obj["drainNatIps"] = drainNatIpsProp } - sourceSubnetworkIpRangesToNatProp, err := expandComputeRouterNatSourceSubnetworkIpRangesToNat(d.Get("source_subnetwork_ip_ranges_to_nat"), d, config) + sourceSubnetworkIpRangesToNatProp, err := expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat(d.Get("source_subnetwork_ip_ranges_to_nat"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("source_subnetwork_ip_ranges_to_nat"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sourceSubnetworkIpRangesToNatProp)) { obj["sourceSubnetworkIpRangesToNat"] = sourceSubnetworkIpRangesToNatProp } - subnetworksProp, err := expandComputeRouterNatSubnetwork(d.Get("subnetwork"), d, config) + subnetworksProp, err := expandNestedComputeRouterNatSubnetwork(d.Get("subnetwork"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("subnetwork"); ok || !reflect.DeepEqual(v, subnetworksProp) { obj["subnetworks"] = subnetworksProp } - minPortsPerVmProp, err := expandComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config) + minPortsPerVmProp, err := expandNestedComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("min_ports_per_vm"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, minPortsPerVmProp)) { obj["minPortsPerVm"] = minPortsPerVmProp } - udpIdleTimeoutSecProp, err := expandComputeRouterNatUdpIdleTimeoutSec(d.Get("udp_idle_timeout_sec"), d, config) + udpIdleTimeoutSecProp, err := expandNestedComputeRouterNatUdpIdleTimeoutSec(d.Get("udp_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("udp_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, udpIdleTimeoutSecProp)) { obj["udpIdleTimeoutSec"] = udpIdleTimeoutSecProp } - icmpIdleTimeoutSecProp, err := expandComputeRouterNatIcmpIdleTimeoutSec(d.Get("icmp_idle_timeout_sec"), d, config) + icmpIdleTimeoutSecProp, err := expandNestedComputeRouterNatIcmpIdleTimeoutSec(d.Get("icmp_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("icmp_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, icmpIdleTimeoutSecProp)) { obj["icmpIdleTimeoutSec"] = icmpIdleTimeoutSecProp } - tcpEstablishedIdleTimeoutSecProp, err := expandComputeRouterNatTcpEstablishedIdleTimeoutSec(d.Get("tcp_established_idle_timeout_sec"), d, config) + tcpEstablishedIdleTimeoutSecProp, err := expandNestedComputeRouterNatTcpEstablishedIdleTimeoutSec(d.Get("tcp_established_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("tcp_established_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tcpEstablishedIdleTimeoutSecProp)) { obj["tcpEstablishedIdleTimeoutSec"] = tcpEstablishedIdleTimeoutSecProp } - tcpTransitoryIdleTimeoutSecProp, err := expandComputeRouterNatTcpTransitoryIdleTimeoutSec(d.Get("tcp_transitory_idle_timeout_sec"), d, config) + tcpTransitoryIdleTimeoutSecProp, err := expandNestedComputeRouterNatTcpTransitoryIdleTimeoutSec(d.Get("tcp_transitory_idle_timeout_sec"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("tcp_transitory_idle_timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tcpTransitoryIdleTimeoutSecProp)) { obj["tcpTransitoryIdleTimeoutSec"] = tcpTransitoryIdleTimeoutSecProp } - logConfigProp, err := expandComputeRouterNatLogConfig(d.Get("log_config"), d, config) + logConfigProp, err := expandNestedComputeRouterNatLogConfig(d.Get("log_config"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("log_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, logConfigProp)) { @@ -676,33 +676,33 @@ func resourceComputeRouterNatImport(d *schema.ResourceData, meta interface{}) ([ return []*schema.ResourceData{d}, nil } -func flattenComputeRouterNatName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterNatNatIpAllocateOption(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatNatIpAllocateOption(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterNatNatIps(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatNatIps(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return convertAndMapStringArr(v.([]interface{}), ConvertSelfLinkToV1) } -func flattenComputeRouterNatDrainNatIps(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatDrainNatIps(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return convertAndMapStringArr(v.([]interface{}), ConvertSelfLinkToV1) } -func flattenComputeRouterNatSourceSubnetworkIpRangesToNat(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatSourceSubnetworkIpRangesToNat(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterNatSubnetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatSubnetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } @@ -715,35 +715,35 @@ func flattenComputeRouterNatSubnetwork(v interface{}, d *schema.ResourceData, co continue } transformed.Add(map[string]interface{}{ - "name": flattenComputeRouterNatSubnetworkName(original["name"], d, config), - "source_ip_ranges_to_nat": flattenComputeRouterNatSubnetworkSourceIpRangesToNat(original["sourceIpRangesToNat"], d, config), - "secondary_ip_range_names": flattenComputeRouterNatSubnetworkSecondaryIpRangeNames(original["secondaryIpRangeNames"], d, config), + "name": flattenNestedComputeRouterNatSubnetworkName(original["name"], d, config), + "source_ip_ranges_to_nat": flattenNestedComputeRouterNatSubnetworkSourceIpRangesToNat(original["sourceIpRangesToNat"], d, config), + "secondary_ip_range_names": flattenNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(original["secondaryIpRangeNames"], d, config), }) } return transformed } -func flattenComputeRouterNatSubnetworkName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatSubnetworkName(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return ConvertSelfLinkToV1(v.(string)) } -func flattenComputeRouterNatSubnetworkSourceIpRangesToNat(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatSubnetworkSourceIpRangesToNat(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return schema.NewSet(schema.HashString, v.([]interface{})) } -func flattenComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return schema.NewSet(schema.HashString, v.([]interface{})) } -func flattenComputeRouterNatMinPortsPerVm(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatMinPortsPerVm(v interface{}, d *schema.ResourceData, config *Config) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -760,7 +760,7 @@ func flattenComputeRouterNatMinPortsPerVm(v interface{}, d *schema.ResourceData, return v // let terraform core handle it otherwise } -func flattenComputeRouterNatUdpIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatUdpIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil || isEmptyValue(reflect.ValueOf(v)) { return 30 } @@ -774,7 +774,7 @@ func flattenComputeRouterNatUdpIdleTimeoutSec(v interface{}, d *schema.ResourceD return v } -func flattenComputeRouterNatIcmpIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatIcmpIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil || isEmptyValue(reflect.ValueOf(v)) { return 30 } @@ -788,7 +788,7 @@ func flattenComputeRouterNatIcmpIdleTimeoutSec(v interface{}, d *schema.Resource return v } -func flattenComputeRouterNatTcpEstablishedIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatTcpEstablishedIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil || isEmptyValue(reflect.ValueOf(v)) { return 1200 } @@ -802,7 +802,7 @@ func flattenComputeRouterNatTcpEstablishedIdleTimeoutSec(v interface{}, d *schem return v } -func flattenComputeRouterNatTcpTransitoryIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatTcpTransitoryIdleTimeoutSec(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil || isEmptyValue(reflect.ValueOf(v)) { return 30 } @@ -816,7 +816,7 @@ func flattenComputeRouterNatTcpTransitoryIdleTimeoutSec(v interface{}, d *schema return v } -func flattenComputeRouterNatLogConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatLogConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return nil } @@ -826,28 +826,28 @@ func flattenComputeRouterNatLogConfig(v interface{}, d *schema.ResourceData, con } transformed := make(map[string]interface{}) transformed["enable"] = - flattenComputeRouterNatLogConfigEnable(original["enable"], d, config) + flattenNestedComputeRouterNatLogConfigEnable(original["enable"], d, config) transformed["filter"] = - flattenComputeRouterNatLogConfigFilter(original["filter"], d, config) + flattenNestedComputeRouterNatLogConfigFilter(original["filter"], d, config) return []interface{}{transformed} } -func flattenComputeRouterNatLogConfigEnable(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatLogConfigEnable(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenComputeRouterNatLogConfigFilter(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedComputeRouterNatLogConfigFilter(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandComputeRouterNatName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatNatIpAllocateOption(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatNatIpAllocateOption(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatNatIps(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatNatIps(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { v = v.(*schema.Set).List() l := v.([]interface{}) req := make([]interface{}, 0, len(l)) @@ -864,7 +864,7 @@ func expandComputeRouterNatNatIps(v interface{}, d TerraformResourceData, config return req, nil } -func expandComputeRouterNatDrainNatIps(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatDrainNatIps(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { v = v.(*schema.Set).List() l := v.([]interface{}) req := make([]interface{}, 0, len(l)) @@ -881,11 +881,11 @@ func expandComputeRouterNatDrainNatIps(v interface{}, d TerraformResourceData, c return req, nil } -func expandComputeRouterNatSourceSubnetworkIpRangesToNat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { v = v.(*schema.Set).List() l := v.([]interface{}) req := make([]interface{}, 0, len(l)) @@ -896,21 +896,21 @@ func expandComputeRouterNatSubnetwork(v interface{}, d TerraformResourceData, co original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedName, err := expandComputeRouterNatSubnetworkName(original["name"], d, config) + transformedName, err := expandNestedComputeRouterNatSubnetworkName(original["name"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { transformed["name"] = transformedName } - transformedSourceIpRangesToNat, err := expandComputeRouterNatSubnetworkSourceIpRangesToNat(original["source_ip_ranges_to_nat"], d, config) + transformedSourceIpRangesToNat, err := expandNestedComputeRouterNatSubnetworkSourceIpRangesToNat(original["source_ip_ranges_to_nat"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedSourceIpRangesToNat); val.IsValid() && !isEmptyValue(val) { transformed["sourceIpRangesToNat"] = transformedSourceIpRangesToNat } - transformedSecondaryIpRangeNames, err := expandComputeRouterNatSubnetworkSecondaryIpRangeNames(original["secondary_ip_range_names"], d, config) + transformedSecondaryIpRangeNames, err := expandNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(original["secondary_ip_range_names"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedSecondaryIpRangeNames); val.IsValid() && !isEmptyValue(val) { @@ -922,7 +922,7 @@ func expandComputeRouterNatSubnetwork(v interface{}, d TerraformResourceData, co return req, nil } -func expandComputeRouterNatSubnetworkName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatSubnetworkName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { f, err := parseRegionalFieldValue("subnetworks", v.(string), "project", "region", "zone", d, config, true) if err != nil { return nil, fmt.Errorf("Invalid value for name: %s", err) @@ -930,37 +930,37 @@ func expandComputeRouterNatSubnetworkName(v interface{}, d TerraformResourceData return f.RelativeLink(), nil } -func expandComputeRouterNatSubnetworkSourceIpRangesToNat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatSubnetworkSourceIpRangesToNat(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { v = v.(*schema.Set).List() return v, nil } -func expandComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { v = v.(*schema.Set).List() return v, nil } -func expandComputeRouterNatMinPortsPerVm(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatMinPortsPerVm(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatUdpIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatUdpIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatIcmpIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatIcmpIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatTcpEstablishedIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatTcpEstablishedIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatTcpTransitoryIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatTcpTransitoryIdleTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatLogConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatLogConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { return nil, nil @@ -969,14 +969,14 @@ func expandComputeRouterNatLogConfig(v interface{}, d TerraformResourceData, con original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedEnable, err := expandComputeRouterNatLogConfigEnable(original["enable"], d, config) + transformedEnable, err := expandNestedComputeRouterNatLogConfigEnable(original["enable"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedEnable); val.IsValid() && !isEmptyValue(val) { transformed["enable"] = transformedEnable } - transformedFilter, err := expandComputeRouterNatLogConfigFilter(original["filter"], d, config) + transformedFilter, err := expandNestedComputeRouterNatLogConfigFilter(original["filter"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedFilter); val.IsValid() && !isEmptyValue(val) { @@ -986,11 +986,11 @@ func expandComputeRouterNatLogConfig(v interface{}, d TerraformResourceData, con return transformed, nil } -func expandComputeRouterNatLogConfigEnable(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatLogConfigEnable(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeRouterNatLogConfigFilter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedComputeRouterNatLogConfigFilter(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -1023,10 +1023,11 @@ func flattenNestedComputeRouterNat(d *schema.ResourceData, meta interface{}, res } func resourceComputeRouterNatFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { - expectedName, err := expandComputeRouterNatName(d.Get("name"), d, meta.(*Config)) + expectedName, err := expandNestedComputeRouterNatName(d.Get("name"), d, meta.(*Config)) if err != nil { return -1, nil, err } + expectedFlattenedName := flattenNestedComputeRouterNatName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -1035,9 +1036,10 @@ func resourceComputeRouterNatFindNestedObjectInList(d *schema.ResourceData, meta } item := itemRaw.(map[string]interface{}) - itemName := flattenComputeRouterNatName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedComputeRouterNatName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_firebase_project_location.go b/google-beta/resource_firebase_project_location.go index fce1360fed..25dbb42b31 100644 --- a/google-beta/resource_firebase_project_location.go +++ b/google-beta/resource_firebase_project_location.go @@ -60,7 +60,7 @@ func resourceFirebaseProjectLocationCreate(d *schema.ResourceData, meta interfac config := meta.(*Config) obj := make(map[string]interface{}) - locationIdProp, err := expandFirebaseProjectLocationLocationId(d.Get("location_id"), d, config) + locationIdProp, err := expandNestedFirebaseProjectLocationLocationId(d.Get("location_id"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("location_id"); !isEmptyValue(reflect.ValueOf(locationIdProp)) && (ok || !reflect.DeepEqual(v, locationIdProp)) { @@ -137,7 +137,7 @@ func resourceFirebaseProjectLocationRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error reading ProjectLocation: %s", err) } - if err := d.Set("location_id", flattenFirebaseProjectLocationLocationId(res["locationId"], d, config)); err != nil { + if err := d.Set("location_id", flattenNestedFirebaseProjectLocationLocationId(res["locationId"], d, config)); err != nil { return fmt.Errorf("Error reading ProjectLocation: %s", err) } @@ -172,11 +172,11 @@ func resourceFirebaseProjectLocationImport(d *schema.ResourceData, meta interfac return []*schema.ResourceData{d}, nil } -func flattenFirebaseProjectLocationLocationId(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedFirebaseProjectLocationLocationId(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandFirebaseProjectLocationLocationId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedFirebaseProjectLocationLocationId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google-beta/resource_resource_manager_lien.go b/google-beta/resource_resource_manager_lien.go index d3fc5c797d..7b128f1dee 100644 --- a/google-beta/resource_resource_manager_lien.go +++ b/google-beta/resource_resource_manager_lien.go @@ -96,25 +96,25 @@ func resourceResourceManagerLienCreate(d *schema.ResourceData, meta interface{}) config := meta.(*Config) obj := make(map[string]interface{}) - reasonProp, err := expandResourceManagerLienReason(d.Get("reason"), d, config) + reasonProp, err := expandNestedResourceManagerLienReason(d.Get("reason"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("reason"); !isEmptyValue(reflect.ValueOf(reasonProp)) && (ok || !reflect.DeepEqual(v, reasonProp)) { obj["reason"] = reasonProp } - originProp, err := expandResourceManagerLienOrigin(d.Get("origin"), d, config) + originProp, err := expandNestedResourceManagerLienOrigin(d.Get("origin"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("origin"); !isEmptyValue(reflect.ValueOf(originProp)) && (ok || !reflect.DeepEqual(v, originProp)) { obj["origin"] = originProp } - parentProp, err := expandResourceManagerLienParent(d.Get("parent"), d, config) + parentProp, err := expandNestedResourceManagerLienParent(d.Get("parent"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("parent"); !isEmptyValue(reflect.ValueOf(parentProp)) && (ok || !reflect.DeepEqual(v, parentProp)) { obj["parent"] = parentProp } - restrictionsProp, err := expandResourceManagerLienRestrictions(d.Get("restrictions"), d, config) + restrictionsProp, err := expandNestedResourceManagerLienRestrictions(d.Get("restrictions"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("restrictions"); !isEmptyValue(reflect.ValueOf(restrictionsProp)) && (ok || !reflect.DeepEqual(v, restrictionsProp)) { @@ -131,7 +131,7 @@ func resourceResourceManagerLienCreate(d *schema.ResourceData, meta interface{}) if err != nil { return fmt.Errorf("Error creating Lien: %s", err) } - if err := d.Set("name", flattenResourceManagerLienName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedResourceManagerLienName(res["name"], d, config)); err != nil { return fmt.Errorf(`Error setting computed identity field "name": %s`, err) } @@ -151,8 +151,8 @@ func resourceResourceManagerLienCreate(d *schema.ResourceData, meta interface{}) // us to know the server-side generated name of the object we're // trying to fetch, and the only way to know that is to capture // it here. The following two lines do that. - d.SetId(flattenResourceManagerLienName(res["name"], d, config).(string)) - d.Set("name", flattenResourceManagerLienName(res["name"], d, config)) + d.SetId(flattenNestedResourceManagerLienName(res["name"], d, config).(string)) + d.Set("name", flattenNestedResourceManagerLienName(res["name"], d, config)) return resourceResourceManagerLienRead(d, meta) } @@ -194,22 +194,22 @@ func resourceResourceManagerLienRead(d *schema.ResourceData, meta interface{}) e return nil } - if err := d.Set("name", flattenResourceManagerLienName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedResourceManagerLienName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } - if err := d.Set("reason", flattenResourceManagerLienReason(res["reason"], d, config)); err != nil { + if err := d.Set("reason", flattenNestedResourceManagerLienReason(res["reason"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } - if err := d.Set("origin", flattenResourceManagerLienOrigin(res["origin"], d, config)); err != nil { + if err := d.Set("origin", flattenNestedResourceManagerLienOrigin(res["origin"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } - if err := d.Set("create_time", flattenResourceManagerLienCreateTime(res["createTime"], d, config)); err != nil { + if err := d.Set("create_time", flattenNestedResourceManagerLienCreateTime(res["createTime"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } - if err := d.Set("parent", flattenResourceManagerLienParent(res["parent"], d, config)); err != nil { + if err := d.Set("parent", flattenNestedResourceManagerLienParent(res["parent"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } - if err := d.Set("restrictions", flattenResourceManagerLienRestrictions(res["restrictions"], d, config)); err != nil { + if err := d.Set("restrictions", flattenNestedResourceManagerLienRestrictions(res["restrictions"], d, config)); err != nil { return fmt.Errorf("Error reading Lien: %s", err) } @@ -268,46 +268,46 @@ func resourceResourceManagerLienImport(d *schema.ResourceData, meta interface{}) return []*schema.ResourceData{d}, nil } -func flattenResourceManagerLienName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienName(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return NameFromSelfLinkStateFunc(v) } -func flattenResourceManagerLienReason(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienReason(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenResourceManagerLienOrigin(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienOrigin(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenResourceManagerLienCreateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienCreateTime(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenResourceManagerLienParent(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienParent(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenResourceManagerLienRestrictions(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedResourceManagerLienRestrictions(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func expandResourceManagerLienReason(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedResourceManagerLienReason(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandResourceManagerLienOrigin(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedResourceManagerLienOrigin(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandResourceManagerLienParent(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedResourceManagerLienParent(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandResourceManagerLienRestrictions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedResourceManagerLienRestrictions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -341,6 +341,7 @@ func flattenNestedResourceManagerLien(d *schema.ResourceData, meta interface{}, func resourceResourceManagerLienFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { expectedName := d.Get("name") + expectedFlattenedName := flattenNestedResourceManagerLienName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -355,9 +356,10 @@ func resourceResourceManagerLienFindNestedObjectInList(d *schema.ResourceData, m return -1, nil, err } - itemName := flattenResourceManagerLienName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedResourceManagerLienName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/google-beta/resource_service_usage_consumer_quota_override.go b/google-beta/resource_service_usage_consumer_quota_override.go index 21cdeedb0a..c6c9a80e17 100644 --- a/google-beta/resource_service_usage_consumer_quota_override.go +++ b/google-beta/resource_service_usage_consumer_quota_override.go @@ -97,13 +97,13 @@ func resourceServiceUsageConsumerQuotaOverrideCreate(d *schema.ResourceData, met config := meta.(*Config) obj := make(map[string]interface{}) - overrideValueProp, err := expandServiceUsageConsumerQuotaOverrideOverrideValue(d.Get("override_value"), d, config) + overrideValueProp, err := expandNestedServiceUsageConsumerQuotaOverrideOverrideValue(d.Get("override_value"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("override_value"); !isEmptyValue(reflect.ValueOf(overrideValueProp)) && (ok || !reflect.DeepEqual(v, overrideValueProp)) { obj["overrideValue"] = overrideValueProp } - dimensionsProp, err := expandServiceUsageConsumerQuotaOverrideDimensions(d.Get("dimensions"), d, config) + dimensionsProp, err := expandNestedServiceUsageConsumerQuotaOverrideDimensions(d.Get("dimensions"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("dimensions"); !isEmptyValue(reflect.ValueOf(dimensionsProp)) && (ok || !reflect.DeepEqual(v, dimensionsProp)) { @@ -154,7 +154,7 @@ func resourceServiceUsageConsumerQuotaOverrideCreate(d *schema.ResourceData, met return fmt.Errorf("Error decoding response from operation, could not find nested object") } } - if err := d.Set("name", flattenServiceUsageConsumerQuotaOverrideName(opRes["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedServiceUsageConsumerQuotaOverrideName(opRes["name"], d, config)); err != nil { return err } @@ -203,13 +203,13 @@ func resourceServiceUsageConsumerQuotaOverrideRead(d *schema.ResourceData, meta return fmt.Errorf("Error reading ConsumerQuotaOverride: %s", err) } - if err := d.Set("override_value", flattenServiceUsageConsumerQuotaOverrideOverrideValue(res["overrideValue"], d, config)); err != nil { + if err := d.Set("override_value", flattenNestedServiceUsageConsumerQuotaOverrideOverrideValue(res["overrideValue"], d, config)); err != nil { return fmt.Errorf("Error reading ConsumerQuotaOverride: %s", err) } - if err := d.Set("dimensions", flattenServiceUsageConsumerQuotaOverrideDimensions(res["dimensions"], d, config)); err != nil { + if err := d.Set("dimensions", flattenNestedServiceUsageConsumerQuotaOverrideDimensions(res["dimensions"], d, config)); err != nil { return fmt.Errorf("Error reading ConsumerQuotaOverride: %s", err) } - if err := d.Set("name", flattenServiceUsageConsumerQuotaOverrideName(res["name"], d, config)); err != nil { + if err := d.Set("name", flattenNestedServiceUsageConsumerQuotaOverrideName(res["name"], d, config)); err != nil { return fmt.Errorf("Error reading ConsumerQuotaOverride: %s", err) } @@ -225,7 +225,7 @@ func resourceServiceUsageConsumerQuotaOverrideUpdate(d *schema.ResourceData, met } obj := make(map[string]interface{}) - overrideValueProp, err := expandServiceUsageConsumerQuotaOverrideOverrideValue(d.Get("override_value"), d, config) + overrideValueProp, err := expandNestedServiceUsageConsumerQuotaOverrideOverrideValue(d.Get("override_value"), d, config) if err != nil { return err } else if v, ok := d.GetOkExists("override_value"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, overrideValueProp)) { @@ -308,26 +308,26 @@ func resourceServiceUsageConsumerQuotaOverrideImport(d *schema.ResourceData, met return []*schema.ResourceData{d}, nil } -func flattenServiceUsageConsumerQuotaOverrideOverrideValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedServiceUsageConsumerQuotaOverrideOverrideValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenServiceUsageConsumerQuotaOverrideDimensions(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedServiceUsageConsumerQuotaOverrideDimensions(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } -func flattenServiceUsageConsumerQuotaOverrideName(v interface{}, d *schema.ResourceData, config *Config) interface{} { +func flattenNestedServiceUsageConsumerQuotaOverrideName(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v } return NameFromSelfLinkStateFunc(v) } -func expandServiceUsageConsumerQuotaOverrideOverrideValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandNestedServiceUsageConsumerQuotaOverrideOverrideValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandServiceUsageConsumerQuotaOverrideDimensions(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) { +func expandNestedServiceUsageConsumerQuotaOverrideDimensions(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) { if v == nil { return map[string]string{}, nil } @@ -368,6 +368,7 @@ func flattenNestedServiceUsageConsumerQuotaOverride(d *schema.ResourceData, meta func resourceServiceUsageConsumerQuotaOverrideFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { expectedName := d.Get("name") + expectedFlattenedName := flattenNestedServiceUsageConsumerQuotaOverrideName(expectedName, d, meta.(*Config)) // Search list for this resource. for idx, itemRaw := range items { @@ -376,9 +377,10 @@ func resourceServiceUsageConsumerQuotaOverrideFindNestedObjectInList(d *schema.R } item := itemRaw.(map[string]interface{}) - itemName := flattenServiceUsageConsumerQuotaOverrideName(item["name"], d, meta.(*Config)) - if !reflect.DeepEqual(itemName, expectedName) { - log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedName) + itemName := flattenNestedServiceUsageConsumerQuotaOverrideName(item["name"], d, meta.(*Config)) + // isEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(isEmptyValue(reflect.ValueOf(itemName)) && isEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) continue } log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) diff --git a/website/docs/r/bigquery_dataset.html.markdown b/website/docs/r/bigquery_dataset.html.markdown index 643ac7d067..fbe6598fa9 100644 --- a/website/docs/r/bigquery_dataset.html.markdown +++ b/website/docs/r/bigquery_dataset.html.markdown @@ -25,6 +25,11 @@ description: |- Datasets allow you to organize and control access to your tables. +To get more information about Dataset, see: + +* [API documentation](https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets) +* How-to Guides + * [Datasets Intro](https://cloud.google.com/bigquery/docs/datasets-intro)
diff --git a/website/docs/r/bigquery_dataset_access.html.markdown b/website/docs/r/bigquery_dataset_access.html.markdown new file mode 100644 index 0000000000..042233e84c --- /dev/null +++ b/website/docs/r/bigquery_dataset_access.html.markdown @@ -0,0 +1,190 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- +subcategory: "BigQuery" +layout: "google" +page_title: "Google: google_bigquery_dataset_access" +sidebar_current: "docs-google-bigquery-dataset-access" +description: |- + Gives dataset access for a single entity. +--- + +# google\_bigquery\_dataset\_access + +Gives dataset access for a single entity. This resource is intended to be used in cases where +it is not possible to compile a full list of access blocks to include in a +`google_bigquery_dataset` resource, to enable them to be added separately. + +~> **Note:** If this resource is used alongside a `google_bigquery_dataset` resource, the +dataset resource must either have no defined `access` blocks or a `lifecycle` block with +`ignore_changes = [access]` so they don't fight over which accesses should be on the dataset. + + +To get more information about DatasetAccess, see: + +* [API documentation](https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets) +* How-to Guides + * [Controlling access to datasets](https://cloud.google.com/bigquery/docs/dataset-access-controls) + +## Example Usage - Bigquery Dataset Access Basic User + + +```hcl +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "OWNER" + user_by_email = google_service_account.bqowner.email +} + +resource "google_bigquery_dataset" "dataset" { + dataset_id = "example_dataset" +} + +resource "google_service_account" "bqowner" { + account_id = "bqowner" +} +``` +## Example Usage - Bigquery Dataset Access View + + +```hcl +resource "google_bigquery_dataset_access" "access" { + dataset_id = google_bigquery_dataset.private.dataset_id + view { + project_id = google_bigquery_table.public.project + dataset_id = google_bigquery_dataset.public.dataset_id + table_id = google_bigquery_table.public.table_id + } +} + +resource "google_bigquery_dataset" "private" { + dataset_id = "example_dataset" +} + +resource "google_bigquery_dataset" "public" { + dataset_id = "example_dataset2" +} + +resource "google_bigquery_table" "public" { + dataset_id = google_bigquery_dataset.public.dataset_id + table_id = "example_table" + + view { + query = "SELECT state FROM [lookerdata:cdc.project_tycho_reports]" + use_legacy_sql = false + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `dataset_id` - + (Required) + A unique ID for this dataset, without the project name. The ID + must contain only letters (a-z, A-Z), numbers (0-9), or + underscores (_). The maximum length is 1,024 characters. + + +- - - + + +* `role` - + (Optional) + Describes the rights granted to the user specified by the other + member of the access object. Primitive, Predefined and custom + roles are supported. Predefined roles that have equivalent + primitive roles are swapped by the API to their Primitive + counterparts, and will show a diff post-create. See + [official docs](https://cloud.google.com/bigquery/docs/access-control). + +* `user_by_email` - + (Optional) + An email address of a user to grant access to. For example: + fred@example.com + +* `group_by_email` - + (Optional) + An email address of a Google Group to grant access to. + +* `domain` - + (Optional) + A domain to grant access to. Any users signed in with the + domain specified will be granted the specified access + +* `special_group` - + (Optional) + A special group to grant access to. Possible values include: + + * `projectOwners`: Owners of the enclosing project. + + * `projectReaders`: Readers of the enclosing project. + + * `projectWriters`: Writers of the enclosing project. + + * `allAuthenticatedUsers`: All authenticated BigQuery users. + +* `iam_member` - + (Optional) + Some other type of member that appears in the IAM Policy but isn't a user, + group, domain, or special group. For example: `allUsers` + +* `view` - + (Optional) + A view from a different dataset to grant access to. Queries + executed against that view will have read access to tables in + this dataset. The role field is not required when this field is + set. If that view is updated by any user, access to the view + needs to be granted again via an update operation. Structure is documented below. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `view` block supports: + +* `dataset_id` - + (Required) + The ID of the dataset containing this table. + +* `project_id` - + (Required) + The ID of the project containing this table. + +* `table_id` - + (Required) + The ID of the table. The ID must contain only letters (a-z, + A-Z), numbers (0-9), or underscores (_). The maximum length + is 1,024 characters. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/datasets/{{dataset_id}}` + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override).