in lib/saw/warehouse.go [490:552]
func parseParams(params *clouds.ResourceTokenCreationParams) (projects map[string][]string, buckets map[string][]string, bqdatasets map[string]map[string][]string, err error) {
projects = make(map[string][]string)
buckets = make(map[string][]string)
bqdatasets = make(map[string]map[string][]string)
for _, role := range params.Roles {
// Roles should be in the format of either
// projects/{PROJECT-ID}/roles/{ROLE-ID} if it's a custom role defined for
// a project, or roles/{ROLE-ID} if it's a curated role.
rparts := strings.Split(role, "/")
isCustomRole := false
switch {
case len(rparts) == 2 || rparts[0] == "roles":
// non-custom role.
case len(rparts) == 4 && strings.HasPrefix(role, "projects/${project}/roles/"):
isCustomRole = true
role = fmt.Sprintf("roles/%s", rparts[3])
default:
return nil, nil, nil, fmt.Errorf(`role %q format not supported: must be "projects/{PROJECT-ID}/roles/{ROLE-ID}" or "roles/{ROLE-ID}"`, role)
}
for index, item := range params.Items {
proj, ok := item[projectVariable]
if !ok || len(proj) == 0 {
return nil, nil, nil, fmt.Errorf("item %d variable %q is undefined", index+1, projectVariable)
}
resolvedRole := role
if isCustomRole {
resolvedRole = fmt.Sprintf("projects/%s/%s", proj, role)
}
// If the bucket variable is available, store bucket-level configuration only.
bkt, ok := item[bucketVariable]
if ok && len(bkt) > 0 {
buckets[bkt] = append(buckets[bkt], resolvedRole)
continue
}
// If the dataset variable is available, store dataset-level configurations, and also add a
// project-level role roles/bigquery.user to give user the permission to run query jobs.
ds, ok := item[datasetVariable]
if ok && len(ds) > 0 {
dr, ok := bqdatasets[proj]
if !ok {
dr = make(map[string][]string)
bqdatasets[proj] = dr
}
dr[ds] = append(dr[ds], resolvedRole)
jobProj, ok := item[jobProjectVariable]
if ok {
proj = jobProj
}
projects[proj] = append(projects[proj], "roles/bigquery.user")
continue
}
// Otherwise, only store project-level configuration.
projects[proj] = append(projects[proj], resolvedRole)
}
}
return
}