Skip to content

Instantly share code, notes, and snippets.

@rwos
Created October 11, 2018 09:21
Show Gist options
  • Save rwos/d9c9af379c9be6d9d2ba43b874cd110e to your computer and use it in GitHub Desktop.
Save rwos/d9c9af379c9be6d9d2ba43b874cd110e to your computer and use it in GitHub Desktop.
diff --git a/registry/storage/driver/gcs/gcs.go b/registry/storage/driver/gcs/gcs.go
index 86dc87f1..72bdf4ef 100644
--- a/registry/storage/driver/gcs/gcs.go
+++ b/registry/storage/driver/gcs/gcs.go
@@ -10,7 +10,6 @@
// Note that the contents of incomplete uploads are not accessible even though
// Stat returns their length
//
-// +build include_gcs
package gcs
@@ -39,6 +38,7 @@ import (
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
"google.golang.org/api/googleapi"
+ storageapi "google.golang.org/api/storage/v1"
"google.golang.org/cloud"
"google.golang.org/cloud/storage"
)
@@ -67,6 +67,7 @@ type driverParameters struct {
client *http.Client
rootDirectory string
chunkSize int
+ projectID string
// maxConcurrency limits the number of concurrent driver operations
// to GCS, which ultimately increases reliability of many simultaneous
@@ -148,6 +149,9 @@ func FromParameters(parameters map[string]interface{}) (storagedriver.StorageDri
}
var ts oauth2.TokenSource
+ var key struct {
+ ProjectID string `json:"project_id"`
+ }
jwtConf := new(jwt.Config)
if keyfile, ok := parameters["keyfile"]; ok {
jsonKey, err := ioutil.ReadFile(fmt.Sprint(keyfile))
@@ -158,6 +162,9 @@ func FromParameters(parameters map[string]interface{}) (storagedriver.StorageDri
if err != nil {
return nil, err
}
+ if err := json.Unmarshal(jsonKey, &key); err != nil {
+ return nil, err
+ }
ts = jwtConf.TokenSource(context.Background())
} else if credentials, ok := parameters["credentials"]; ok {
credentialMap, ok := credentials.(map[interface{}]interface{})
@@ -204,6 +211,7 @@ func FromParameters(parameters map[string]interface{}) (storagedriver.StorageDri
privateKey: jwtConf.PrivateKey,
client: oauth2.NewClient(context.Background(), ts),
chunkSize: chunkSize,
+ projectID: fmt.Sprint(key.ProjectID),
maxConcurrency: maxConcurrency,
}
@@ -219,6 +227,17 @@ func New(params driverParameters) (storagedriver.StorageDriver, error) {
if params.chunkSize <= 0 || params.chunkSize%minChunkSize != 0 {
return nil, fmt.Errorf("Invalid chunksize: %d is not a positive multiple of %d", params.chunkSize, minChunkSize)
}
+
+ service, err := storageapi.New(params.client)
+ if err != nil {
+ return nil, err
+ }
+ if _, err := service.Buckets.Get(params.bucket).Do(); err != nil {
+ if _, err := service.Buckets.Insert(params.projectID, &storageapi.Bucket{Name: params.bucket}).Do(); err != nil {
+ return nil, err
+ }
+ }
+
d := &driver{
bucket: params.bucket,
rootDirectory: rootDirectory,
@@ -540,6 +559,9 @@ func (w *writer) Write(p []byte) (int, error) {
// Size returns the number of bytes written to this FileWriter.
func (w *writer) Size() int64 {
+ if !w.closed {
+ return w.offset + int64(w.buffSize)
+ }
return w.size
}
diff --git a/registry/storage/driver/gcs/gcs_test.go b/registry/storage/driver/gcs/gcs_test.go
index e58216be..daa0698f 100644
--- a/registry/storage/driver/gcs/gcs_test.go
+++ b/registry/storage/driver/gcs/gcs_test.go
@@ -1,5 +1,3 @@
-// +build include_gcs
-
package gcs
import (
@@ -8,6 +6,8 @@ import (
"os"
"testing"
+ "fmt"
+ ctx "github.com/docker/distribution/context"
dcontext "github.com/docker/distribution/context"
storagedriver "github.com/docker/distribution/registry/storage/driver"
"github.com/docker/distribution/registry/storage/driver/testsuites"
diff --git a/registry/storage/driver/s3-aws/s3.go b/registry/storage/driver/s3-aws/s3.go
index 800435d0..3b23f7d5 100644
--- a/registry/storage/driver/s3-aws/s3.go
+++ b/registry/storage/driver/s3-aws/s3.go
@@ -460,6 +460,23 @@ func New(params DriverParameters) (*Driver, error) {
setv2Handlers(s3obj)
}
+ _, err = s3obj.CreateBucket(&s3.CreateBucketInput{
+ Bucket: &params.Bucket,
+ })
+ if err != nil {
+ if s3err, ok := err.(awserr.Error); ok {
+ if s3err.Code() != "BucketAlreadyOwnedByYou" && s3err.Code() != "BucketAlreadyExists" {
+ return nil, err
+ }
+ } else {
+ return nil, err
+ }
+ }
+
+ if err := s3obj.WaitUntilBucketExists(&s3.HeadBucketInput{Bucket: &params.Bucket}); err != nil {
+ return nil, err
+ }
+
// TODO Currently multipart uploads have no timestamps, so this would be unwise
// if you initiated a new s3driver while another one is running on the same bucket.
// multis, _, err := bucket.ListMulti("", "")
diff --git a/registry/storage/driver/storagedriver.go b/registry/storage/driver/storagedriver.go
index b220713f..aee67820 100644
--- a/registry/storage/driver/storagedriver.go
+++ b/registry/storage/driver/storagedriver.go
@@ -116,7 +116,7 @@ type FileWriter interface {
// number of path components separated by slashes, where each component is
// restricted to alphanumeric characters or a period, underscore, or
// hyphen.
-var PathRegexp = regexp.MustCompile(`^(/[A-Za-z0-9._-]+)+$`)
+var PathRegexp = regexp.MustCompile(`^([A-Za-z0-9._:-]*(/[A-Za-z0-9._:-]+)*)+$`)
// ErrUnsupportedMethod may be returned in the case where a StorageDriver implementation does not support an optional method.
type ErrUnsupportedMethod struct {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment