Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support BigQuery authorized routines #12979

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/6680.txt
@@ -0,0 +1,3 @@
```release-note:enhancement
bigquery: supported authorized routines on resource `bigquery_dataset` and `bigquery_dataset_access`
```
4 changes: 4 additions & 0 deletions google/iam_bigquery_dataset.go
Expand Up @@ -242,6 +242,10 @@ func accessToIamMember(access map[string]interface{}) (string, error) {
// dataset does not map to an IAM member, use access instead
return "", fmt.Errorf("Failed to convert BigQuery Dataset access to IAM member. To use views with a dataset, please use dataset_access")
}
if _, ok := access["routine"]; ok {
// dataset does not map to an IAM member, use access instead
return "", fmt.Errorf("Failed to convert BigQuery Dataset access to IAM member. To use views with a dataset, please use dataset_access")
}
if member, ok := access["userByEmail"]; ok {
// service accounts have "gservice" in their email. This is best guess due to lost information
if strings.Contains(member.(string), "gserviceaccount") {
Expand Down
113 changes: 113 additions & 0 deletions google/resource_bigquery_dataset.go
Expand Up @@ -286,6 +286,37 @@ are supported. Predefined roles that have equivalent basic roles
are swapped by the API to their basic counterparts. See
[official docs](https://cloud.google.com/bigquery/docs/access-control).`,
},
"routine": {
Type: schema.TypeList,
Optional: true,
Description: `A routine from a different dataset to grant access to. Queries
executed against that routine will have read access to tables in
this dataset. The role field is not required when this field is
set. If that routine is updated by any user, access to the routine
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,
Description: `The ID of the dataset containing this table.`,
},
"project_id": {
Type: schema.TypeString,
Required: true,
Description: `The ID of the project containing this table.`,
},
"routine_id": {
Type: schema.TypeString,
Required: true,
Description: `The ID of the routine. The ID must contain only letters (a-z,
A-Z), numbers (0-9), or underscores (_). The maximum length
is 256 characters.`,
},
},
},
},
"special_group": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -733,6 +764,7 @@ func flattenBigQueryDatasetAccess(v interface{}, d *schema.ResourceData, config
"user_by_email": flattenBigQueryDatasetAccessUserByEmail(original["userByEmail"], d, config),
"view": flattenBigQueryDatasetAccessView(original["view"], d, config),
"dataset": flattenBigQueryDatasetAccessDataset(original["dataset"], d, config),
"routine": flattenBigQueryDatasetAccessRoutine(original["routine"], d, config),
})
}
return transformed
Expand Down Expand Up @@ -828,6 +860,35 @@ func flattenBigQueryDatasetAccessDatasetTargetTypes(v interface{}, d *schema.Res
return v
}

func flattenBigQueryDatasetAccessRoutine(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"] =
flattenBigQueryDatasetAccessRoutineDatasetId(original["datasetId"], d, config)
transformed["project_id"] =
flattenBigQueryDatasetAccessRoutineProjectId(original["projectId"], d, config)
transformed["routine_id"] =
flattenBigQueryDatasetAccessRoutineRoutineId(original["routineId"], d, config)
return []interface{}{transformed}
}
func flattenBigQueryDatasetAccessRoutineDatasetId(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenBigQueryDatasetAccessRoutineProjectId(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenBigQueryDatasetAccessRoutineRoutineId(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenBigQueryDatasetCreationTime(v interface{}, d *schema.ResourceData, config *Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
Expand Down Expand Up @@ -1020,6 +1081,13 @@ func expandBigQueryDatasetAccess(v interface{}, d TerraformResourceData, config
transformed["dataset"] = transformedDataset
}

transformedRoutine, err := expandBigQueryDatasetAccessRoutine(original["routine"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRoutine); val.IsValid() && !isEmptyValue(val) {
transformed["routine"] = transformedRoutine
}

req = append(req, transformed)
}
return req, nil
Expand Down Expand Up @@ -1154,6 +1222,51 @@ func expandBigQueryDatasetAccessDatasetTargetTypes(v interface{}, d TerraformRes
return v, nil
}

func expandBigQueryDatasetAccessRoutine(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 := expandBigQueryDatasetAccessRoutineDatasetId(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 := expandBigQueryDatasetAccessRoutineProjectId(original["project_id"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedProjectId); val.IsValid() && !isEmptyValue(val) {
transformed["projectId"] = transformedProjectId
}

transformedRoutineId, err := expandBigQueryDatasetAccessRoutineRoutineId(original["routine_id"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRoutineId); val.IsValid() && !isEmptyValue(val) {
transformed["routineId"] = transformedRoutineId
}

return transformed, nil
}

func expandBigQueryDatasetAccessRoutineDatasetId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandBigQueryDatasetAccessRoutineProjectId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandBigQueryDatasetAccessRoutineRoutineId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandBigQueryDatasetDatasetReference(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
transformed := make(map[string]interface{})
transformedDatasetId, err := expandBigQueryDatasetDatasetReferenceDatasetId(d.Get("dataset_id"), d, config)
Expand Down