|
|
|
@ -29,7 +29,10 @@ import ( |
|
|
|
|
"strings" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"golang.org/x/oauth2/google" |
|
|
|
|
|
|
|
|
|
"cloud.google.com/go/storage" |
|
|
|
|
cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1" |
|
|
|
|
"google.golang.org/api/googleapi" |
|
|
|
|
"google.golang.org/api/iterator" |
|
|
|
|
|
|
|
|
@ -176,14 +179,56 @@ func gcsToObjectError(err error, params ...string) error { |
|
|
|
|
// gcsProjectIDRegex defines a valid gcs project id format
|
|
|
|
|
var gcsProjectIDRegex = regexp.MustCompile("^[a-z][a-z0-9-]{5,29}$") |
|
|
|
|
|
|
|
|
|
// isValidGCSProjectId - checks if a given project id is valid or not.
|
|
|
|
|
// Project IDs must start with a lowercase letter and can have lowercase
|
|
|
|
|
// ASCII letters, digits or hyphens. Project IDs must be between 6 and 30 characters.
|
|
|
|
|
// isValidGCSProjectIDFormat - checks if a given project id format is valid or not.
|
|
|
|
|
// Project IDs must start with a lowercase letter and can have lowercase ASCII letters,
|
|
|
|
|
// digits or hyphens. Project IDs must be between 6 and 30 characters.
|
|
|
|
|
// Ref: https://cloud.google.com/resource-manager/reference/rest/v1/projects#Project (projectId section)
|
|
|
|
|
func isValidGCSProjectID(projectID string) bool { |
|
|
|
|
func isValidGCSProjectIDFormat(projectID string) bool { |
|
|
|
|
// Checking projectID format
|
|
|
|
|
return gcsProjectIDRegex.MatchString(projectID) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// checkGCSProjectID - checks if the project ID does really exist using resource manager API.
|
|
|
|
|
func checkGCSProjectID(ctx context.Context, projectID string) error { |
|
|
|
|
// Check if a project id associated to the current account does really exist
|
|
|
|
|
resourceManagerClient, err := google.DefaultClient(ctx, cloudresourcemanager.CloudPlatformReadOnlyScope) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
baseSvc, err := cloudresourcemanager.New(resourceManagerClient) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
projectSvc := cloudresourcemanager.NewProjectsService(baseSvc) |
|
|
|
|
|
|
|
|
|
curPageToken := "" |
|
|
|
|
|
|
|
|
|
// Iterate over projects list result pages and immediately return nil when
|
|
|
|
|
// the project ID is found.
|
|
|
|
|
for { |
|
|
|
|
resp, err := projectSvc.List().PageToken(curPageToken).Context(ctx).Do() |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("Error getting projects list: %s", err.Error()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, p := range resp.Projects { |
|
|
|
|
if p.ProjectId == projectID { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if resp.NextPageToken != "" { |
|
|
|
|
curPageToken = resp.NextPageToken |
|
|
|
|
} else { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return errGCSProjectIDNotFound |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// gcsGateway - Implements gateway for Minio and GCS compatible object storage servers.
|
|
|
|
|
type gcsGateway struct { |
|
|
|
|
client *storage.Client |
|
|
|
@ -198,6 +243,11 @@ const googleStorageEndpoint = "storage.googleapis.com" |
|
|
|
|
func newGCSGateway(projectID string) (GatewayLayer, error) { |
|
|
|
|
ctx := context.Background() |
|
|
|
|
|
|
|
|
|
err := checkGCSProjectID(ctx, projectID) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Initialize a GCS client.
|
|
|
|
|
client, err := storage.NewClient(ctx) |
|
|
|
|
if err != nil { |
|
|
|
|