From 4b217ccbf566e6e38f2c62292ebd980d920fbcda Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Thu, 21 Apr 2016 15:54:48 -0700 Subject: [PATCH 1/6] add middleware storage driver for redirect Signed-off-by: Andrew Hsu (github: andrewhsu) --- .../driver/middleware/redirect/middleware.go | 47 ++++++++++++++ .../middleware/redirect/middleware_test.go | 62 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 registry/storage/driver/middleware/redirect/middleware.go create mode 100644 registry/storage/driver/middleware/redirect/middleware_test.go diff --git a/registry/storage/driver/middleware/redirect/middleware.go b/registry/storage/driver/middleware/redirect/middleware.go new file mode 100644 index 00000000..286a84ab --- /dev/null +++ b/registry/storage/driver/middleware/redirect/middleware.go @@ -0,0 +1,47 @@ +package middleware + +import ( + "fmt" + "github.com/docker/distribution/context" + storagedriver "github.com/docker/distribution/registry/storage/driver" + storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware" + "net/url" + "strings" +) + +type redirectStorageMiddleware struct { + storagedriver.StorageDriver + scheme string + host string +} + +var _ storagedriver.StorageDriver = &redirectStorageMiddleware{} + +func newRedirectStorageMiddleware(sd storagedriver.StorageDriver, options map[string]interface{}) (storagedriver.StorageDriver, error) { + o, ok := options["baseurl"] + if !ok { + return nil, fmt.Errorf("no baseurl provided") + } + b, ok := o.(string) + if !ok { + return nil, fmt.Errorf("baseurl must be a string") + } + if !strings.Contains(b, "://") { + b = "https://" + b + } + u, err := url.Parse(b) + if err != nil { + return nil, fmt.Errorf("invalid baseurl: %v", err) + } + + return &redirectStorageMiddleware{StorageDriver: sd, scheme: u.Scheme, host: u.Host}, nil +} + +func (r *redirectStorageMiddleware) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) { + u := &url.URL{Scheme: r.scheme, Host: r.host, Path: path} + return u.String(), nil +} + +func init() { + storagemiddleware.Register("redirect", storagemiddleware.InitFunc(newRedirectStorageMiddleware)) +} diff --git a/registry/storage/driver/middleware/redirect/middleware_test.go b/registry/storage/driver/middleware/redirect/middleware_test.go new file mode 100644 index 00000000..31b661b6 --- /dev/null +++ b/registry/storage/driver/middleware/redirect/middleware_test.go @@ -0,0 +1,62 @@ +package middleware + +import ( + check "gopkg.in/check.v1" + "testing" +) + +func Test(t *testing.T) { check.TestingT(t) } + +type MiddlewareSuite struct{} + +var _ = check.Suite(&MiddlewareSuite{}) + +func (s *MiddlewareSuite) TestNoConfig(c *check.C) { + options := make(map[string]interface{}) + _, err := newRedirectStorageMiddleware(nil, options) + c.Assert(err, check.ErrorMatches, "no baseurl provided") +} + +func (s *MiddlewareSuite) TestDefaultScheme(c *check.C) { + options := make(map[string]interface{}) + options["baseurl"] = "example.com" + middleware, err := newRedirectStorageMiddleware(nil, options) + c.Assert(err, check.Equals, nil) + + m, ok := middleware.(*redirectStorageMiddleware) + c.Assert(ok, check.Equals, true) + c.Assert(m.scheme, check.Equals, "https") + c.Assert(m.host, check.Equals, "example.com") +} + +func (s *MiddlewareSuite) TestHTTPS(c *check.C) { + options := make(map[string]interface{}) + options["baseurl"] = "https://example.com" + middleware, err := newRedirectStorageMiddleware(nil, options) + c.Assert(err, check.Equals, nil) + + m, ok := middleware.(*redirectStorageMiddleware) + c.Assert(ok, check.Equals, true) + c.Assert(m.scheme, check.Equals, "https") + c.Assert(m.host, check.Equals, "example.com") + + url, err := middleware.URLFor(nil, "/rick/data", nil) + c.Assert(err, check.Equals, nil) + c.Assert(url, check.Equals, "https://example.com/rick/data") +} + +func (s *MiddlewareSuite) TestHTTP(c *check.C) { + options := make(map[string]interface{}) + options["baseurl"] = "http://example.com" + middleware, err := newRedirectStorageMiddleware(nil, options) + c.Assert(err, check.Equals, nil) + + m, ok := middleware.(*redirectStorageMiddleware) + c.Assert(ok, check.Equals, true) + c.Assert(m.scheme, check.Equals, "http") + c.Assert(m.host, check.Equals, "example.com") + + url, err := middleware.URLFor(nil, "morty/data", nil) + c.Assert(err, check.Equals, nil) + c.Assert(url, check.Equals, "http://example.com/morty/data") +} From 059bc5f5ef965b8b668c9fc61b5af0eda589d033 Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Mon, 25 Apr 2016 09:32:36 -0700 Subject: [PATCH 2/6] separate the go/non-go imports and reorder Signed-off-by: Andrew Hsu (github: andrewhsu) --- registry/storage/driver/middleware/redirect/middleware.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/registry/storage/driver/middleware/redirect/middleware.go b/registry/storage/driver/middleware/redirect/middleware.go index 286a84ab..a806bc0f 100644 --- a/registry/storage/driver/middleware/redirect/middleware.go +++ b/registry/storage/driver/middleware/redirect/middleware.go @@ -2,11 +2,12 @@ package middleware import ( "fmt" + "net/url" + "strings" + "github.com/docker/distribution/context" storagedriver "github.com/docker/distribution/registry/storage/driver" storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware" - "net/url" - "strings" ) type redirectStorageMiddleware struct { From 80248c3d3aabec255bd3e2c4132b985b467931ee Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Mon, 25 Apr 2016 10:28:32 -0700 Subject: [PATCH 3/6] scheme and host mandatory in baseurl Signed-off-by: Andrew Hsu (github: andrewhsu) --- .../storage/driver/middleware/redirect/middleware.go | 12 +++++++----- .../driver/middleware/redirect/middleware_test.go | 11 +++-------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/registry/storage/driver/middleware/redirect/middleware.go b/registry/storage/driver/middleware/redirect/middleware.go index a806bc0f..20cd7daa 100644 --- a/registry/storage/driver/middleware/redirect/middleware.go +++ b/registry/storage/driver/middleware/redirect/middleware.go @@ -3,7 +3,6 @@ package middleware import ( "fmt" "net/url" - "strings" "github.com/docker/distribution/context" storagedriver "github.com/docker/distribution/registry/storage/driver" @@ -27,12 +26,15 @@ func newRedirectStorageMiddleware(sd storagedriver.StorageDriver, options map[st if !ok { return nil, fmt.Errorf("baseurl must be a string") } - if !strings.Contains(b, "://") { - b = "https://" + b - } u, err := url.Parse(b) if err != nil { - return nil, fmt.Errorf("invalid baseurl: %v", err) + return nil, fmt.Errorf("unable to parse redirect baseurl: %s", b) + } + if u.Scheme == "" { + return nil, fmt.Errorf("no scheme specified for redirect baseurl") + } + if u.Host == "" { + return nil, fmt.Errorf("no host specified for redirect baseurl") } return &redirectStorageMiddleware{StorageDriver: sd, scheme: u.Scheme, host: u.Host}, nil diff --git a/registry/storage/driver/middleware/redirect/middleware_test.go b/registry/storage/driver/middleware/redirect/middleware_test.go index 31b661b6..5fffafba 100644 --- a/registry/storage/driver/middleware/redirect/middleware_test.go +++ b/registry/storage/driver/middleware/redirect/middleware_test.go @@ -17,16 +17,11 @@ func (s *MiddlewareSuite) TestNoConfig(c *check.C) { c.Assert(err, check.ErrorMatches, "no baseurl provided") } -func (s *MiddlewareSuite) TestDefaultScheme(c *check.C) { +func (s *MiddlewareSuite) TestMissingScheme(c *check.C) { options := make(map[string]interface{}) options["baseurl"] = "example.com" - middleware, err := newRedirectStorageMiddleware(nil, options) - c.Assert(err, check.Equals, nil) - - m, ok := middleware.(*redirectStorageMiddleware) - c.Assert(ok, check.Equals, true) - c.Assert(m.scheme, check.Equals, "https") - c.Assert(m.host, check.Equals, "example.com") + _, err := newRedirectStorageMiddleware(nil, options) + c.Assert(err, check.ErrorMatches, "no scheme specified for redirect baseurl") } func (s *MiddlewareSuite) TestHTTPS(c *check.C) { From fe9509f8f3bd075a46b57f1bd86bec63a96e02fb Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Mon, 25 Apr 2016 11:31:02 -0700 Subject: [PATCH 4/6] added config doc for redirect middleware Signed-off-by: Andrew Hsu (github: andrewhsu) --- docs/configuration.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index f9b89feb..91d85231 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -165,6 +165,10 @@ information about each option that appears later in this page. privatekey: /path/to/pem keypairid: cloudfrontkeypairid duration: 3000s + storage: + - name: redirect + options: + baseurl: https://example.com/ reporting: bugsnag: apikey: bugsnagapikey @@ -676,8 +680,7 @@ object they're wrapping. This means a registry middleware must implement the `distribution.Repository`, and storage middleware must implement `driver.StorageDriver`. -Currently only one middleware, `cloudfront`, a storage middleware, is supported -in the registry implementation. +An example configuration of the `cloudfront` middleware, a storage middleware: middleware: registry: @@ -758,6 +761,15 @@ interpretation of the options. +### redirect + +In place of the `cloudfront` storage middleware, the `redirect` +storage middleware can be used to specify a custom URL to a location +of a proxy for the layer stored by the S3 storage driver. + +| Parameter | Required | Description | +| --- | --- | --- | +| baseurl | yes | `SCHEME://HOST` at which layers are served. Can also contain port. For example, `https://example.com:5443`. | ## reporting @@ -1794,7 +1806,7 @@ This example illustrates how to configure storage middleware in a registry. Middleware allows the registry to serve layers via a content delivery network (CDN). This is useful for reducing requests to the storage layer. -Currently, the registry supports [Amazon +The registry supports [Amazon Cloudfront](http://aws.amazon.com/cloudfront/). You can only use Cloudfront in conjunction with the S3 storage driver. From c4df027d41ce5af9b87aef02f08241216f3f3524 Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Mon, 25 Apr 2016 11:40:21 -0700 Subject: [PATCH 5/6] modify redirect test to include port Signed-off-by: Andrew Hsu (github: andrewhsu) --- .../storage/driver/middleware/redirect/middleware_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/registry/storage/driver/middleware/redirect/middleware_test.go b/registry/storage/driver/middleware/redirect/middleware_test.go index 5fffafba..82f4a561 100644 --- a/registry/storage/driver/middleware/redirect/middleware_test.go +++ b/registry/storage/driver/middleware/redirect/middleware_test.go @@ -24,20 +24,20 @@ func (s *MiddlewareSuite) TestMissingScheme(c *check.C) { c.Assert(err, check.ErrorMatches, "no scheme specified for redirect baseurl") } -func (s *MiddlewareSuite) TestHTTPS(c *check.C) { +func (s *MiddlewareSuite) TestHttpsPort(c *check.C) { options := make(map[string]interface{}) - options["baseurl"] = "https://example.com" + options["baseurl"] = "https://example.com:5443" middleware, err := newRedirectStorageMiddleware(nil, options) c.Assert(err, check.Equals, nil) m, ok := middleware.(*redirectStorageMiddleware) c.Assert(ok, check.Equals, true) c.Assert(m.scheme, check.Equals, "https") - c.Assert(m.host, check.Equals, "example.com") + c.Assert(m.host, check.Equals, "example.com:5443") url, err := middleware.URLFor(nil, "/rick/data", nil) c.Assert(err, check.Equals, nil) - c.Assert(url, check.Equals, "https://example.com/rick/data") + c.Assert(url, check.Equals, "https://example.com:5443/rick/data") } func (s *MiddlewareSuite) TestHTTP(c *check.C) { From 09a9b0cf902d23a84506934a652257e0370398a1 Mon Sep 17 00:00:00 2001 From: Andrew Hsu Date: Tue, 26 Apr 2016 14:33:54 -0700 Subject: [PATCH 6/6] separate the go/non-go imports and reorder Signed-off-by: Andrew Hsu (github: andrewhsu) --- registry/storage/driver/middleware/redirect/middleware_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/registry/storage/driver/middleware/redirect/middleware_test.go b/registry/storage/driver/middleware/redirect/middleware_test.go index 82f4a561..1eb6309f 100644 --- a/registry/storage/driver/middleware/redirect/middleware_test.go +++ b/registry/storage/driver/middleware/redirect/middleware_test.go @@ -1,8 +1,9 @@ package middleware import ( - check "gopkg.in/check.v1" "testing" + + check "gopkg.in/check.v1" ) func Test(t *testing.T) { check.TestingT(t) }