From 98539fba8a1687ee88a87142092e31bcd22258f3 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Wed, 12 Jul 2017 14:08:59 -0700 Subject: [PATCH] Updated deps --- .../internal/datastoreutil/validator.go | 11 + api/datastore/mock.go | 7 + api/datastore/sql/sql.go | 5 + api/models/datastore.go | 5 + glide.lock | 2 +- glide.yaml | 4 +- .../docker/distribution/BUILDING.md | 8 +- .../docker/distribution/CHANGELOG.md | 6 - .../github.com/docker/distribution/Dockerfile | 5 +- .../docker/distribution/Godeps/Godeps.json | 458 ------------- .../docker/distribution/Godeps/Readme | 5 - .../github.com/docker/distribution/Makefile | 26 +- .../github.com/docker/distribution/README.md | 3 +- .../docker/distribution/RELEASE-CHECKLIST.md | 16 +- .../github.com/docker/distribution/blobs.go | 4 +- .../github.com/docker/distribution/circle.yml | 17 +- .../docker/distribution/cmd/digest/main.go | 4 +- .../configuration/configuration.go | 14 +- .../docker/distribution/context/doc.go | 2 +- .../distribution/contrib/compose/README.md | 6 +- .../docker-integration/docker-compose.yml | 2 +- .../contrib/docker-integration/golem.conf | 2 +- .../contrib/docker-integration/helpers.bash | 34 +- .../docker-integration/malevolent.bats | 6 +- .../contrib/docker-integration/plugins.bats | 103 +++ .../docker-integration/run_multiversion.sh | 5 +- .../contrib/docker-integration/tls.bats | 19 +- .../contrib/docker-integration/token.bats | 16 +- .../tokenserver-oauth/Dockerfile | 2 +- .../docker-integration/tokenserver/Dockerfile | 2 +- .../docker/distribution/digest/digest.go | 139 ---- .../docker/distribution/digest/digest_test.go | 82 --- .../docker/distribution/digest/digester.go | 155 ----- .../docker/distribution/digest/doc.go | 42 -- .../docker/distribution/digest/verifiers.go | 44 -- .../distribution/digest/verifiers_test.go | 49 -- .../distribution/{digest => digestset}/set.go | 30 +- .../{digest => digestset}/set_test.go | 25 +- .../docker/distribution/docs/architecture.md | 52 ++ .../docker/distribution/docs/configuration.md | 29 +- .../docker/distribution/docs/spec/api.md | 2 +- .../docker/distribution/docs/spec/api.md.tmpl | 2 +- .../distribution/docs/spec/manifest-v2-1.md | 2 +- .../distribution/docs/spec/manifest-v2-2.md | 10 +- .../github.com/docker/distribution/errors.go | 4 +- .../distribution/health/checks/checks.go | 17 +- .../docker/distribution/health/doc.go | 8 +- .../docker/distribution/health/health_test.go | 4 +- .../manifest/manifestlist/manifestlist.go | 4 +- .../manifest/schema1/config_builder.go | 11 +- .../manifest/schema1/config_builder_test.go | 8 +- .../distribution/manifest/schema1/manifest.go | 2 +- .../manifest/schema1/reference_builder.go | 2 +- .../schema1/reference_builder_test.go | 4 +- .../distribution/manifest/schema2/builder.go | 32 +- .../manifest/schema2/builder_test.go | 6 +- .../distribution/manifest/schema2/manifest.go | 10 +- .../manifest/schema2/manifest_test.go | 4 +- .../docker/distribution/manifests.go | 22 +- .../distribution/notifications/bridge.go | 2 +- .../distribution/notifications/bridge_test.go | 14 +- .../distribution/notifications/endpoint.go | 2 +- .../distribution/notifications/event.go | 4 +- .../distribution/notifications/http_test.go | 20 +- .../distribution/notifications/listener.go | 2 +- .../notifications/listener_test.go | 4 +- .../notifications/metrics_test.go | 28 + .../distribution/notifications/sinks.go | 2 +- .../docker/distribution/reference/helpers.go | 42 ++ .../distribution/reference/normalize.go | 170 +++++ .../distribution/reference/normalize_test.go | 625 ++++++++++++++++++ .../distribution/reference/reference.go | 211 +++--- .../distribution/reference/reference_test.go | 194 +++--- .../docker/distribution/reference/regexp.go | 41 +- .../distribution/reference/regexp_test.go | 68 +- .../docker/distribution/registry.go | 2 +- .../registry/api/v2/descriptors.go | 2 +- .../distribution/registry/api/v2/urls.go | 3 + .../distribution/registry/api/v2/urls_test.go | 56 +- .../registry/auth/token/token_test.go | 21 + .../registry/client/auth/session.go | 4 +- .../registry/client/repository.go | 10 +- .../registry/client/repository_test.go | 34 +- .../registry/handlers/api_test.go | 160 ++++- .../distribution/registry/handlers/app.go | 41 +- .../registry/handlers/app_test.go | 6 +- .../distribution/registry/handlers/blob.go | 2 +- .../registry/handlers/blobupload.go | 8 +- .../distribution/registry/handlers/context.go | 64 +- .../handlers/{images.go => manifests.go} | 72 +- .../registry/proxy/proxyblobstore.go | 2 +- .../registry/proxy/proxyblobstore_test.go | 4 +- .../registry/proxy/proxymanifeststore.go | 2 +- .../registry/proxy/proxymanifeststore_test.go | 4 +- .../docker/distribution/registry/registry.go | 2 +- .../registry/storage/blob_test.go | 16 +- .../registry/storage/blobserver.go | 2 +- .../registry/storage/blobstore.go | 4 +- .../registry/storage/blobwriter.go | 25 +- .../storage/cache/cachecheck/suite.go | 2 +- .../cache/cachedblobdescriptorstore.go | 2 +- .../registry/storage/cache/memory/memory.go | 4 +- .../registry/storage/cache/redis/redis.go | 4 +- .../registry/storage/catalog_test.go | 4 +- .../storage}/digester_resumable_test.go | 5 +- .../registry/storage/driver/azure/azure.go | 44 +- .../registry/storage/driver/base/regulator.go | 6 +- .../storage/driver/base/regulator_test.go | 67 ++ .../registry/storage/driver/oss/oss.go | 10 +- .../registry/storage/driver/s3-aws/s3.go | 12 +- .../registry/storage/driver/s3-aws/s3_test.go | 2 + .../storage/driver/s3-aws/s3_v2_signer.go | 3 + .../registry/storage/driver/s3-goamz/s3.go | 34 +- .../registry/storage/filereader_test.go | 8 +- .../registry/storage/garbagecollect.go | 4 +- .../registry/storage/garbagecollect_test.go | 4 +- .../registry/storage/linkedblobstore.go | 4 +- .../registry/storage/linkedblobstore_test.go | 8 +- .../registry/storage/manifestlisthandler.go | 2 +- .../registry/storage/manifeststore.go | 2 +- .../registry/storage/manifeststore_test.go | 4 +- .../distribution/registry/storage/paths.go | 2 +- .../registry/storage/paths_test.go | 2 +- .../registry/storage/purgeuploads.go | 6 +- .../storage/schema2manifesthandler.go | 2 +- .../storage/schema2manifesthandler_test.go | 2 +- .../registry/storage/signedmanifesthandler.go | 2 +- .../distribution/registry/storage/tagstore.go | 2 +- .../registry/storage/tagstore_test.go | 2 +- .../distribution/registry/storage/vacuum.go | 4 +- .../docker/distribution/testutil/manifests.go | 4 +- .../docker/distribution/testutil/tarfile.go | 2 +- .../docker/distribution/vendor.conf | 43 ++ 133 files changed, 2224 insertions(+), 1659 deletions(-) delete mode 100644 vendor/github.com/docker/distribution/Godeps/Godeps.json delete mode 100644 vendor/github.com/docker/distribution/Godeps/Readme create mode 100644 vendor/github.com/docker/distribution/contrib/docker-integration/plugins.bats delete mode 100644 vendor/github.com/docker/distribution/digest/digest.go delete mode 100644 vendor/github.com/docker/distribution/digest/digest_test.go delete mode 100644 vendor/github.com/docker/distribution/digest/digester.go delete mode 100644 vendor/github.com/docker/distribution/digest/doc.go delete mode 100644 vendor/github.com/docker/distribution/digest/verifiers.go delete mode 100644 vendor/github.com/docker/distribution/digest/verifiers_test.go rename vendor/github.com/docker/distribution/{digest => digestset}/set.go (90%) rename vendor/github.com/docker/distribution/{digest => digestset}/set_test.go (93%) create mode 100644 vendor/github.com/docker/distribution/docs/architecture.md create mode 100644 vendor/github.com/docker/distribution/notifications/metrics_test.go create mode 100644 vendor/github.com/docker/distribution/reference/helpers.go create mode 100644 vendor/github.com/docker/distribution/reference/normalize.go create mode 100644 vendor/github.com/docker/distribution/reference/normalize_test.go rename vendor/github.com/docker/distribution/registry/handlers/{images.go => manifests.go} (84%) rename vendor/github.com/docker/distribution/{digest => registry/storage}/digester_resumable_test.go (83%) create mode 100644 vendor/github.com/docker/distribution/registry/storage/driver/base/regulator_test.go create mode 100644 vendor/github.com/docker/distribution/vendor.conf diff --git a/api/datastore/internal/datastoreutil/validator.go b/api/datastore/internal/datastoreutil/validator.go index c747316b8..7f2a9abb4 100644 --- a/api/datastore/internal/datastoreutil/validator.go +++ b/api/datastore/internal/datastoreutil/validator.go @@ -3,6 +3,8 @@ package datastoreutil import ( "context" + "github.com/jmoiron/sqlx" + "gitlab-odx.oracle.com/odx/functions/api/models" ) @@ -135,3 +137,12 @@ func (v *validator) GetTask(ctx context.Context, callID string) (*models.FnCall, } return v.Datastore.GetTask(ctx, callID) } + +func (v *validator) DeleteLog(ctx context.Context, callID string) error { + return v.Datastore.DeleteLog(ctx, callID) +} + +// GetDatabase returns the underlying sqlx database implementation +func (v *validator) GetDatabase() *sqlx.DB { + return v.Datastore.GetDatabase() +} diff --git a/api/datastore/mock.go b/api/datastore/mock.go index d3a22b2c9..4784fc800 100644 --- a/api/datastore/mock.go +++ b/api/datastore/mock.go @@ -3,6 +3,8 @@ package datastore import ( "context" + "github.com/jmoiron/sqlx" + "gitlab-odx.oracle.com/odx/functions/api/datastore/internal/datastoreutil" "gitlab-odx.oracle.com/odx/functions/api/logs" "gitlab-odx.oracle.com/odx/functions/api/models" @@ -167,3 +169,8 @@ func (m *mock) GetTask(ctx context.Context, callID string) (*models.FnCall, erro func (m *mock) GetTasks(ctx context.Context, filter *models.CallFilter) (models.FnCalls, error) { return m.Calls, nil } + +// GetDatabase returns nil here since shouldn't really be used +func (m *mock) GetDatabase() *sqlx.DB { + return nil +} diff --git a/api/datastore/sql/sql.go b/api/datastore/sql/sql.go index 718bfbbda..b7fb6f274 100644 --- a/api/datastore/sql/sql.go +++ b/api/datastore/sql/sql.go @@ -757,3 +757,8 @@ func scanCall(scanner RowScanner, call *models.FnCall) error { } return nil } + +// GetDatabase returns the underlying sqlx database implementation +func (ds *sqlStore) GetDatabase() *sqlx.DB { + return ds.db +} diff --git a/api/models/datastore.go b/api/models/datastore.go index 53827e69f..a81fbc3a8 100644 --- a/api/models/datastore.go +++ b/api/models/datastore.go @@ -3,6 +3,8 @@ package models import ( "context" "errors" + + "github.com/jmoiron/sqlx" ) type Datastore interface { @@ -64,6 +66,9 @@ type Datastore interface { // Implement FnLog methods for convenience FnLog + + // GetDatabase returns the underlying sqlx database implementation + GetDatabase() *sqlx.DB } var ( diff --git a/glide.lock b/glide.lock index d5edee581..329589e79 100644 --- a/glide.lock +++ b/glide.lock @@ -40,7 +40,7 @@ imports: subpackages: - cli/config/configfile - name: github.com/docker/distribution - version: a25b9ef0c9fe242ac04bb20d3a028442b7d266b6 + version: f86db6b22663a27ba4d278220b7e34be528b1e79 subpackages: - context - digest diff --git a/glide.yaml b/glide.yaml index 339f74c2d..3b9db327f 100644 --- a/glide.yaml +++ b/glide.yaml @@ -28,9 +28,7 @@ import: subpackages: - cli/config/configfile - package: github.com/docker/distribution - version: ^2.6.1 - subpackages: - - manifest/schema1 + branch: master - package: github.com/fsouza/go-dockerclient - package: github.com/garyburd/redigo subpackages: diff --git a/vendor/github.com/docker/distribution/BUILDING.md b/vendor/github.com/docker/distribution/BUILDING.md index 2d5a10119..d52ed0d94 100644 --- a/vendor/github.com/docker/distribution/BUILDING.md +++ b/vendor/github.com/docker/distribution/BUILDING.md @@ -71,9 +71,7 @@ commands, such as `go test`, should work per package (please see A `Makefile` has been provided as a convenience to support repeatable builds. Please install the following into `GOPATH` for it to work: - go get github.com/tools/godep github.com/golang/lint/golint - -**TODO(stevvooe):** Add a `make setup` command to Makefile to run this. Have to think about how to interact with Godeps properly. + go get github.com/golang/lint/golint Once these commands are available in the `GOPATH`, run `make` to get a full build: @@ -105,8 +103,8 @@ build: + /Users/sday/go/src/github.com/docker/distribution/bin/registry-api-descriptor-template + binaries -The above provides a repeatable build using the contents of the vendored -Godeps directory. This includes formatting, vetting, linting, building, +The above provides a repeatable build using the contents of the vendor +directory. This includes formatting, vetting, linting, building, testing and generating tagged binaries. We can verify this worked by running the registry binary generated in the "./bin" directory: diff --git a/vendor/github.com/docker/distribution/CHANGELOG.md b/vendor/github.com/docker/distribution/CHANGELOG.md index b1a5c6824..e7b16b3c2 100644 --- a/vendor/github.com/docker/distribution/CHANGELOG.md +++ b/vendor/github.com/docker/distribution/CHANGELOG.md @@ -1,11 +1,5 @@ # Changelog -## 2.6.1 (2017-04-05) - -#### Registry -- Fix `Forwarded` header handling, revert use of `X-Forwarded-Port` -- Use driver `Stat` for registry health check - ## 2.6.0 (2017-01-18) #### Storage diff --git a/vendor/github.com/docker/distribution/Dockerfile b/vendor/github.com/docker/distribution/Dockerfile index 426954a11..ac8dbca2f 100644 --- a/vendor/github.com/docker/distribution/Dockerfile +++ b/vendor/github.com/docker/distribution/Dockerfile @@ -1,8 +1,11 @@ -FROM golang:1.7-alpine +FROM golang:1.8-alpine ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution ENV DOCKER_BUILDTAGS include_oss include_gcs +ARG GOOS=linux +ARG GOARCH=amd64 + RUN set -ex \ && apk add --no-cache make git diff --git a/vendor/github.com/docker/distribution/Godeps/Godeps.json b/vendor/github.com/docker/distribution/Godeps/Godeps.json deleted file mode 100644 index dbdd89149..000000000 --- a/vendor/github.com/docker/distribution/Godeps/Godeps.json +++ /dev/null @@ -1,458 +0,0 @@ -{ - "ImportPath": "github.com/docker/distribution", - "GoVersion": "go1.6", - "GodepVersion": "v74", - "Packages": [ - "./..." - ], - "Deps": [ - { - "ImportPath": "github.com/Azure/azure-sdk-for-go/storage", - "Comment": "v5.0.0-beta-6-g0b5fe2a", - "Rev": "0b5fe2abe0271ba07049eacaa65922d67c319543" - }, - { - "ImportPath": "github.com/Sirupsen/logrus", - "Comment": "v0.7.3", - "Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d" - }, - { - "ImportPath": "github.com/Sirupsen/logrus/formatters/logstash", - "Comment": "v0.7.3", - "Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/awserr", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/client", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/credentials", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/defaults", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/request", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/session", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/aws/signer/v4", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/endpoints", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/private/waiter", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/service/cloudfront/sign", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/service/s3", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/vendor/github.com/go-ini/ini", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/aws/aws-sdk-go/vendor/github.com/jmespath/go-jmespath", - "Comment": "v1.2.4", - "Rev": "90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6" - }, - { - "ImportPath": "github.com/bugsnag/bugsnag-go", - "Comment": "v1.0.2-5-gb1d1530", - "Rev": "b1d153021fcd90ca3f080db36bec96dc690fb274" - }, - { - "ImportPath": "github.com/bugsnag/bugsnag-go/errors", - "Comment": "v1.0.2-5-gb1d1530", - "Rev": "b1d153021fcd90ca3f080db36bec96dc690fb274" - }, - { - "ImportPath": "github.com/bugsnag/osext", - "Rev": "0dd3f918b21bec95ace9dc86c7e70266cfc5c702" - }, - { - "ImportPath": "github.com/bugsnag/panicwrap", - "Comment": "1.0.0-2-ge2c2850", - "Rev": "e2c28503fcd0675329da73bf48b33404db873782" - }, - { - "ImportPath": "github.com/denverdino/aliyungo/common", - "Rev": "afedced274aa9a7fcdd47ac97018f0f8db4e5de2" - }, - { - "ImportPath": "github.com/denverdino/aliyungo/oss", - "Rev": "afedced274aa9a7fcdd47ac97018f0f8db4e5de2" - }, - { - "ImportPath": "github.com/denverdino/aliyungo/util", - "Rev": "afedced274aa9a7fcdd47ac97018f0f8db4e5de2" - }, - { - "ImportPath": "github.com/docker/goamz/aws", - "Rev": "f0a21f5b2e12f83a505ecf79b633bb2035cf6f85" - }, - { - "ImportPath": "github.com/docker/goamz/s3", - "Rev": "f0a21f5b2e12f83a505ecf79b633bb2035cf6f85" - }, - { - "ImportPath": "github.com/docker/libtrust", - "Rev": "fa567046d9b14f6aa788882a950d69651d230b21" - }, - { - "ImportPath": "github.com/garyburd/redigo/internal", - "Rev": "535138d7bcd717d6531c701ef5933d98b1866257" - }, - { - "ImportPath": "github.com/garyburd/redigo/redis", - "Rev": "535138d7bcd717d6531c701ef5933d98b1866257" - }, - { - "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "8d92cf5fc15a4382f8964b08e1f42a75c0591aa3" - }, - { - "ImportPath": "github.com/gorilla/context", - "Rev": "14f550f51af52180c2eefed15e5fd18d63c0a64a" - }, - { - "ImportPath": "github.com/gorilla/handlers", - "Rev": "60c7bfde3e33c201519a200a4507a158cc03a17b" - }, - { - "ImportPath": "github.com/gorilla/mux", - "Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf" - }, - { - "ImportPath": "github.com/inconshreveable/mousetrap", - "Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" - }, - { - "ImportPath": "github.com/mitchellh/mapstructure", - "Rev": "482a9fd5fa83e8c4e7817413b80f3eb8feec03ef" - }, - { - "ImportPath": "github.com/ncw/swift", - "Rev": "ce444d6d47c51d4dda9202cd38f5094dd8e27e86" - }, - { - "ImportPath": "github.com/ncw/swift/swifttest", - "Rev": "ce444d6d47c51d4dda9202cd38f5094dd8e27e86" - }, - { - "ImportPath": "github.com/spf13/cobra", - "Rev": "312092086bed4968099259622145a0c9ae280064" - }, - { - "ImportPath": "github.com/spf13/pflag", - "Rev": "5644820622454e71517561946e3d94b9f9db6842" - }, - { - "ImportPath": "github.com/stevvooe/resumable", - "Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4" - }, - { - "ImportPath": "github.com/stevvooe/resumable/sha256", - "Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4" - }, - { - "ImportPath": "github.com/stevvooe/resumable/sha512", - "Rev": "51ad44105773cafcbe91927f70ac68e1bf78f8b4" - }, - { - "ImportPath": "github.com/yvasiyarov/go-metrics", - "Rev": "57bccd1ccd43f94bb17fdd8bf3007059b802f85e" - }, - { - "ImportPath": "github.com/yvasiyarov/gorelic", - "Comment": "v0.0.6-8-ga9bba5b", - "Rev": "a9bba5b9ab508a086f9a12b8c51fab68478e2128" - }, - { - "ImportPath": "github.com/yvasiyarov/newrelic_platform_go", - "Rev": "b21fdbd4370f3717f3bbd2bf41c223bc273068e6" - }, - { - "ImportPath": "golang.org/x/crypto/bcrypt", - "Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b" - }, - { - "ImportPath": "golang.org/x/crypto/blowfish", - "Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b" - }, - { - "ImportPath": "golang.org/x/crypto/ocsp", - "Rev": "c10c31b5e94b6f7a0283272dc2bb27163dcea24b" - }, - { - "ImportPath": "golang.org/x/net/context", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/net/context/ctxhttp", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/net/http2", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/net/http2/hpack", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/net/internal/timeseries", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/net/trace", - "Rev": "4876518f9e71663000c348837735820161a42df7" - }, - { - "ImportPath": "golang.org/x/oauth2", - "Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf" - }, - { - "ImportPath": "golang.org/x/oauth2/google", - "Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf" - }, - { - "ImportPath": "golang.org/x/oauth2/internal", - "Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf" - }, - { - "ImportPath": "golang.org/x/oauth2/jws", - "Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf" - }, - { - "ImportPath": "golang.org/x/oauth2/jwt", - "Rev": "045497edb6234273d67dbc25da3f2ddbc4c4cacf" - }, - { - "ImportPath": "golang.org/x/time/rate", - "Rev": "a4bde12657593d5e90d0533a3e4fd95e635124cb" - }, - { - "ImportPath": "google.golang.org/api/gensupport", - "Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54" - }, - { - "ImportPath": "google.golang.org/api/googleapi", - "Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54" - }, - { - "ImportPath": "google.golang.org/api/googleapi/internal/uritemplates", - "Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54" - }, - { - "ImportPath": "google.golang.org/api/storage/v1", - "Rev": "9bf6e6e569ff057f75d9604a46c52928f17d2b54" - }, - { - "ImportPath": "google.golang.org/appengine", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/app_identity", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/base", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/datastore", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/log", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/modules", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/appengine/internal/remote_api", - "Rev": "12d5545dc1cfa6047a286d5e853841b6471f4c19" - }, - { - "ImportPath": "google.golang.org/cloud", - "Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2" - }, - { - "ImportPath": "google.golang.org/cloud/compute/metadata", - "Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2" - }, - { - "ImportPath": "google.golang.org/cloud/internal", - "Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2" - }, - { - "ImportPath": "google.golang.org/cloud/internal/opts", - "Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2" - }, - { - "ImportPath": "google.golang.org/cloud/storage", - "Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2" - }, - { - "ImportPath": "google.golang.org/grpc", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/codes", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/credentials", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/grpclog", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/internal", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/metadata", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/naming", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/peer", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "google.golang.org/grpc/transport", - "Rev": "d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994" - }, - { - "ImportPath": "gopkg.in/check.v1", - "Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673" - }, - { - "ImportPath": "gopkg.in/yaml.v2", - "Rev": "bef53efd0c76e49e6de55ead051f886bea7e9420" - }, - { - "ImportPath": "rsc.io/letsencrypt", - "Rev": "a019c9e6fce0c7132679dea13bd8df7c86ffe26c" - }, - { - "ImportPath": "rsc.io/letsencrypt/vendor/github.com/xenolf/lego/acme", - "Rev": "a019c9e6fce0c7132679dea13bd8df7c86ffe26c" - }, - { - "ImportPath": "rsc.io/letsencrypt/vendor/gopkg.in/square/go-jose.v1", - "Rev": "a019c9e6fce0c7132679dea13bd8df7c86ffe26c" - }, - { - "ImportPath": "rsc.io/letsencrypt/vendor/gopkg.in/square/go-jose.v1/cipher", - "Rev": "a019c9e6fce0c7132679dea13bd8df7c86ffe26c" - }, - { - "ImportPath": "rsc.io/letsencrypt/vendor/gopkg.in/square/go-jose.v1/json", - "Rev": "a019c9e6fce0c7132679dea13bd8df7c86ffe26c" - } - ] -} diff --git a/vendor/github.com/docker/distribution/Godeps/Readme b/vendor/github.com/docker/distribution/Godeps/Readme deleted file mode 100644 index 4cdaa53d5..000000000 --- a/vendor/github.com/docker/distribution/Godeps/Readme +++ /dev/null @@ -1,5 +0,0 @@ -This directory tree is generated automatically by godep. - -Please do not edit. - -See https://github.com/tools/godep for more information. diff --git a/vendor/github.com/docker/distribution/Makefile b/vendor/github.com/docker/distribution/Makefile index 47b8f1d0b..7c6f9c7a6 100644 --- a/vendor/github.com/docker/distribution/Makefile +++ b/vendor/github.com/docker/distribution/Makefile @@ -35,7 +35,7 @@ PKGS=$(shell go list -tags "${DOCKER_BUILDTAGS}" ./... | grep -v ^github.com/doc # Resolving binary dependencies for specific targets GOLINT=$(shell which golint || echo '') -GODEP=$(shell which godep || echo '') +VNDR=$(shell which vndr || echo '') ${PREFIX}/bin/registry: $(GOFILES) @echo "+ $@" @@ -86,24 +86,14 @@ clean: @echo "+ $@" @rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/digest" "${PREFIX}/bin/registry-api-descriptor-template" -dep-save: - @echo "+ $@" - $(if $(GODEP), , \ - $(error Please install godep: go get github.com/tools/godep)) - @$(GODEP) save $(PKGS) - -dep-restore: - @echo "+ $@" - $(if $(GODEP), , \ - $(error Please install godep: go get github.com/tools/godep)) - @$(GODEP) restore -v - -dep-validate: dep-restore +dep-validate: @echo "+ $@" + $(if $(VNDR), , \ + $(error Please install vndr: go get github.com/lk4d4/vndr)) @rm -Rf .vendor.bak @mv vendor .vendor.bak - @rm -Rf Godeps - @$(GODEP) save ./... + @$(VNDR) @test -z "$$(diff -r vendor .vendor.bak 2>&1 | tee /dev/stderr)" || \ - (echo >&2 "+ borked dependencies! what you have in Godeps/Godeps.json does not match with what you have in vendor" && false) - @rm -Rf .vendor.bak + (echo >&2 "+ inconsistent dependencies! what you have in vendor.conf does not match with what you have in vendor" && false) + @rm -Rf vendor + @mv .vendor.bak vendor diff --git a/vendor/github.com/docker/distribution/README.md b/vendor/github.com/docker/distribution/README.md index a6e8db0fb..998878850 100644 --- a/vendor/github.com/docker/distribution/README.md +++ b/vendor/github.com/docker/distribution/README.md @@ -76,8 +76,7 @@ may be the better choice. For those who have previously deployed their own registry based on the Registry 1.0 implementation and wish to deploy a Registry 2.0 while retaining images, data migration is required. A tool to assist with migration efforts has been -created. For more information see [docker/migrator] -(https://github.com/docker/migrator). +created. For more information see [docker/migrator](https://github.com/docker/migrator). ## Contribute diff --git a/vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md b/vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md index 49235cecd..73eba5a87 100644 --- a/vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md +++ b/vendor/github.com/docker/distribution/RELEASE-CHECKLIST.md @@ -1,19 +1,27 @@ ## Registry Release Checklist -10. Compile release notes detailing features and since the last release. Update the `CHANGELOG.md` file. +10. Compile release notes detailing features and since the last release. + + Update the `CHANGELOG.md` file and create a PR to master with the updates. +Once that PR has been approved by maintainers the change may be cherry-picked +to the release branch (new release branches may be forked from this commit). 20. Update the version file: `https://github.com/docker/distribution/blob/master/version/version.go` 30. Update the `MAINTAINERS` (if necessary), `AUTHORS` and `.mailmap` files. - ``` +``` make AUTHORS ``` 40. Create a signed tag. - Distribution uses semantic versioning. Tags are of the format `vx.y.z[-rcn]` -You will need PGP installed and a PGP key which has been added to your Github account. The comment for the tag should include the release notes. + Distribution uses semantic versioning. Tags are of the format +`vx.y.z[-rcn]`. You will need PGP installed and a PGP key which has been added +to your Github account. The comment for the tag should include the release +notes, use previous tags as a guide for formatting consistently. Run +`git tag -s vx.y.z[-rcn]` to create tag and `git -v vx.y.z[-rcn]` to verify tag, +check comment and correct commit hash. 50. Push the signed tag diff --git a/vendor/github.com/docker/distribution/blobs.go b/vendor/github.com/docker/distribution/blobs.go index 1f91ae21e..01d309029 100644 --- a/vendor/github.com/docker/distribution/blobs.go +++ b/vendor/github.com/docker/distribution/blobs.go @@ -8,8 +8,8 @@ import ( "time" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" + "github.com/opencontainers/go-digest" ) var ( @@ -152,7 +152,7 @@ type BlobProvider interface { // BlobServer can serve blobs via http. type BlobServer interface { - // ServeBlob attempts to serve the blob, identifed by dgst, via http. The + // ServeBlob attempts to serve the blob, identified by dgst, via http. The // service may decide to redirect the client elsewhere or serve the data // directly. // diff --git a/vendor/github.com/docker/distribution/circle.yml b/vendor/github.com/docker/distribution/circle.yml index 61f8be0cb..ddc76c86c 100644 --- a/vendor/github.com/docker/distribution/circle.yml +++ b/vendor/github.com/docker/distribution/circle.yml @@ -8,7 +8,7 @@ machine: post: # go - - gvm install go1.7 --prefer-binary --name=stable + - gvm install go1.8 --prefer-binary --name=stable environment: # Convenient shortcuts to "common" locations @@ -34,7 +34,7 @@ dependencies: override: # Install dependencies for every copied clone/go version - - gvm use stable && go get github.com/tools/godep: + - gvm use stable && go get github.com/lk4d4/vndr: pwd: $BASE_STABLE post: @@ -49,14 +49,15 @@ test: # - gvm use old && go version - gvm use stable && go version - # todo(richard): replace with a more robust vendoring solution. Removed due to a fundamental disagreement in godep philosophies. # Ensure validation of dependencies - # - gvm use stable && if test -n "`git diff --stat=1000 master | grep -Ei \"vendor|godeps\"`"; then make dep-validate; fi: - # pwd: $BASE_STABLE + - git fetch origin: + pwd: $BASE_STABLE + - gvm use stable && if test -n "`git diff --stat=1000 origin/master | grep -E \"^[[:space:]]*vendor\"`"; then make dep-validate; fi: + pwd: $BASE_STABLE # First thing: build everything. This will catch compile errors, and it's # also necessary for go vet to work properly (see #807). - - gvm use stable && godep go install $(go list ./... | grep -v "/vendor/"): + - gvm use stable && go install $(go list ./... | grep -v "/vendor/"): pwd: $BASE_STABLE # FMT @@ -73,12 +74,12 @@ test: override: # Test stable, and report - - gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; godep go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/$PACKAGE/coverage.out -coverpkg=$(./coverpkg.sh $PACKAGE $ROOT_PACKAGE) $PACKAGE': + - gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/$PACKAGE/coverage.out -coverpkg=$(./coverpkg.sh $PACKAGE $ROOT_PACKAGE) $PACKAGE': timeout: 1000 pwd: $BASE_STABLE # Test stable with race - - gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | grep -v "registry/handlers" | grep -v "registry/storage/driver" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; godep go test -race -tags "$DOCKER_BUILDTAGS" -test.short $PACKAGE': + - gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | grep -v "registry/handlers" | grep -v "registry/storage/driver" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; go test -race -tags "$DOCKER_BUILDTAGS" -test.short $PACKAGE': timeout: 1000 pwd: $BASE_STABLE post: diff --git a/vendor/github.com/docker/distribution/cmd/digest/main.go b/vendor/github.com/docker/distribution/cmd/digest/main.go index 49426a886..20f64ddb4 100644 --- a/vendor/github.com/docker/distribution/cmd/digest/main.go +++ b/vendor/github.com/docker/distribution/cmd/digest/main.go @@ -7,8 +7,8 @@ import ( "log" "os" - "github.com/docker/distribution/digest" "github.com/docker/distribution/version" + "github.com/opencontainers/go-digest" ) var ( @@ -32,7 +32,7 @@ func init() { func usage() { fmt.Fprintf(os.Stderr, "usage: %s [files...]\n", os.Args[0]) - fmt.Fprintf(os.Stderr, ` + fmt.Fprint(os.Stderr, ` Calculate the digest of one or more input files, emitting the result to standard out. If no files are provided, the digest of stdin will be calculated. diff --git a/vendor/github.com/docker/distribution/configuration/configuration.go b/vendor/github.com/docker/distribution/configuration/configuration.go index ec50a6b18..cdc996b9d 100644 --- a/vendor/github.com/docker/distribution/configuration/configuration.go +++ b/vendor/github.com/docker/distribution/configuration/configuration.go @@ -1,6 +1,7 @@ package configuration import ( + "errors" "fmt" "io" "io/ioutil" @@ -132,7 +133,7 @@ type Configuration struct { // HTTP2 configuration options HTTP2 struct { - // Specifies wether the registry should disallow clients attempting + // Specifies whether the registry should disallow clients attempting // to connect via http2. If set to true, only http/1.1 is supported. Disabled bool `yaml:"disabled,omitempty"` } `yaml:"http2,omitempty"` @@ -188,8 +189,11 @@ type Configuration struct { // Validation configures validation options for the registry. Validation struct { - // Enabled enables the other options in this section. + // Enabled enables the other options in this section. This field is + // deprecated in favor of Disabled. Enabled bool `yaml:"enabled,omitempty"` + // Disabled disables the other options in this section. + Disabled bool `yaml:"disabled,omitempty"` // Manifests configures manifest validation. Manifests struct { // URLs configures validation for URLs in pushed manifests. @@ -232,7 +236,7 @@ type LogHook struct { // Levels set which levels of log message will let hook executed. Levels []string `yaml:"levels,omitempty"` - // MailOptions allows user to configurate email parameters. + // MailOptions allows user to configure email parameters. MailOptions MailOptions `yaml:"options,omitempty"` } @@ -326,7 +330,7 @@ type Health struct { type v0_1Configuration Configuration // UnmarshalYAML implements the yaml.Unmarshaler interface -// Unmarshals a string of the form X.Y into a Version, validating that X and Y can represent uints +// Unmarshals a string of the form X.Y into a Version, validating that X and Y can represent unsigned integers func (version *Version) UnmarshalYAML(unmarshal func(interface{}) error) error { var versionString string err := unmarshal(&versionString) @@ -624,7 +628,7 @@ func Parse(rd io.Reader) (*Configuration, error) { v0_1.Loglevel = Loglevel("info") } if v0_1.Storage.Type() == "" { - return nil, fmt.Errorf("No storage configuration provided") + return nil, errors.New("No storage configuration provided") } return (*Configuration)(v0_1), nil } diff --git a/vendor/github.com/docker/distribution/context/doc.go b/vendor/github.com/docker/distribution/context/doc.go index 3b4ab8882..9b623074e 100644 --- a/vendor/github.com/docker/distribution/context/doc.go +++ b/vendor/github.com/docker/distribution/context/doc.go @@ -64,7 +64,7 @@ // Note that this only affects the new context, the previous context, with the // version field, can be used independently. Put another way, the new logger, // added to the request context, is unique to that context and can have -// request scoped varaibles. +// request scoped variables. // // HTTP Requests // diff --git a/vendor/github.com/docker/distribution/contrib/compose/README.md b/vendor/github.com/docker/distribution/contrib/compose/README.md index a9522fd24..45050b70d 100644 --- a/vendor/github.com/docker/distribution/contrib/compose/README.md +++ b/vendor/github.com/docker/distribution/contrib/compose/README.md @@ -123,13 +123,13 @@ to the 1.0 registry. Requests from newer clients will route to the 2.0 registry. 4. Use `curl` to list the image in the registry. - $ curl -v -X GET http://localhost:32777/v2/registry1/tags/list + $ curl -v -X GET http://localhost:5000/v2/registry_one/tags/list * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 32777 (#0) > GET /v2/registry1/tags/list HTTP/1.1 > User-Agent: curl/7.36.0 - > Host: localhost:32777 + > Host: localhost:5000 > Accept: */* > < HTTP/1.1 200 OK @@ -138,7 +138,7 @@ to the 1.0 registry. Requests from newer clients will route to the 2.0 registry. < Date: Tue, 14 Apr 2015 22:34:13 GMT < Content-Length: 39 < - {"name":"registry1","tags":["latest"]} + {"name":"registry_one","tags":["latest"]} * Connection #0 to host localhost left intact This example refers to the specific port assigned to the 2.0 registry. You saw diff --git a/vendor/github.com/docker/distribution/contrib/docker-integration/docker-compose.yml b/vendor/github.com/docker/distribution/contrib/docker-integration/docker-compose.yml index 4d4f3856f..374197acc 100644 --- a/vendor/github.com/docker/distribution/contrib/docker-integration/docker-compose.yml +++ b/vendor/github.com/docker/distribution/contrib/docker-integration/docker-compose.yml @@ -64,7 +64,7 @@ registryv2tokenoauthnotls: - ./tokenserver-oauth/certs/signing.cert:/etc/docker/registry/tokenbundle.pem tokenserveroauth: build: "tokenserver-oauth" - command: "--debug -addr 0.0.0.0:5559 -issuer registry-test -passwd .htpasswd -tlscert tls.cert -tlskey tls.key -key sign.key -realm http://auth.localregistry:5559" + command: "--debug -addr 0.0.0.0:5559 -issuer registry-test -passwd .htpasswd -tlscert tls.cert -tlskey tls.key -key sign.key -realm http://auth.localregistry:5559 -enforce-class" ports: - "5559" malevolent: diff --git a/vendor/github.com/docker/distribution/contrib/docker-integration/golem.conf b/vendor/github.com/docker/distribution/contrib/docker-integration/golem.conf index 99c8d600c..eb1757076 100644 --- a/vendor/github.com/docker/distribution/contrib/docker-integration/golem.conf +++ b/vendor/github.com/docker/distribution/contrib/docker-integration/golem.conf @@ -1,6 +1,6 @@ [[suite]] dind=true - images=[ "nginx:1.9", "dmcgowan/token-server:simple", "dmcgowan/token-server:oauth", "dmcgowan/malevolent:0.1.0" ] + images=[ "nginx:1.9", "dmcgowan/token-server:simple", "dmcgowan/token-server:oauth", "dmcgowan/malevolent:0.1.0", "dmcgowan/ncat:latest" ] [[suite.pretest]] command="sh ./install_certs.sh /etc/generated_certs.d" diff --git a/vendor/github.com/docker/distribution/contrib/docker-integration/helpers.bash b/vendor/github.com/docker/distribution/contrib/docker-integration/helpers.bash index e1813d3e5..8760f9cf3 100644 --- a/vendor/github.com/docker/distribution/contrib/docker-integration/helpers.bash +++ b/vendor/github.com/docker/distribution/contrib/docker-integration/helpers.bash @@ -32,18 +32,44 @@ function basic_auth_version_check() { fi } +email="a@nowhere.com" + +# docker_t_login calls login with email depending on version +function docker_t_login() { + # Only pass email field pre 1.11, no deprecation warning + parse_version "$GOLEM_DIND_VERSION" + v=$version + parse_version "1.11.0" + if [ "$v" -lt "$version" ]; then + run docker_t login -e $email $@ + else + run docker_t login $@ + fi +} + # login issues a login to docker to the provided server # uses user, password, and email variables set outside of function # requies bats function login() { rm -f /root/.docker/config.json - run docker_t login -u $user -p $password -e $email $1 + + docker_t_login -u $user -p $password $1 if [ "$status" -ne 0 ]; then echo $output fi [ "$status" -eq 0 ] - # First line is WARNING about credential save or email deprecation (maybe both) - [ "${lines[2]}" = "Login Succeeded" -o "${lines[1]}" = "Login Succeeded" ] + + # Handle different deprecation warnings + parse_version "$GOLEM_DIND_VERSION" + v=$version + parse_version "1.11.0" + if [ "$v" -lt "$version" ]; then + # First line is WARNING about credential save or email deprecation (maybe both) + [ "${lines[2]}" = "Login Succeeded" -o "${lines[1]}" = "Login Succeeded" ] + else + [ "${lines[0]}" = "Login Succeeded" ] + fi + } function login_oauth() { @@ -92,7 +118,7 @@ function docker_t() { docker exec dockerdaemon docker $@ } -# build reates a new docker image id from another image +# build creates a new docker image id from another image function build() { docker exec -i dockerdaemon docker build --no-cache -t $1 - < $plugindir/config.json <: -// -// An example of a sha256 digest representation follows: -// -// sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc -// -// In this case, the string "sha256" is the algorithm and the hex bytes are -// the "digest". -// -// Because the Digest type is simply a string, once a valid Digest is -// obtained, comparisons are cheap, quick and simple to express with the -// standard equality operator. -// -// Verification -// -// The main benefit of using the Digest type is simple verification against a -// given digest. The Verifier interface, modeled after the stdlib hash.Hash -// interface, provides a common write sink for digest verification. After -// writing is complete, calling the Verifier.Verified method will indicate -// whether or not the stream of bytes matches the target digest. -// -// Missing Features -// -// In addition to the above, we intend to add the following features to this -// package: -// -// 1. A Digester type that supports write sink digest calculation. -// -// 2. Suspend and resume of ongoing digest calculations to support efficient digest verification in the registry. -// -package digest diff --git a/vendor/github.com/docker/distribution/digest/verifiers.go b/vendor/github.com/docker/distribution/digest/verifiers.go deleted file mode 100644 index 9af3be134..000000000 --- a/vendor/github.com/docker/distribution/digest/verifiers.go +++ /dev/null @@ -1,44 +0,0 @@ -package digest - -import ( - "hash" - "io" -) - -// Verifier presents a general verification interface to be used with message -// digests and other byte stream verifications. Users instantiate a Verifier -// from one of the various methods, write the data under test to it then check -// the result with the Verified method. -type Verifier interface { - io.Writer - - // Verified will return true if the content written to Verifier matches - // the digest. - Verified() bool -} - -// NewDigestVerifier returns a verifier that compares the written bytes -// against a passed in digest. -func NewDigestVerifier(d Digest) (Verifier, error) { - if err := d.Validate(); err != nil { - return nil, err - } - - return hashVerifier{ - hash: d.Algorithm().Hash(), - digest: d, - }, nil -} - -type hashVerifier struct { - digest Digest - hash hash.Hash -} - -func (hv hashVerifier) Write(p []byte) (n int, err error) { - return hv.hash.Write(p) -} - -func (hv hashVerifier) Verified() bool { - return hv.digest == NewDigest(hv.digest.Algorithm(), hv.hash) -} diff --git a/vendor/github.com/docker/distribution/digest/verifiers_test.go b/vendor/github.com/docker/distribution/digest/verifiers_test.go deleted file mode 100644 index c342d6e7c..000000000 --- a/vendor/github.com/docker/distribution/digest/verifiers_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package digest - -import ( - "bytes" - "crypto/rand" - "io" - "testing" -) - -func TestDigestVerifier(t *testing.T) { - p := make([]byte, 1<<20) - rand.Read(p) - digest := FromBytes(p) - - verifier, err := NewDigestVerifier(digest) - if err != nil { - t.Fatalf("unexpected error getting digest verifier: %s", err) - } - - io.Copy(verifier, bytes.NewReader(p)) - - if !verifier.Verified() { - t.Fatalf("bytes not verified") - } -} - -// TestVerifierUnsupportedDigest ensures that unsupported digest validation is -// flowing through verifier creation. -func TestVerifierUnsupportedDigest(t *testing.T) { - unsupported := Digest("bean:0123456789abcdef") - - _, err := NewDigestVerifier(unsupported) - if err == nil { - t.Fatalf("expected error when creating verifier") - } - - if err != ErrDigestUnsupported { - t.Fatalf("incorrect error for unsupported digest: %v", err) - } -} - -// TODO(stevvooe): Add benchmarks to measure bytes/second throughput for -// DigestVerifier. -// -// The relevant benchmark for comparison can be run with the following -// commands: -// -// go test -bench . crypto/sha1 -// diff --git a/vendor/github.com/docker/distribution/digest/set.go b/vendor/github.com/docker/distribution/digestset/set.go similarity index 90% rename from vendor/github.com/docker/distribution/digest/set.go rename to vendor/github.com/docker/distribution/digestset/set.go index 4b9313c1a..71327dca7 100644 --- a/vendor/github.com/docker/distribution/digest/set.go +++ b/vendor/github.com/docker/distribution/digestset/set.go @@ -1,10 +1,12 @@ -package digest +package digestset import ( "errors" "sort" "strings" "sync" + + digest "github.com/opencontainers/go-digest" ) var ( @@ -44,7 +46,7 @@ func NewSet() *Set { // values or short values. This function does not test equality, // rather whether the second value could match against the first // value. -func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool { +func checkShortMatch(alg digest.Algorithm, hex, shortAlg, shortHex string) bool { if len(hex) == len(shortHex) { if hex != shortHex { return false @@ -64,7 +66,7 @@ func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool { // If no digests could be found ErrDigestNotFound will be returned // with an empty digest value. If multiple matches are found // ErrDigestAmbiguous will be returned with an empty digest value. -func (dst *Set) Lookup(d string) (Digest, error) { +func (dst *Set) Lookup(d string) (digest.Digest, error) { dst.mutex.RLock() defer dst.mutex.RUnlock() if len(dst.entries) == 0 { @@ -72,11 +74,11 @@ func (dst *Set) Lookup(d string) (Digest, error) { } var ( searchFunc func(int) bool - alg Algorithm + alg digest.Algorithm hex string ) - dgst, err := ParseDigest(d) - if err == ErrDigestInvalidFormat { + dgst, err := digest.Parse(d) + if err == digest.ErrDigestInvalidFormat { hex = d searchFunc = func(i int) bool { return dst.entries[i].val >= d @@ -108,7 +110,7 @@ func (dst *Set) Lookup(d string) (Digest, error) { // Add adds the given digest to the set. An error will be returned // if the given digest is invalid. If the digest already exists in the // set, this operation will be a no-op. -func (dst *Set) Add(d Digest) error { +func (dst *Set) Add(d digest.Digest) error { if err := d.Validate(); err != nil { return err } @@ -139,7 +141,7 @@ func (dst *Set) Add(d Digest) error { // Remove removes the given digest from the set. An err will be // returned if the given digest is invalid. If the digest does // not exist in the set, this operation will be a no-op. -func (dst *Set) Remove(d Digest) error { +func (dst *Set) Remove(d digest.Digest) error { if err := d.Validate(); err != nil { return err } @@ -167,10 +169,10 @@ func (dst *Set) Remove(d Digest) error { } // All returns all the digests in the set -func (dst *Set) All() []Digest { +func (dst *Set) All() []digest.Digest { dst.mutex.RLock() defer dst.mutex.RUnlock() - retValues := make([]Digest, len(dst.entries)) + retValues := make([]digest.Digest, len(dst.entries)) for i := range dst.entries { retValues[i] = dst.entries[i].digest } @@ -183,10 +185,10 @@ func (dst *Set) All() []Digest { // entire value of digest if uniqueness cannot be achieved without the // full value. This function will attempt to make short codes as short // as possible to be unique. -func ShortCodeTable(dst *Set, length int) map[Digest]string { +func ShortCodeTable(dst *Set, length int) map[digest.Digest]string { dst.mutex.RLock() defer dst.mutex.RUnlock() - m := make(map[Digest]string, len(dst.entries)) + m := make(map[digest.Digest]string, len(dst.entries)) l := length resetIdx := 0 for i := 0; i < len(dst.entries); i++ { @@ -222,9 +224,9 @@ func ShortCodeTable(dst *Set, length int) map[Digest]string { } type digestEntry struct { - alg Algorithm + alg digest.Algorithm val string - digest Digest + digest digest.Digest } type digestEntries []*digestEntry diff --git a/vendor/github.com/docker/distribution/digest/set_test.go b/vendor/github.com/docker/distribution/digestset/set_test.go similarity index 93% rename from vendor/github.com/docker/distribution/digest/set_test.go rename to vendor/github.com/docker/distribution/digestset/set_test.go index e9dab8795..89c5729d0 100644 --- a/vendor/github.com/docker/distribution/digest/set_test.go +++ b/vendor/github.com/docker/distribution/digestset/set_test.go @@ -1,20 +1,23 @@ -package digest +package digestset import ( "crypto/sha256" + _ "crypto/sha512" "encoding/binary" "math/rand" "testing" + + digest "github.com/opencontainers/go-digest" ) -func assertEqualDigests(t *testing.T, d1, d2 Digest) { +func assertEqualDigests(t *testing.T, d1, d2 digest.Digest) { if d1 != d2 { t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2) } } func TestLookup(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -88,7 +91,7 @@ func TestLookup(t *testing.T) { } func TestAddDuplication(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -110,7 +113,7 @@ func TestAddDuplication(t *testing.T) { t.Fatal("Invalid dset size") } - if err := dset.Add(Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { + if err := dset.Add(digest.Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { t.Fatal(err) } @@ -118,7 +121,7 @@ func TestAddDuplication(t *testing.T) { t.Fatal("Duplicate digest insert allowed") } - if err := dset.Add(Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { + if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { t.Fatal(err) } @@ -170,7 +173,7 @@ func TestAll(t *testing.T) { } } - all := map[Digest]struct{}{} + all := map[digest.Digest]struct{}{} for _, dgst := range dset.All() { all[dgst] = struct{}{} } @@ -194,7 +197,7 @@ func assertEqualShort(t *testing.T, actual, expected string) { } func TestShortCodeTable(t *testing.T) { - digests := []Digest{ + digests := []digest.Digest{ "sha256:1234111111111111111111111111111111111111111111111111111111111111", "sha256:1234511111111111111111111111111111111111111111111111111111111111", "sha256:1234611111111111111111111111111111111111111111111111111111111111", @@ -227,15 +230,15 @@ func TestShortCodeTable(t *testing.T) { assertEqualShort(t, dump[digests[7]], "653") } -func createDigests(count int) ([]Digest, error) { +func createDigests(count int) ([]digest.Digest, error) { r := rand.New(rand.NewSource(25823)) - digests := make([]Digest, count) + digests := make([]digest.Digest, count) for i := range digests { h := sha256.New() if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil { return nil, err } - digests[i] = NewDigest("sha256", h) + digests[i] = digest.NewDigest("sha256", h) } return digests, nil } diff --git a/vendor/github.com/docker/distribution/docs/architecture.md b/vendor/github.com/docker/distribution/docs/architecture.md new file mode 100644 index 000000000..c2aaa9f2d --- /dev/null +++ b/vendor/github.com/docker/distribution/docs/architecture.md @@ -0,0 +1,52 @@ +--- +published: false +--- + +# Architecture + +## Design +**TODO(stevvooe):** Discuss the architecture of the registry, internally and externally, in a few different deployment scenarios. + +### Eventual Consistency + +> **NOTE:** This section belongs somewhere, perhaps in a design document. We +> are leaving this here so the information is not lost. + +Running the registry on eventually consistent backends has been part of the +design from the beginning. This section covers some of the approaches to +dealing with this reality. + +There are a few classes of issues that we need to worry about when +implementing something on top of the storage drivers: + +1. Read-After-Write consistency (see this [article on + s3](http://shlomoswidler.com/2009/12/read-after-write-consistency-in-amazon.html)). +2. [Write-Write Conflicts](http://en.wikipedia.org/wiki/Write%E2%80%93write_conflict). + +In reality, the registry must worry about these kinds of errors when doing the +following: + +1. Accepting data into a temporary upload file may not have latest data block + yet (read-after-write). +2. Moving uploaded data into its blob location (write-write race). +3. Modifying the "current" manifest for given tag (write-write race). +4. A whole slew of operations around deletes (read-after-write, delete-write + races, garbage collection, etc.). + +The backend path layout employs a few techniques to avoid these problems: + +1. Large writes are done to private upload directories. This alleviates most + of the corruption potential under multiple writers by avoiding multiple + writers. +2. Constraints in storage driver implementations, such as support for writing + after the end of a file to extend it. +3. Digest verification to avoid data corruption. +4. Manifest files are stored by digest and cannot change. +5. All other non-content files (links, hashes, etc.) are written as an atomic + unit. Anything that requires additions and deletions is broken out into + separate "files". Last writer still wins. + +Unfortunately, one must play this game when trying to build something like +this on top of eventually consistent storage systems. If we run into serious +problems, we can wrap the storagedrivers in a shared consistency layer but +that would increase complexity and hinder registry cluster performance. diff --git a/vendor/github.com/docker/distribution/docs/configuration.md b/vendor/github.com/docker/distribution/docs/configuration.md index a1c66b21c..c7f9023fb 100644 --- a/vendor/github.com/docker/distribution/docs/configuration.md +++ b/vendor/github.com/docker/distribution/docs/configuration.md @@ -223,9 +223,9 @@ notifications: disabled: false url: https://my.listener.com/event headers: - timeout: 500 - threshold: 5 - backoff: 1000 + timeout: 1s + threshold: 10 + backoff: 1s ignoredmediatypes: - application/octet-stream redis: @@ -268,7 +268,6 @@ compatibility: schema1: signingkeyfile: /etc/registry/key.json validation: - enabled: true manifests: urls: allow: @@ -553,7 +552,7 @@ The `auth` option is **optional**. Possible auth providers include: - [`silly`](#silly) - [`token`](#token) -- [`htpasswd`](#token) +- [`htpasswd`](#htpasswd) You can configure only one authentication provider. @@ -817,9 +816,9 @@ notifications: disabled: false url: https://my.listener.com/event headers: - timeout: 500 - threshold: 5 - backoff: 1000 + timeout: 1s + threshold: 10 + backoff: 1s ignoredmediatypes: - application/octet-stream ``` @@ -948,7 +947,7 @@ a file. | Parameter | Required | Description | |-----------|----------|-------------------------------------------------------| | `file` | yes | The path to check for existence of a file. | -| `interval`| no | How long to wait before repeating the check. A positive integer and an optional suffix indicating the unit of time. The suffix is one of `ns`, `us`, `ms`, `s`, `m`, or `h`. Defaults to `10s` if the value is omitted. | +| `interval`| no | How long to wait before repeating the check. A positive integer and an optional suffix indicating the unit of time. The suffix is one of `ns`, `us`, `ms`, `s`, `m`, or `h`. Defaults to `10s` if the value is omitted. If you specify a value but omit the suffix, the value is interpreted as a number of nanoseconds. | ### `http` @@ -1028,7 +1027,6 @@ features. Each subsection defines such a feature with configurable behavior. ```none validation: - enabled: true manifests: urls: allow: @@ -1037,14 +1035,15 @@ validation: - ^https?://www\.example\.com/ ``` -### `enabled` +### `disabled` -Use the `enabled` flag to enable the other options in the `validation` -section. They are disabled by default. +The `disabled` flag disables the other options in the `validation` +section. They are enabled by default. This option deprecates the `enabled` flag. ### `manifests` -Use the `manifest` subsection to configure manifest validation. +Use the `manifests` subsection to configure validation of manifests. If +`disabled` is `false`, the validation allows nothing. #### `urls` @@ -1110,7 +1109,7 @@ middleware: baseurl: http://d111111abcdef8.cloudfront.net privatekey: /path/to/asecret.pem keypairid: asecret - duration: 60 + duration: 60s ``` See the configuration reference for [Cloudfront](#cloudfront) for more diff --git a/vendor/github.com/docker/distribution/docs/spec/api.md b/vendor/github.com/docker/distribution/docs/spec/api.md index 74ac8e24f..efa55cfcf 100644 --- a/vendor/github.com/docker/distribution/docs/spec/api.md +++ b/vendor/github.com/docker/distribution/docs/spec/api.md @@ -795,7 +795,7 @@ Note that the upload url will not be available forever. If the upload uuid is unknown to the registry, a `404 Not Found` response will be returned and the client must restart the upload process. -### Deleting a Layer +#### Deleting a Layer A layer may be deleted from the registry via its `name` and `digest`. A delete may be issued with the following request format: diff --git a/vendor/github.com/docker/distribution/docs/spec/api.md.tmpl b/vendor/github.com/docker/distribution/docs/spec/api.md.tmpl index 406eda5be..cf7f92971 100644 --- a/vendor/github.com/docker/distribution/docs/spec/api.md.tmpl +++ b/vendor/github.com/docker/distribution/docs/spec/api.md.tmpl @@ -795,7 +795,7 @@ Note that the upload url will not be available forever. If the upload uuid is unknown to the registry, a `404 Not Found` response will be returned and the client must restart the upload process. -### Deleting a Layer +#### Deleting a Layer A layer may be deleted from the registry via its `name` and `digest`. A delete may be issued with the following request format: diff --git a/vendor/github.com/docker/distribution/docs/spec/manifest-v2-1.md b/vendor/github.com/docker/distribution/docs/spec/manifest-v2-1.md index b06c2f2a9..1fadc25a0 100644 --- a/vendor/github.com/docker/distribution/docs/spec/manifest-v2-1.md +++ b/vendor/github.com/docker/distribution/docs/spec/manifest-v2-1.md @@ -6,7 +6,7 @@ keywords: ["registry, on-prem, images, tags, repository, distribution, api, adva # Image Manifest Version 2, Schema 1 -This document outlines the format of of the V2 image manifest. The image +This document outlines the format of the V2 image manifest. The image manifest described herein was introduced in the Docker daemon in the [v1.3.0 release](https://github.com/docker/docker/commit/9f482a66ab37ec396ac61ed0c00d59122ac07453). It is a provisional manifest to provide a compatibility with the [V1 Image diff --git a/vendor/github.com/docker/distribution/docs/spec/manifest-v2-2.md b/vendor/github.com/docker/distribution/docs/spec/manifest-v2-2.md index 4b41bb28c..2319cf6d2 100644 --- a/vendor/github.com/docker/distribution/docs/spec/manifest-v2-2.md +++ b/vendor/github.com/docker/distribution/docs/spec/manifest-v2-2.md @@ -6,7 +6,7 @@ keywords: ["registry, on-prem, images, tags, repository, distribution, api, adva # Image Manifest Version 2, Schema 2 -This document outlines the format of of the V2 image manifest, schema version 2. +This document outlines the format of the V2 image manifest, schema version 2. The original (and provisional) image manifest for V2 (schema 1), was introduced in the Docker daemon in the [v1.3.0 release](https://github.com/docker/docker/commit/9f482a66ab37ec396ac61ed0c00d59122ac07453) @@ -60,8 +60,8 @@ image manifest based on the Content-Type returned in the HTTP response. - **`mediaType`** *string* The MIME type of the referenced object. This will generally be - `application/vnd.docker.image.manifest.v2+json`, but it could also - be `application/vnd.docker.image.manifest.v1+json` if the manifest + `application/vnd.docker.distribution.manifest.v2+json`, but it could also + be `application/vnd.docker.distribution.manifest.v1+json` if the manifest list references a legacy schema-1 manifest. - **`size`** *int* @@ -123,7 +123,7 @@ image manifest based on the Content-Type returned in the HTTP response. "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { - "mediaType": "application/vnd.docker.image.manifest.v2+json", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 7143, "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f", "platform": { @@ -132,7 +132,7 @@ image manifest based on the Content-Type returned in the HTTP response. } }, { - "mediaType": "application/vnd.docker.image.manifest.v2+json", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 7682, "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270", "platform": { diff --git a/vendor/github.com/docker/distribution/errors.go b/vendor/github.com/docker/distribution/errors.go index c20f28113..020d33258 100644 --- a/vendor/github.com/docker/distribution/errors.go +++ b/vendor/github.com/docker/distribution/errors.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // ErrAccessDenied is returned when an access to a requested resource is @@ -77,7 +77,7 @@ func (err ErrManifestUnknownRevision) Error() string { type ErrManifestUnverified struct{} func (ErrManifestUnverified) Error() string { - return fmt.Sprintf("unverified manifest") + return "unverified manifest" } // ErrManifestVerification provides a type to collect errors encountered diff --git a/vendor/github.com/docker/distribution/health/checks/checks.go b/vendor/github.com/docker/distribution/health/checks/checks.go index e3c3b08d3..7760f6105 100644 --- a/vendor/github.com/docker/distribution/health/checks/checks.go +++ b/vendor/github.com/docker/distribution/health/checks/checks.go @@ -2,9 +2,11 @@ package checks import ( "errors" + "fmt" "net" "net/http" "os" + "path/filepath" "strconv" "time" @@ -15,10 +17,19 @@ import ( // if the file exists. func FileChecker(f string) health.Checker { return health.CheckFunc(func() error { - if _, err := os.Stat(f); err == nil { - return errors.New("file exists") + absoluteFilePath, err := filepath.Abs(f) + if err != nil { + return fmt.Errorf("failed to get absolute path for %q: %v", f, err) } - return nil + + _, err = os.Stat(absoluteFilePath) + if err == nil { + return errors.New("file exists") + } else if os.IsNotExist(err) { + return nil + } + + return err }) } diff --git a/vendor/github.com/docker/distribution/health/doc.go b/vendor/github.com/docker/distribution/health/doc.go index 8c106b42b..877f4daca 100644 --- a/vendor/github.com/docker/distribution/health/doc.go +++ b/vendor/github.com/docker/distribution/health/doc.go @@ -24,7 +24,7 @@ // "manual" checks that allow the service to quickly be brought in/out of // rotation. // -// import _ "github.com/docker/distribution/registry/health/api" +// import _ "github.com/docker/distribution/health/api" // // # curl localhost:5001/debug/health // {} @@ -122,6 +122,12 @@ // # curl localhost:5001/debug/health // {"fileChecker":"file exists"} // +// FileChecker only accepts absolute or relative file path. It does not work +// properly with tilde(~). You should make sure that the application has +// proper permission(read and execute permission for directory along with +// the specified file path). Otherwise, the FileChecker will report error +// and file health check is not ok. +// // You could also test the connectivity to a downstream service by using a // "HTTPChecker", but ensure that you only mark the test unhealthy if there // are a minimum of two failures in a row: diff --git a/vendor/github.com/docker/distribution/health/health_test.go b/vendor/github.com/docker/distribution/health/health_test.go index 766fe159f..8d1a028b7 100644 --- a/vendor/github.com/docker/distribution/health/health_test.go +++ b/vendor/github.com/docker/distribution/health/health_test.go @@ -25,8 +25,8 @@ func TestReturns200IfThereAreNoChecks(t *testing.T) { } } -// TestReturns500IfThereAreErrorChecks ensures that the result code of the -// health endpoint is 500 if there are health checks with errors +// TestReturns503IfThereAreErrorChecks ensures that the result code of the +// health endpoint is 503 if there are health checks with errors. func TestReturns503IfThereAreErrorChecks(t *testing.T) { recorder := httptest.NewRecorder() diff --git a/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go b/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go index a2082ec02..3aa0662d9 100644 --- a/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go +++ b/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go @@ -6,8 +6,8 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" ) // MediaTypeManifestList specifies the mediaType for manifest lists. @@ -81,7 +81,7 @@ type ManifestList struct { Manifests []ManifestDescriptor `json:"manifests"` } -// References returnes the distribution descriptors for the referenced image +// References returns the distribution descriptors for the referenced image // manifests. func (m ManifestList) References() []distribution.Descriptor { dependencies := make([]distribution.Descriptor, len(m.Manifests)) diff --git a/vendor/github.com/docker/distribution/manifest/schema1/config_builder.go b/vendor/github.com/docker/distribution/manifest/schema1/config_builder.go index be0123731..9d222566c 100644 --- a/vendor/github.com/docker/distribution/manifest/schema1/config_builder.go +++ b/vendor/github.com/docker/distribution/manifest/schema1/config_builder.go @@ -9,10 +9,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type diffID digest.Digest @@ -240,8 +240,13 @@ func (mb *configManifestBuilder) emptyTar(ctx context.Context) (digest.Digest, e // AppendReference adds a reference to the current ManifestBuilder func (mb *configManifestBuilder) AppendReference(d distribution.Describable) error { - // todo: verification here? - mb.descriptors = append(mb.descriptors, d.Descriptor()) + descriptor := d.Descriptor() + + if err := descriptor.Digest.Validate(); err != nil { + return err + } + + mb.descriptors = append(mb.descriptors, descriptor) return nil } diff --git a/vendor/github.com/docker/distribution/manifest/schema1/config_builder_test.go b/vendor/github.com/docker/distribution/manifest/schema1/config_builder_test.go index 5f9abaa9f..399d8f315 100644 --- a/vendor/github.com/docker/distribution/manifest/schema1/config_builder_test.go +++ b/vendor/github.com/docker/distribution/manifest/schema1/config_builder_test.go @@ -9,9 +9,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type mockBlobService struct { @@ -197,10 +197,14 @@ func TestConfigBuilder(t *testing.T) { bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)} - ref, err := reference.ParseNamed("testrepo:testtag") + ref, err := reference.WithName("testrepo") if err != nil { t.Fatalf("could not parse reference: %v", err) } + ref, err = reference.WithTag(ref, "testtag") + if err != nil { + t.Fatalf("could not add tag: %v", err) + } builder := NewConfigManifestBuilder(bs, pk, ref, []byte(imgJSON)) diff --git a/vendor/github.com/docker/distribution/manifest/schema1/manifest.go b/vendor/github.com/docker/distribution/manifest/schema1/manifest.go index bff47bde0..65042a75f 100644 --- a/vendor/github.com/docker/distribution/manifest/schema1/manifest.go +++ b/vendor/github.com/docker/distribution/manifest/schema1/manifest.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) const ( diff --git a/vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go b/vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go index fc1045f9e..ae4014781 100644 --- a/vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go +++ b/vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go @@ -6,10 +6,10 @@ import ( "errors" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // referenceManifestBuilder is a type for constructing manifests from schema1 diff --git a/vendor/github.com/docker/distribution/manifest/schema1/reference_builder_test.go b/vendor/github.com/docker/distribution/manifest/schema1/reference_builder_test.go index 35db28e46..9eaa666c9 100644 --- a/vendor/github.com/docker/distribution/manifest/schema1/reference_builder_test.go +++ b/vendor/github.com/docker/distribution/manifest/schema1/reference_builder_test.go @@ -4,10 +4,10 @@ import ( "testing" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func makeSignedManifest(t *testing.T, pk libtrust.PrivateKey, refs []Reference) *SignedManifest { @@ -55,7 +55,7 @@ func TestReferenceBuilder(t *testing.T) { handCrafted := makeSignedManifest(t, pk, []Reference{r1, r2}) - ref, err := reference.ParseNamed(handCrafted.Manifest.Name) + ref, err := reference.WithName(handCrafted.Manifest.Name) if err != nil { t.Fatalf("could not parse reference: %v", err) } diff --git a/vendor/github.com/docker/distribution/manifest/schema2/builder.go b/vendor/github.com/docker/distribution/manifest/schema2/builder.go index ec0bf858d..4b6ba5628 100644 --- a/vendor/github.com/docker/distribution/manifest/schema2/builder.go +++ b/vendor/github.com/docker/distribution/manifest/schema2/builder.go @@ -3,7 +3,7 @@ package schema2 import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // builder is a type for constructing manifests. @@ -11,21 +11,25 @@ type builder struct { // bs is a BlobService used to publish the configuration blob. bs distribution.BlobService + // configMediaType is media type used to describe configuration + configMediaType string + // configJSON references configJSON []byte - // layers is a list of layer descriptors that gets built by successive - // calls to AppendReference. - layers []distribution.Descriptor + // dependencies is a list of descriptors that gets built by successive + // calls to AppendReference. In case of image configuration these are layers. + dependencies []distribution.Descriptor } // NewManifestBuilder is used to build new manifests for the current schema // version. It takes a BlobService so it can publish the configuration blob // as part of the Build process. -func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribution.ManifestBuilder { +func NewManifestBuilder(bs distribution.BlobService, configMediaType string, configJSON []byte) distribution.ManifestBuilder { mb := &builder{ - bs: bs, - configJSON: make([]byte, len(configJSON)), + bs: bs, + configMediaType: configMediaType, + configJSON: make([]byte, len(configJSON)), } copy(mb.configJSON, configJSON) @@ -36,9 +40,9 @@ func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribu func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { m := Manifest{ Versioned: SchemaVersion, - Layers: make([]distribution.Descriptor, len(mb.layers)), + Layers: make([]distribution.Descriptor, len(mb.dependencies)), } - copy(m.Layers, mb.layers) + copy(m.Layers, mb.dependencies) configDigest := digest.FromBytes(mb.configJSON) @@ -48,7 +52,7 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { case nil: // Override MediaType, since Put always replaces the specified media // type with application/octet-stream in the descriptor it returns. - m.Config.MediaType = MediaTypeConfig + m.Config.MediaType = mb.configMediaType return FromStruct(m) case distribution.ErrBlobUnknown: // nop @@ -57,10 +61,10 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { } // Add config to the blob store - m.Config, err = mb.bs.Put(ctx, MediaTypeConfig, mb.configJSON) + m.Config, err = mb.bs.Put(ctx, mb.configMediaType, mb.configJSON) // Override MediaType, since Put always replaces the specified media // type with application/octet-stream in the descriptor it returns. - m.Config.MediaType = MediaTypeConfig + m.Config.MediaType = mb.configMediaType if err != nil { return nil, err } @@ -70,11 +74,11 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { // AppendReference adds a reference to the current ManifestBuilder. func (mb *builder) AppendReference(d distribution.Describable) error { - mb.layers = append(mb.layers, d.Descriptor()) + mb.dependencies = append(mb.dependencies, d.Descriptor()) return nil } // References returns the current references added to this builder. func (mb *builder) References() []distribution.Descriptor { - return mb.layers + return mb.dependencies } diff --git a/vendor/github.com/docker/distribution/manifest/schema2/builder_test.go b/vendor/github.com/docker/distribution/manifest/schema2/builder_test.go index 851f917cb..697c1bc92 100644 --- a/vendor/github.com/docker/distribution/manifest/schema2/builder_test.go +++ b/vendor/github.com/docker/distribution/manifest/schema2/builder_test.go @@ -6,7 +6,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) type mockBlobService struct { @@ -166,7 +166,7 @@ func TestBuilder(t *testing.T) { } bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)} - builder := NewManifestBuilder(bs, imgJSON) + builder := NewManifestBuilder(bs, MediaTypeImageConfig, imgJSON) for _, d := range descriptors { if err := builder.AppendReference(d); err != nil { @@ -195,7 +195,7 @@ func TestBuilder(t *testing.T) { if target.Digest != configDigest { t.Fatalf("unexpected digest in target: %s", target.Digest.String()) } - if target.MediaType != MediaTypeConfig { + if target.MediaType != MediaTypeImageConfig { t.Fatalf("unexpected media type in target: %s", target.MediaType) } if target.Size != 3153 { diff --git a/vendor/github.com/docker/distribution/manifest/schema2/manifest.go b/vendor/github.com/docker/distribution/manifest/schema2/manifest.go index 741998d04..a2708c750 100644 --- a/vendor/github.com/docker/distribution/manifest/schema2/manifest.go +++ b/vendor/github.com/docker/distribution/manifest/schema2/manifest.go @@ -6,16 +6,16 @@ import ( "fmt" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" ) const ( // MediaTypeManifest specifies the mediaType for the current version. MediaTypeManifest = "application/vnd.docker.distribution.manifest.v2+json" - // MediaTypeConfig specifies the mediaType for the image configuration. - MediaTypeConfig = "application/vnd.docker.container.image.v1+json" + // MediaTypeImageConfig specifies the mediaType for the image configuration. + MediaTypeImageConfig = "application/vnd.docker.container.image.v1+json" // MediaTypePluginConfig specifies the mediaType for plugin configuration. MediaTypePluginConfig = "application/vnd.docker.plugin.v1+json" @@ -27,6 +27,10 @@ const ( // MediaTypeForeignLayer is the mediaType used for layers that must be // downloaded from foreign URLs. MediaTypeForeignLayer = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" + + // MediaTypeUncompressedLayer is the mediaType used for layers which + // are not compressed. + MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar" ) var ( diff --git a/vendor/github.com/docker/distribution/manifest/schema2/manifest_test.go b/vendor/github.com/docker/distribution/manifest/schema2/manifest_test.go index f0003d18b..86226606f 100644 --- a/vendor/github.com/docker/distribution/manifest/schema2/manifest_test.go +++ b/vendor/github.com/docker/distribution/manifest/schema2/manifest_test.go @@ -32,7 +32,7 @@ func TestManifest(t *testing.T) { Config: distribution.Descriptor{ Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b", Size: 985, - MediaType: MediaTypeConfig, + MediaType: MediaTypeImageConfig, }, Layers: []distribution.Descriptor{ { @@ -82,7 +82,7 @@ func TestManifest(t *testing.T) { if target.Digest != "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b" { t.Fatalf("unexpected digest in target: %s", target.Digest.String()) } - if target.MediaType != MediaTypeConfig { + if target.MediaType != MediaTypeImageConfig { t.Fatalf("unexpected media type in target: %s", target.MediaType) } if target.Size != 985 { diff --git a/vendor/github.com/docker/distribution/manifests.go b/vendor/github.com/docker/distribution/manifests.go index c4fb63450..2c99f25d3 100644 --- a/vendor/github.com/docker/distribution/manifests.go +++ b/vendor/github.com/docker/distribution/manifests.go @@ -5,7 +5,7 @@ import ( "mime" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // Manifest represents a registry object specifying a set of @@ -22,8 +22,8 @@ type Manifest interface { References() []Descriptor // Payload provides the serialized format of the manifest, in addition to - // the mediatype. - Payload() (mediatype string, payload []byte, err error) + // the media type. + Payload() (mediaType string, payload []byte, err error) } // ManifestBuilder creates a manifest allowing one to include dependencies. @@ -94,20 +94,20 @@ var mappings = make(map[string]UnmarshalFunc, 0) func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) { // Need to look up by the actual media type, not the raw contents of // the header. Strip semicolons and anything following them. - var mediatype string + var mediaType string if ctHeader != "" { var err error - mediatype, _, err = mime.ParseMediaType(ctHeader) + mediaType, _, err = mime.ParseMediaType(ctHeader) if err != nil { return nil, Descriptor{}, err } } - unmarshalFunc, ok := mappings[mediatype] + unmarshalFunc, ok := mappings[mediaType] if !ok { unmarshalFunc, ok = mappings[""] if !ok { - return nil, Descriptor{}, fmt.Errorf("unsupported manifest mediatype and no default available: %s", mediatype) + return nil, Descriptor{}, fmt.Errorf("unsupported manifest media type and no default available: %s", mediaType) } } @@ -116,10 +116,10 @@ func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) // RegisterManifestSchema registers an UnmarshalFunc for a given schema type. This // should be called from specific -func RegisterManifestSchema(mediatype string, u UnmarshalFunc) error { - if _, ok := mappings[mediatype]; ok { - return fmt.Errorf("manifest mediatype registration would overwrite existing: %s", mediatype) +func RegisterManifestSchema(mediaType string, u UnmarshalFunc) error { + if _, ok := mappings[mediaType]; ok { + return fmt.Errorf("manifest media type registration would overwrite existing: %s", mediaType) } - mappings[mediatype] = u + mappings[mediaType] = u return nil } diff --git a/vendor/github.com/docker/distribution/notifications/bridge.go b/vendor/github.com/docker/distribution/notifications/bridge.go index 502288a40..8f6386d3c 100644 --- a/vendor/github.com/docker/distribution/notifications/bridge.go +++ b/vendor/github.com/docker/distribution/notifications/bridge.go @@ -6,9 +6,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/uuid" + "github.com/opencontainers/go-digest" ) type bridge struct { diff --git a/vendor/github.com/docker/distribution/notifications/bridge_test.go b/vendor/github.com/docker/distribution/notifications/bridge_test.go index 0f85791c8..863509936 100644 --- a/vendor/github.com/docker/distribution/notifications/bridge_test.go +++ b/vendor/github.com/docker/distribution/notifications/bridge_test.go @@ -4,12 +4,12 @@ import ( "testing" "github.com/docker/distribution" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) var ( @@ -43,7 +43,7 @@ func TestEventBridgeManifestPulled(t *testing.T) { return nil })) - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) if err := l.ManifestPulled(repoRef, sm); err != nil { t.Fatalf("unexpected error notifying manifest pull: %v", err) } @@ -56,7 +56,7 @@ func TestEventBridgeManifestPushed(t *testing.T) { return nil })) - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) if err := l.ManifestPushed(repoRef, sm); err != nil { t.Fatalf("unexpected error notifying manifest pull: %v", err) } @@ -72,7 +72,7 @@ func TestEventBridgeManifestPushedWithTag(t *testing.T) { return nil })) - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) if err := l.ManifestPushed(repoRef, sm, distribution.WithTag(m.Tag)); err != nil { t.Fatalf("unexpected error notifying manifest pull: %v", err) } @@ -88,7 +88,7 @@ func TestEventBridgeManifestPulledWithTag(t *testing.T) { return nil })) - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) if err := l.ManifestPulled(repoRef, sm, distribution.WithTag(m.Tag)); err != nil { t.Fatalf("unexpected error notifying manifest pull: %v", err) } @@ -100,7 +100,7 @@ func TestEventBridgeManifestDeleted(t *testing.T) { return nil })) - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) if err := l.ManifestDeleted(repoRef, dgst); err != nil { t.Fatalf("unexpected error notifying manifest pull: %v", err) } @@ -160,7 +160,7 @@ func checkCommonManifest(t *testing.T, action string, events ...Event) { t.Fatalf("unexpected event action: %q != %q", event.Action, action) } - repoRef, _ := reference.ParseNamed(repo) + repoRef, _ := reference.WithName(repo) ref, _ := reference.WithDigest(repoRef, dgst) u, err := ub.BuildManifestURL(ref) if err != nil { diff --git a/vendor/github.com/docker/distribution/notifications/endpoint.go b/vendor/github.com/docker/distribution/notifications/endpoint.go index 29a9e27b5..44d0f6d7b 100644 --- a/vendor/github.com/docker/distribution/notifications/endpoint.go +++ b/vendor/github.com/docker/distribution/notifications/endpoint.go @@ -13,7 +13,7 @@ type EndpointConfig struct { Threshold int Backoff time.Duration IgnoredMediaTypes []string - Transport *http.Transport + Transport *http.Transport `json:"-"` } // defaults set any zero-valued fields to a reasonable default. diff --git a/vendor/github.com/docker/distribution/notifications/event.go b/vendor/github.com/docker/distribution/notifications/event.go index b59a72bed..9651cd1b1 100644 --- a/vendor/github.com/docker/distribution/notifications/event.go +++ b/vendor/github.com/docker/distribution/notifications/event.go @@ -77,7 +77,7 @@ type Event struct { Request RequestRecord `json:"request,omitempty"` // Actor specifies the agent that initiated the event. For most - // situations, this could be from the authorizaton context of the request. + // situations, this could be from the authorization context of the request. Actor ActorRecord `json:"actor,omitempty"` // Source identifies the registry node that generated the event. Put @@ -87,7 +87,7 @@ type Event struct { } // ActorRecord specifies the agent that initiated the event. For most -// situations, this could be from the authorizaton context of the request. +// situations, this could be from the authorization context of the request. // Data in this record can refer to both the initiating client and the // generating request. type ActorRecord struct { diff --git a/vendor/github.com/docker/distribution/notifications/http_test.go b/vendor/github.com/docker/distribution/notifications/http_test.go index e04693621..de47f789e 100644 --- a/vendor/github.com/docker/distribution/notifications/http_test.go +++ b/vendor/github.com/docker/distribution/notifications/http_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "mime" + "net" "net/http" "net/http/httptest" "reflect" @@ -94,6 +95,21 @@ func TestHTTPSink(t *testing.T) { var expectedMetrics EndpointMetrics expectedMetrics.Statuses = make(map[string]int) + closeL, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("unexpected error creating listener: %v", err) + } + defer closeL.Close() + go func() { + for { + c, err := closeL.Accept() + if err != nil { + return + } + c.Close() + } + }() + for _, tc := range []struct { events []Event // events to send url string @@ -121,8 +137,8 @@ func TestHTTPSink(t *testing.T) { failure: true, }, { - // Case where connection never goes through. - url: "http://shoudlntresolve/", + // Case where connection is immediately closed + url: closeL.Addr().String(), failure: true, }, } { diff --git a/vendor/github.com/docker/distribution/notifications/listener.go b/vendor/github.com/docker/distribution/notifications/listener.go index c968b98ad..25b5a800f 100644 --- a/vendor/github.com/docker/distribution/notifications/listener.go +++ b/vendor/github.com/docker/distribution/notifications/listener.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" + "github.com/opencontainers/go-digest" ) // ManifestListener describes a set of methods for listening to events related to manifests. diff --git a/vendor/github.com/docker/distribution/notifications/listener_test.go b/vendor/github.com/docker/distribution/notifications/listener_test.go index c7db5944e..a58498078 100644 --- a/vendor/github.com/docker/distribution/notifications/listener_test.go +++ b/vendor/github.com/docker/distribution/notifications/listener_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -16,6 +15,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func TestListener(t *testing.T) { @@ -33,7 +33,7 @@ func TestListener(t *testing.T) { ops: make(map[string]int), } - repoRef, _ := reference.ParseNamed("foo/bar") + repoRef, _ := reference.WithName("foo/bar") repository, err := registry.Repository(ctx, repoRef) if err != nil { t.Fatalf("unexpected error getting repo: %v", err) diff --git a/vendor/github.com/docker/distribution/notifications/metrics_test.go b/vendor/github.com/docker/distribution/notifications/metrics_test.go new file mode 100644 index 000000000..03a08e2c8 --- /dev/null +++ b/vendor/github.com/docker/distribution/notifications/metrics_test.go @@ -0,0 +1,28 @@ +package notifications + +import ( + "encoding/json" + "expvar" + "testing" +) + +func TestMetricsExpvar(t *testing.T) { + endpointsVar := expvar.Get("registry").(*expvar.Map).Get("notifications").(*expvar.Map).Get("endpoints") + + var v interface{} + if err := json.Unmarshal([]byte(endpointsVar.String()), &v); err != nil { + t.Fatalf("unexpected error unmarshaling endpoints: %v", err) + } + if v != nil { + t.Fatalf("expected nil, got %#v", v) + } + + NewEndpoint("x", "y", EndpointConfig{}) + + if err := json.Unmarshal([]byte(endpointsVar.String()), &v); err != nil { + t.Fatalf("unexpected error unmarshaling endpoints: %v", err) + } + if slice, ok := v.([]interface{}); !ok || len(slice) != 1 { + t.Logf("expected one-element []interface{}, got %#v", v) + } +} diff --git a/vendor/github.com/docker/distribution/notifications/sinks.go b/vendor/github.com/docker/distribution/notifications/sinks.go index 549ba97e2..beb8bad46 100644 --- a/vendor/github.com/docker/distribution/notifications/sinks.go +++ b/vendor/github.com/docker/distribution/notifications/sinks.go @@ -151,7 +151,7 @@ func (eq *eventQueue) Write(events ...Event) error { return nil } -// Close shutsdown the event queue, flushing +// Close shuts down the event queue, flushing func (eq *eventQueue) Close() error { eq.mu.Lock() defer eq.mu.Unlock() diff --git a/vendor/github.com/docker/distribution/reference/helpers.go b/vendor/github.com/docker/distribution/reference/helpers.go new file mode 100644 index 000000000..978df7eab --- /dev/null +++ b/vendor/github.com/docker/distribution/reference/helpers.go @@ -0,0 +1,42 @@ +package reference + +import "path" + +// IsNameOnly returns true if reference only contains a repo name. +func IsNameOnly(ref Named) bool { + if _, ok := ref.(NamedTagged); ok { + return false + } + if _, ok := ref.(Canonical); ok { + return false + } + return true +} + +// FamiliarName returns the familiar name string +// for the given named, familiarizing if needed. +func FamiliarName(ref Named) string { + if nn, ok := ref.(normalizedNamed); ok { + return nn.Familiar().Name() + } + return ref.Name() +} + +// FamiliarString returns the familiar string representation +// for the given reference, familiarizing if needed. +func FamiliarString(ref Reference) string { + if nn, ok := ref.(normalizedNamed); ok { + return nn.Familiar().String() + } + return ref.String() +} + +// FamiliarMatch reports whether ref matches the specified pattern. +// See https://godoc.org/path#Match for supported patterns. +func FamiliarMatch(pattern string, ref Reference) (bool, error) { + matched, err := path.Match(pattern, FamiliarString(ref)) + if namedRef, isNamed := ref.(Named); isNamed && !matched { + matched, _ = path.Match(pattern, FamiliarName(namedRef)) + } + return matched, err +} diff --git a/vendor/github.com/docker/distribution/reference/normalize.go b/vendor/github.com/docker/distribution/reference/normalize.go new file mode 100644 index 000000000..2d71fc5e9 --- /dev/null +++ b/vendor/github.com/docker/distribution/reference/normalize.go @@ -0,0 +1,170 @@ +package reference + +import ( + "errors" + "fmt" + "strings" + + "github.com/docker/distribution/digestset" + "github.com/opencontainers/go-digest" +) + +var ( + legacyDefaultDomain = "index.docker.io" + defaultDomain = "docker.io" + officialRepoName = "library" + defaultTag = "latest" +) + +// normalizedNamed represents a name which has been +// normalized and has a familiar form. A familiar name +// is what is used in Docker UI. An example normalized +// name is "docker.io/library/ubuntu" and corresponding +// familiar name of "ubuntu". +type normalizedNamed interface { + Named + Familiar() Named +} + +// ParseNormalizedNamed parses a string into a named reference +// transforming a familiar name from Docker UI to a fully +// qualified reference. If the value may be an identifier +// use ParseAnyReference. +func ParseNormalizedNamed(s string) (Named, error) { + if ok := anchoredIdentifierRegexp.MatchString(s); ok { + return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s) + } + domain, remainder := splitDockerDomain(s) + var remoteName string + if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 { + remoteName = remainder[:tagSep] + } else { + remoteName = remainder + } + if strings.ToLower(remoteName) != remoteName { + return nil, errors.New("invalid reference format: repository name must be lowercase") + } + + ref, err := Parse(domain + "/" + remainder) + if err != nil { + return nil, err + } + named, isNamed := ref.(Named) + if !isNamed { + return nil, fmt.Errorf("reference %s has no name", ref.String()) + } + return named, nil +} + +// splitDockerDomain splits a repository name to domain and remotename string. +// If no valid domain is found, the default domain is used. Repository name +// needs to be already validated before. +func splitDockerDomain(name string) (domain, remainder string) { + i := strings.IndexRune(name, '/') + if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") { + domain, remainder = defaultDomain, name + } else { + domain, remainder = name[:i], name[i+1:] + } + if domain == legacyDefaultDomain { + domain = defaultDomain + } + if domain == defaultDomain && !strings.ContainsRune(remainder, '/') { + remainder = officialRepoName + "/" + remainder + } + return +} + +// familiarizeName returns a shortened version of the name familiar +// to to the Docker UI. Familiar names have the default domain +// "docker.io" and "library/" repository prefix removed. +// For example, "docker.io/library/redis" will have the familiar +// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp". +// Returns a familiarized named only reference. +func familiarizeName(named namedRepository) repository { + repo := repository{ + domain: named.Domain(), + path: named.Path(), + } + + if repo.domain == defaultDomain { + repo.domain = "" + // Handle official repositories which have the pattern "library/" + if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName { + repo.path = split[1] + } + } + return repo +} + +func (r reference) Familiar() Named { + return reference{ + namedRepository: familiarizeName(r.namedRepository), + tag: r.tag, + digest: r.digest, + } +} + +func (r repository) Familiar() Named { + return familiarizeName(r) +} + +func (t taggedReference) Familiar() Named { + return taggedReference{ + namedRepository: familiarizeName(t.namedRepository), + tag: t.tag, + } +} + +func (c canonicalReference) Familiar() Named { + return canonicalReference{ + namedRepository: familiarizeName(c.namedRepository), + digest: c.digest, + } +} + +// TagNameOnly adds the default tag "latest" to a reference if it only has +// a repo name. +func TagNameOnly(ref Named) Named { + if IsNameOnly(ref) { + namedTagged, err := WithTag(ref, defaultTag) + if err != nil { + // Default tag must be valid, to create a NamedTagged + // type with non-validated input the WithTag function + // should be used instead + panic(err) + } + return namedTagged + } + return ref +} + +// ParseAnyReference parses a reference string as a possible identifier, +// full digest, or familiar name. +func ParseAnyReference(ref string) (Reference, error) { + if ok := anchoredIdentifierRegexp.MatchString(ref); ok { + return digestReference("sha256:" + ref), nil + } + if dgst, err := digest.Parse(ref); err == nil { + return digestReference(dgst), nil + } + + return ParseNormalizedNamed(ref) +} + +// ParseAnyReferenceWithSet parses a reference string as a possible short +// identifier to be matched in a digest set, a full digest, or familiar name. +func ParseAnyReferenceWithSet(ref string, ds *digestset.Set) (Reference, error) { + if ok := anchoredShortIdentifierRegexp.MatchString(ref); ok { + dgst, err := ds.Lookup(ref) + if err == nil { + return digestReference(dgst), nil + } + } else { + if dgst, err := digest.Parse(ref); err == nil { + return digestReference(dgst), nil + } + } + + return ParseNormalizedNamed(ref) +} diff --git a/vendor/github.com/docker/distribution/reference/normalize_test.go b/vendor/github.com/docker/distribution/reference/normalize_test.go new file mode 100644 index 000000000..a881972ac --- /dev/null +++ b/vendor/github.com/docker/distribution/reference/normalize_test.go @@ -0,0 +1,625 @@ +package reference + +import ( + "strconv" + "testing" + + "github.com/docker/distribution/digestset" + "github.com/opencontainers/go-digest" +) + +func TestValidateReferenceName(t *testing.T) { + validRepoNames := []string{ + "docker/docker", + "library/debian", + "debian", + "docker.io/docker/docker", + "docker.io/library/debian", + "docker.io/debian", + "index.docker.io/docker/docker", + "index.docker.io/library/debian", + "index.docker.io/debian", + "127.0.0.1:5000/docker/docker", + "127.0.0.1:5000/library/debian", + "127.0.0.1:5000/debian", + "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", + + // This test case was moved from invalid to valid since it is valid input + // when specified with a hostname, it removes the ambiguity from about + // whether the value is an identifier or repository name + "docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", + } + invalidRepoNames := []string{ + "https://github.com/docker/docker", + "docker/Docker", + "-docker", + "-docker/docker", + "-docker.io/docker/docker", + "docker///docker", + "docker.io/docker/Docker", + "docker.io/docker///docker", + "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", + } + + for _, name := range invalidRepoNames { + _, err := ParseNormalizedNamed(name) + if err == nil { + t.Fatalf("Expected invalid repo name for %q", name) + } + } + + for _, name := range validRepoNames { + _, err := ParseNormalizedNamed(name) + if err != nil { + t.Fatalf("Error parsing repo name %s, got: %q", name, err) + } + } +} + +func TestValidateRemoteName(t *testing.T) { + validRepositoryNames := []string{ + // Sanity check. + "docker/docker", + + // Allow 64-character non-hexadecimal names (hexadecimal names are forbidden). + "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", + + // Allow embedded hyphens. + "docker-rules/docker", + + // Allow multiple hyphens as well. + "docker---rules/docker", + + //Username doc and image name docker being tested. + "doc/docker", + + // single character names are now allowed. + "d/docker", + "jess/t", + + // Consecutive underscores. + "dock__er/docker", + } + for _, repositoryName := range validRepositoryNames { + _, err := ParseNormalizedNamed(repositoryName) + if err != nil { + t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err) + } + } + + invalidRepositoryNames := []string{ + // Disallow capital letters. + "docker/Docker", + + // Only allow one slash. + "docker///docker", + + // Disallow 64-character hexadecimal. + "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", + + // Disallow leading and trailing hyphens in namespace. + "-docker/docker", + "docker-/docker", + "-docker-/docker", + + // Don't allow underscores everywhere (as opposed to hyphens). + "____/____", + + "_docker/_docker", + + // Disallow consecutive periods. + "dock..er/docker", + "dock_.er/docker", + "dock-.er/docker", + + // No repository. + "docker/", + + //namespace too long + "this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker", + } + for _, repositoryName := range invalidRepositoryNames { + if _, err := ParseNormalizedNamed(repositoryName); err == nil { + t.Errorf("Repository name should be invalid: %v", repositoryName) + } + } +} + +func TestParseRepositoryInfo(t *testing.T) { + type tcase struct { + RemoteName, FamiliarName, FullName, AmbiguousName, Domain string + } + + tcases := []tcase{ + { + RemoteName: "fooo/bar", + FamiliarName: "fooo/bar", + FullName: "docker.io/fooo/bar", + AmbiguousName: "index.docker.io/fooo/bar", + Domain: "docker.io", + }, + { + RemoteName: "library/ubuntu", + FamiliarName: "ubuntu", + FullName: "docker.io/library/ubuntu", + AmbiguousName: "library/ubuntu", + Domain: "docker.io", + }, + { + RemoteName: "nonlibrary/ubuntu", + FamiliarName: "nonlibrary/ubuntu", + FullName: "docker.io/nonlibrary/ubuntu", + AmbiguousName: "", + Domain: "docker.io", + }, + { + RemoteName: "other/library", + FamiliarName: "other/library", + FullName: "docker.io/other/library", + AmbiguousName: "", + Domain: "docker.io", + }, + { + RemoteName: "private/moonbase", + FamiliarName: "127.0.0.1:8000/private/moonbase", + FullName: "127.0.0.1:8000/private/moonbase", + AmbiguousName: "", + Domain: "127.0.0.1:8000", + }, + { + RemoteName: "privatebase", + FamiliarName: "127.0.0.1:8000/privatebase", + FullName: "127.0.0.1:8000/privatebase", + AmbiguousName: "", + Domain: "127.0.0.1:8000", + }, + { + RemoteName: "private/moonbase", + FamiliarName: "example.com/private/moonbase", + FullName: "example.com/private/moonbase", + AmbiguousName: "", + Domain: "example.com", + }, + { + RemoteName: "privatebase", + FamiliarName: "example.com/privatebase", + FullName: "example.com/privatebase", + AmbiguousName: "", + Domain: "example.com", + }, + { + RemoteName: "private/moonbase", + FamiliarName: "example.com:8000/private/moonbase", + FullName: "example.com:8000/private/moonbase", + AmbiguousName: "", + Domain: "example.com:8000", + }, + { + RemoteName: "privatebasee", + FamiliarName: "example.com:8000/privatebasee", + FullName: "example.com:8000/privatebasee", + AmbiguousName: "", + Domain: "example.com:8000", + }, + { + RemoteName: "library/ubuntu-12.04-base", + FamiliarName: "ubuntu-12.04-base", + FullName: "docker.io/library/ubuntu-12.04-base", + AmbiguousName: "index.docker.io/library/ubuntu-12.04-base", + Domain: "docker.io", + }, + { + RemoteName: "library/foo", + FamiliarName: "foo", + FullName: "docker.io/library/foo", + AmbiguousName: "docker.io/foo", + Domain: "docker.io", + }, + { + RemoteName: "library/foo/bar", + FamiliarName: "library/foo/bar", + FullName: "docker.io/library/foo/bar", + AmbiguousName: "", + Domain: "docker.io", + }, + { + RemoteName: "store/foo/bar", + FamiliarName: "store/foo/bar", + FullName: "docker.io/store/foo/bar", + AmbiguousName: "", + Domain: "docker.io", + }, + } + + for _, tcase := range tcases { + refStrings := []string{tcase.FamiliarName, tcase.FullName} + if tcase.AmbiguousName != "" { + refStrings = append(refStrings, tcase.AmbiguousName) + } + + var refs []Named + for _, r := range refStrings { + named, err := ParseNormalizedNamed(r) + if err != nil { + t.Fatal(err) + } + refs = append(refs, named) + } + + for _, r := range refs { + if expected, actual := tcase.FamiliarName, FamiliarName(r); expected != actual { + t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual) + } + if expected, actual := tcase.FullName, r.String(); expected != actual { + t.Fatalf("Invalid canonical reference for %q. Expected %q, got %q", r, expected, actual) + } + if expected, actual := tcase.Domain, Domain(r); expected != actual { + t.Fatalf("Invalid domain for %q. Expected %q, got %q", r, expected, actual) + } + if expected, actual := tcase.RemoteName, Path(r); expected != actual { + t.Fatalf("Invalid remoteName for %q. Expected %q, got %q", r, expected, actual) + } + + } + } +} + +func TestParseReferenceWithTagAndDigest(t *testing.T) { + shortRef := "busybox:latest@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa" + ref, err := ParseNormalizedNamed(shortRef) + if err != nil { + t.Fatal(err) + } + if expected, actual := "docker.io/library/"+shortRef, ref.String(); actual != expected { + t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual) + } + + if _, isTagged := ref.(NamedTagged); !isTagged { + t.Fatalf("Reference from %q should support tag", ref) + } + if _, isCanonical := ref.(Canonical); !isCanonical { + t.Fatalf("Reference from %q should support digest", ref) + } + if expected, actual := shortRef, FamiliarString(ref); actual != expected { + t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual) + } +} + +func TestInvalidReferenceComponents(t *testing.T) { + if _, err := ParseNormalizedNamed("-foo"); err == nil { + t.Fatal("Expected WithName to detect invalid name") + } + ref, err := ParseNormalizedNamed("busybox") + if err != nil { + t.Fatal(err) + } + if _, err := WithTag(ref, "-foo"); err == nil { + t.Fatal("Expected WithName to detect invalid tag") + } + if _, err := WithDigest(ref, digest.Digest("foo")); err == nil { + t.Fatal("Expected WithDigest to detect invalid digest") + } +} + +func equalReference(r1, r2 Reference) bool { + switch v1 := r1.(type) { + case digestReference: + if v2, ok := r2.(digestReference); ok { + return v1 == v2 + } + case repository: + if v2, ok := r2.(repository); ok { + return v1 == v2 + } + case taggedReference: + if v2, ok := r2.(taggedReference); ok { + return v1 == v2 + } + case canonicalReference: + if v2, ok := r2.(canonicalReference); ok { + return v1 == v2 + } + case reference: + if v2, ok := r2.(reference); ok { + return v1 == v2 + } + } + return false +} + +func TestParseAnyReference(t *testing.T) { + tcases := []struct { + Reference string + Equivalent string + Expected Reference + Digests []digest.Digest + }{ + { + Reference: "redis", + Equivalent: "docker.io/library/redis", + }, + { + Reference: "redis:latest", + Equivalent: "docker.io/library/redis:latest", + }, + { + Reference: "docker.io/library/redis:latest", + Equivalent: "docker.io/library/redis:latest", + }, + { + Reference: "redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "dmcgowan/myapp", + Equivalent: "docker.io/dmcgowan/myapp", + }, + { + Reference: "dmcgowan/myapp:latest", + Equivalent: "docker.io/dmcgowan/myapp:latest", + }, + { + Reference: "docker.io/mcgowan/myapp:latest", + Equivalent: "docker.io/mcgowan/myapp:latest", + }, + { + Reference: "dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Equivalent: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Equivalent: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + }, + { + Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9", + Equivalent: "docker.io/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9", + }, + { + Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9", + Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Digests: []digest.Digest{ + digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + }, + }, + { + Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9", + Equivalent: "docker.io/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9", + Digests: []digest.Digest{ + digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + }, + }, + { + Reference: "dbcc1c", + Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c", + Digests: []digest.Digest{ + digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + }, + }, + { + Reference: "dbcc1", + Equivalent: "docker.io/library/dbcc1", + Digests: []digest.Digest{ + digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + }, + }, + { + Reference: "dbcc1c", + Equivalent: "docker.io/library/dbcc1c", + Digests: []digest.Digest{ + digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"), + }, + }, + } + + for _, tcase := range tcases { + var ref Reference + var err error + if len(tcase.Digests) == 0 { + ref, err = ParseAnyReference(tcase.Reference) + } else { + ds := digestset.NewSet() + for _, dgst := range tcase.Digests { + if err := ds.Add(dgst); err != nil { + t.Fatalf("Error adding digest %s: %v", dgst.String(), err) + } + } + ref, err = ParseAnyReferenceWithSet(tcase.Reference, ds) + } + if err != nil { + t.Fatalf("Error parsing reference %s: %v", tcase.Reference, err) + } + if ref.String() != tcase.Equivalent { + t.Fatalf("Unexpected string: %s, expected %s", ref.String(), tcase.Equivalent) + } + + expected := tcase.Expected + if expected == nil { + expected, err = Parse(tcase.Equivalent) + if err != nil { + t.Fatalf("Error parsing reference %s: %v", tcase.Equivalent, err) + } + } + if !equalReference(ref, expected) { + t.Errorf("Unexpected reference %#v, expected %#v", ref, expected) + } + } +} + +func TestNormalizedSplitHostname(t *testing.T) { + testcases := []struct { + input string + domain string + name string + }{ + { + input: "test.com/foo", + domain: "test.com", + name: "foo", + }, + { + input: "test_com/foo", + domain: "docker.io", + name: "test_com/foo", + }, + { + input: "docker/migrator", + domain: "docker.io", + name: "docker/migrator", + }, + { + input: "test.com:8080/foo", + domain: "test.com:8080", + name: "foo", + }, + { + input: "test-com:8080/foo", + domain: "test-com:8080", + name: "foo", + }, + { + input: "foo", + domain: "docker.io", + name: "library/foo", + }, + { + input: "xn--n3h.com/foo", + domain: "xn--n3h.com", + name: "foo", + }, + { + input: "xn--n3h.com:18080/foo", + domain: "xn--n3h.com:18080", + name: "foo", + }, + { + input: "docker.io/foo", + domain: "docker.io", + name: "library/foo", + }, + { + input: "docker.io/library/foo", + domain: "docker.io", + name: "library/foo", + }, + { + input: "docker.io/library/foo/bar", + domain: "docker.io", + name: "library/foo/bar", + }, + } + for _, testcase := range testcases { + failf := func(format string, v ...interface{}) { + t.Logf(strconv.Quote(testcase.input)+": "+format, v...) + t.Fail() + } + + named, err := ParseNormalizedNamed(testcase.input) + if err != nil { + failf("error parsing name: %s", err) + } + domain, name := SplitHostname(named) + if domain != testcase.domain { + failf("unexpected domain: got %q, expected %q", domain, testcase.domain) + } + if name != testcase.name { + failf("unexpected name: got %q, expected %q", name, testcase.name) + } + } +} + +func TestMatchError(t *testing.T) { + named, err := ParseAnyReference("foo") + if err != nil { + t.Fatal(err) + } + _, err = FamiliarMatch("[-x]", named) + if err == nil { + t.Fatalf("expected an error, got nothing") + } +} + +func TestMatch(t *testing.T) { + matchCases := []struct { + reference string + pattern string + expected bool + }{ + { + reference: "foo", + pattern: "foo/**/ba[rz]", + expected: false, + }, + { + reference: "foo/any/bat", + pattern: "foo/**/ba[rz]", + expected: false, + }, + { + reference: "foo/a/bar", + pattern: "foo/**/ba[rz]", + expected: true, + }, + { + reference: "foo/b/baz", + pattern: "foo/**/ba[rz]", + expected: true, + }, + { + reference: "foo/c/baz:tag", + pattern: "foo/**/ba[rz]", + expected: true, + }, + { + reference: "foo/c/baz:tag", + pattern: "foo/*/baz:tag", + expected: true, + }, + { + reference: "foo/c/baz:tag", + pattern: "foo/c/baz:tag", + expected: true, + }, + { + reference: "example.com/foo/c/baz:tag", + pattern: "*/foo/c/baz", + expected: true, + }, + { + reference: "example.com/foo/c/baz:tag", + pattern: "example.com/foo/c/baz", + expected: true, + }, + } + for _, c := range matchCases { + named, err := ParseAnyReference(c.reference) + if err != nil { + t.Fatal(err) + } + actual, err := FamiliarMatch(c.pattern, named) + if err != nil { + t.Fatal(err) + } + if actual != c.expected { + t.Fatalf("expected %s match %s to be %v, was %v", c.reference, c.pattern, c.expected, actual) + } + } +} diff --git a/vendor/github.com/docker/distribution/reference/reference.go b/vendor/github.com/docker/distribution/reference/reference.go index 02786628e..2f66cca87 100644 --- a/vendor/github.com/docker/distribution/reference/reference.go +++ b/vendor/github.com/docker/distribution/reference/reference.go @@ -4,30 +4,32 @@ // Grammar // // reference := name [ ":" tag ] [ "@" digest ] -// name := [hostname '/'] component ['/' component]* -// hostname := hostcomponent ['.' hostcomponent]* [':' port-number] -// hostcomponent := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/ +// name := [domain '/'] path-component ['/' path-component]* +// domain := domain-component ['.' domain-component]* [':' port-number] +// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/ // port-number := /[0-9]+/ -// component := alpha-numeric [separator alpha-numeric]* +// path-component := alpha-numeric [separator alpha-numeric]* // alpha-numeric := /[a-z0-9]+/ // separator := /[_.]|__|[-]*/ // // tag := /[\w][\w.-]{0,127}/ // // digest := digest-algorithm ":" digest-hex -// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ] +// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]* // digest-algorithm-separator := /[+.-_]/ // digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/ // digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value +// +// identifier := /[a-f0-9]{64}/ +// short-identifier := /[a-f0-9]{6,64}/ package reference import ( "errors" "fmt" - "path" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) const ( @@ -53,6 +55,9 @@ var ( // ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax. ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax) + + // ErrNameNotCanonical is returned when a name is not canonical. + ErrNameNotCanonical = errors.New("repository name must be canonical") ) // Reference is an opaque object reference identifier that may include @@ -126,23 +131,56 @@ type Digested interface { } // Canonical reference is an object with a fully unique -// name including a name with hostname and digest +// name including a name with domain and digest type Canonical interface { Named Digest() digest.Digest } +// namedRepository is a reference to a repository with a name. +// A namedRepository has both domain and path components. +type namedRepository interface { + Named + Domain() string + Path() string +} + +// Domain returns the domain part of the Named reference +func Domain(named Named) string { + if r, ok := named.(namedRepository); ok { + return r.Domain() + } + domain, _ := splitDomain(named.Name()) + return domain +} + +// Path returns the name without the domain part of the Named reference +func Path(named Named) (name string) { + if r, ok := named.(namedRepository); ok { + return r.Path() + } + _, path := splitDomain(named.Name()) + return path +} + +func splitDomain(name string) (string, string) { + match := anchoredNameRegexp.FindStringSubmatch(name) + if len(match) != 3 { + return "", name + } + return match[1], match[2] +} + // SplitHostname splits a named reference into a // hostname and name string. If no valid hostname is // found, the hostname is empty and the full value // is returned as name +// DEPRECATED: Use Domain or Path func SplitHostname(named Named) (string, string) { - name := named.Name() - match := anchoredNameRegexp.FindStringSubmatch(name) - if len(match) != 3 { - return "", name + if r, ok := named.(namedRepository); ok { + return r.Domain(), r.Path() } - return match[1], match[2] + return splitDomain(named.Name()) } // Parse parses s and returns a syntactically valid Reference. @@ -164,13 +202,24 @@ func Parse(s string) (Reference, error) { return nil, ErrNameTooLong } + var repo repository + + nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1]) + if nameMatch != nil && len(nameMatch) == 3 { + repo.domain = nameMatch[1] + repo.path = nameMatch[2] + } else { + repo.domain = "" + repo.path = matches[1] + } + ref := reference{ - name: matches[1], - tag: matches[2], + namedRepository: repo, + tag: matches[2], } if matches[3] != "" { var err error - ref.digest, err = digest.ParseDigest(matches[3]) + ref.digest, err = digest.Parse(matches[3]) if err != nil { return nil, err } @@ -185,18 +234,17 @@ func Parse(s string) (Reference, error) { } // ParseNamed parses s and returns a syntactically valid reference implementing -// the Named interface. The reference must have a name, otherwise an error is -// returned. +// the Named interface. The reference must have a name and be in the canonical +// form, otherwise an error is returned. // If an error was encountered it is returned, along with a nil Reference. // NOTE: ParseNamed will not handle short digests. func ParseNamed(s string) (Named, error) { - ref, err := Parse(s) + named, err := ParseNormalizedNamed(s) if err != nil { return nil, err } - named, isNamed := ref.(Named) - if !isNamed { - return nil, fmt.Errorf("reference %s has no name", ref.String()) + if named.String() != s { + return nil, ErrNameNotCanonical } return named, nil } @@ -207,10 +255,15 @@ func WithName(name string) (Named, error) { if len(name) > NameTotalLengthMax { return nil, ErrNameTooLong } - if !anchoredNameRegexp.MatchString(name) { + + match := anchoredNameRegexp.FindStringSubmatch(name) + if match == nil || len(match) != 3 { return nil, ErrReferenceInvalidFormat } - return repository(name), nil + return repository{ + domain: match[1], + path: match[2], + }, nil } // WithTag combines the name from "name" and the tag from "tag" to form a @@ -219,16 +272,23 @@ func WithTag(name Named, tag string) (NamedTagged, error) { if !anchoredTagRegexp.MatchString(tag) { return nil, ErrTagInvalidFormat } + var repo repository + if r, ok := name.(namedRepository); ok { + repo.domain = r.Domain() + repo.path = r.Path() + } else { + repo.path = name.Name() + } if canonical, ok := name.(Canonical); ok { return reference{ - name: name.Name(), - tag: tag, - digest: canonical.Digest(), + namedRepository: repo, + tag: tag, + digest: canonical.Digest(), }, nil } return taggedReference{ - name: name.Name(), - tag: tag, + namedRepository: repo, + tag: tag, }, nil } @@ -238,36 +298,37 @@ func WithDigest(name Named, digest digest.Digest) (Canonical, error) { if !anchoredDigestRegexp.MatchString(digest.String()) { return nil, ErrDigestInvalidFormat } + var repo repository + if r, ok := name.(namedRepository); ok { + repo.domain = r.Domain() + repo.path = r.Path() + } else { + repo.path = name.Name() + } if tagged, ok := name.(Tagged); ok { return reference{ - name: name.Name(), - tag: tagged.Tag(), - digest: digest, + namedRepository: repo, + tag: tagged.Tag(), + digest: digest, }, nil } return canonicalReference{ - name: name.Name(), - digest: digest, + namedRepository: repo, + digest: digest, }, nil } -// Match reports whether ref matches the specified pattern. -// See https://godoc.org/path#Match for supported patterns. -func Match(pattern string, ref Reference) (bool, error) { - matched, err := path.Match(pattern, ref.String()) - if namedRef, isNamed := ref.(Named); isNamed && !matched { - matched, _ = path.Match(pattern, namedRef.Name()) - } - return matched, err -} - // TrimNamed removes any tag or digest from the named reference. func TrimNamed(ref Named) Named { - return repository(ref.Name()) + domain, path := SplitHostname(ref) + return repository{ + domain: domain, + path: path, + } } func getBestReferenceType(ref reference) Reference { - if ref.name == "" { + if ref.Name() == "" { // Allow digest only references if ref.digest != "" { return digestReference(ref.digest) @@ -277,16 +338,16 @@ func getBestReferenceType(ref reference) Reference { if ref.tag == "" { if ref.digest != "" { return canonicalReference{ - name: ref.name, - digest: ref.digest, + namedRepository: ref.namedRepository, + digest: ref.digest, } } - return repository(ref.name) + return ref.namedRepository } if ref.digest == "" { return taggedReference{ - name: ref.name, - tag: ref.tag, + namedRepository: ref.namedRepository, + tag: ref.tag, } } @@ -294,17 +355,13 @@ func getBestReferenceType(ref reference) Reference { } type reference struct { - name string + namedRepository tag string digest digest.Digest } func (r reference) String() string { - return r.name + ":" + r.tag + "@" + r.digest.String() -} - -func (r reference) Name() string { - return r.name + return r.Name() + ":" + r.tag + "@" + r.digest.String() } func (r reference) Tag() string { @@ -315,20 +372,34 @@ func (r reference) Digest() digest.Digest { return r.digest } -type repository string +type repository struct { + domain string + path string +} func (r repository) String() string { - return string(r) + return r.Name() } func (r repository) Name() string { - return string(r) + if r.domain == "" { + return r.path + } + return r.domain + "/" + r.path +} + +func (r repository) Domain() string { + return r.domain +} + +func (r repository) Path() string { + return r.path } type digestReference digest.Digest func (d digestReference) String() string { - return d.String() + return digest.Digest(d).String() } func (d digestReference) Digest() digest.Digest { @@ -336,16 +407,12 @@ func (d digestReference) Digest() digest.Digest { } type taggedReference struct { - name string - tag string + namedRepository + tag string } func (t taggedReference) String() string { - return t.name + ":" + t.tag -} - -func (t taggedReference) Name() string { - return t.name + return t.Name() + ":" + t.tag } func (t taggedReference) Tag() string { @@ -353,16 +420,12 @@ func (t taggedReference) Tag() string { } type canonicalReference struct { - name string + namedRepository digest digest.Digest } func (c canonicalReference) String() string { - return c.name + "@" + c.digest.String() -} - -func (c canonicalReference) Name() string { - return c.name + return c.Name() + "@" + c.digest.String() } func (c canonicalReference) Digest() digest.Digest { diff --git a/vendor/github.com/docker/distribution/reference/reference_test.go b/vendor/github.com/docker/distribution/reference/reference_test.go index 405c47c05..16b871f98 100644 --- a/vendor/github.com/docker/distribution/reference/reference_test.go +++ b/vendor/github.com/docker/distribution/reference/reference_test.go @@ -1,12 +1,14 @@ package reference import ( + _ "crypto/sha256" + _ "crypto/sha512" "encoding/json" "strconv" "strings" "testing" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) func TestReferenceParse(t *testing.T) { @@ -19,8 +21,8 @@ func TestReferenceParse(t *testing.T) { err error // repository is the string representation for the reference repository string - // hostname is the hostname expected in the reference - hostname string + // domain is the domain expected in the reference + domain string // tag is the tag for the reference tag string // digest is the digest for the reference (enforces digest reference) @@ -42,37 +44,37 @@ func TestReferenceParse(t *testing.T) { }, { input: "test.com/repo:tag", - hostname: "test.com", + domain: "test.com", repository: "test.com/repo", tag: "tag", }, { input: "test:5000/repo", - hostname: "test:5000", + domain: "test:5000", repository: "test:5000/repo", }, { input: "test:5000/repo:tag", - hostname: "test:5000", + domain: "test:5000", repository: "test:5000/repo", tag: "tag", }, { input: "test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - hostname: "test:5000", + domain: "test:5000", repository: "test:5000/repo", digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", }, { input: "test:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - hostname: "test:5000", + domain: "test:5000", repository: "test:5000/repo", tag: "tag", digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", }, { input: "test:5000/repo", - hostname: "test:5000", + domain: "test:5000", repository: "test:5000/repo", }, { @@ -120,7 +122,7 @@ func TestReferenceParse(t *testing.T) { }, { input: strings.Repeat("a/", 127) + "a:tag-puts-this-over-max", - hostname: "a", + domain: "a", repository: strings.Repeat("a/", 127) + "a", tag: "tag-puts-this-over-max", }, @@ -130,30 +132,30 @@ func TestReferenceParse(t *testing.T) { }, { input: "sub-dom1.foo.com/bar/baz/quux", - hostname: "sub-dom1.foo.com", + domain: "sub-dom1.foo.com", repository: "sub-dom1.foo.com/bar/baz/quux", }, { input: "sub-dom1.foo.com/bar/baz/quux:some-long-tag", - hostname: "sub-dom1.foo.com", + domain: "sub-dom1.foo.com", repository: "sub-dom1.foo.com/bar/baz/quux", tag: "some-long-tag", }, { input: "b.gcr.io/test.example.com/my-app:test.example.com", - hostname: "b.gcr.io", + domain: "b.gcr.io", repository: "b.gcr.io/test.example.com/my-app", tag: "test.example.com", }, { input: "xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode - hostname: "xn--n3h.com", + domain: "xn--n3h.com", repository: "xn--n3h.com/myimage", tag: "xn--n3h.com", }, { input: "xn--7o8h.com/myimage:xn--7o8h.com@sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // 🐳.com in punycode - hostname: "xn--7o8h.com", + domain: "xn--7o8h.com", repository: "xn--7o8h.com/myimage", tag: "xn--7o8h.com", digest: "sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", @@ -165,7 +167,7 @@ func TestReferenceParse(t *testing.T) { }, { input: "foo/foo_bar.com:8080", - hostname: "foo", + domain: "foo", repository: "foo/foo_bar.com", tag: "8080", }, @@ -196,11 +198,11 @@ func TestReferenceParse(t *testing.T) { if named.Name() != testcase.repository { failf("unexpected repository: got %q, expected %q", named.Name(), testcase.repository) } - hostname, _ := SplitHostname(named) - if hostname != testcase.hostname { - failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname) + domain, _ := SplitHostname(named) + if domain != testcase.domain { + failf("unexpected domain: got %q, expected %q", domain, testcase.domain) } - } else if testcase.repository != "" || testcase.hostname != "" { + } else if testcase.repository != "" || testcase.domain != "" { failf("expected named type, got %T", repo) } @@ -280,39 +282,39 @@ func TestWithNameFailure(t *testing.T) { func TestSplitHostname(t *testing.T) { testcases := []struct { - input string - hostname string - name string + input string + domain string + name string }{ { - input: "test.com/foo", - hostname: "test.com", - name: "foo", + input: "test.com/foo", + domain: "test.com", + name: "foo", }, { - input: "test_com/foo", - hostname: "", - name: "test_com/foo", + input: "test_com/foo", + domain: "", + name: "test_com/foo", }, { - input: "test:8080/foo", - hostname: "test:8080", - name: "foo", + input: "test:8080/foo", + domain: "test:8080", + name: "foo", }, { - input: "test.com:8080/foo", - hostname: "test.com:8080", - name: "foo", + input: "test.com:8080/foo", + domain: "test.com:8080", + name: "foo", }, { - input: "test-com:8080/foo", - hostname: "test-com:8080", - name: "foo", + input: "test-com:8080/foo", + domain: "test-com:8080", + name: "foo", }, { - input: "xn--n3h.com:18080/foo", - hostname: "xn--n3h.com:18080", - name: "foo", + input: "xn--n3h.com:18080/foo", + domain: "xn--n3h.com:18080", + name: "foo", }, } for _, testcase := range testcases { @@ -325,9 +327,9 @@ func TestSplitHostname(t *testing.T) { if err != nil { failf("error parsing name: %s", err) } - hostname, name := SplitHostname(named) - if hostname != testcase.hostname { - failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname) + domain, name := SplitHostname(named) + if domain != testcase.domain { + failf("unexpected domain: got %q, expected %q", domain, testcase.domain) } if name != testcase.name { failf("unexpected name: got %q, expected %q", name, testcase.name) @@ -582,80 +584,76 @@ func TestWithDigest(t *testing.T) { } } -func TestMatchError(t *testing.T) { - named, err := Parse("foo") - if err != nil { - t.Fatal(err) - } - _, err = Match("[-x]", named) - if err == nil { - t.Fatalf("expected an error, got nothing") - } -} - -func TestMatch(t *testing.T) { - matchCases := []struct { - reference string - pattern string - expected bool +func TestParseNamed(t *testing.T) { + testcases := []struct { + input string + domain string + name string + err error }{ { - reference: "foo", - pattern: "foo/**/ba[rz]", - expected: false, + input: "test.com/foo", + domain: "test.com", + name: "foo", }, { - reference: "foo/any/bat", - pattern: "foo/**/ba[rz]", - expected: false, + input: "test:8080/foo", + domain: "test:8080", + name: "foo", }, { - reference: "foo/a/bar", - pattern: "foo/**/ba[rz]", - expected: true, + input: "test_com/foo", + err: ErrNameNotCanonical, }, { - reference: "foo/b/baz", - pattern: "foo/**/ba[rz]", - expected: true, + input: "test.com", + err: ErrNameNotCanonical, }, { - reference: "foo/c/baz:tag", - pattern: "foo/**/ba[rz]", - expected: true, + input: "foo", + err: ErrNameNotCanonical, }, { - reference: "foo/c/baz:tag", - pattern: "foo/*/baz:tag", - expected: true, + input: "library/foo", + err: ErrNameNotCanonical, }, { - reference: "foo/c/baz:tag", - pattern: "foo/c/baz:tag", - expected: true, + input: "docker.io/library/foo", + domain: "docker.io", + name: "library/foo", }, + // Ambiguous case, parser will add "library/" to foo { - reference: "example.com/foo/c/baz:tag", - pattern: "*/foo/c/baz", - expected: true, - }, - { - reference: "example.com/foo/c/baz:tag", - pattern: "example.com/foo/c/baz", - expected: true, + input: "docker.io/foo", + err: ErrNameNotCanonical, }, } - for _, c := range matchCases { - named, err := Parse(c.reference) - if err != nil { - t.Fatal(err) + for _, testcase := range testcases { + failf := func(format string, v ...interface{}) { + t.Logf(strconv.Quote(testcase.input)+": "+format, v...) + t.Fail() } - actual, err := Match(c.pattern, named) - if err != nil { - t.Fatal(err) + + named, err := ParseNamed(testcase.input) + if err != nil && testcase.err == nil { + failf("error parsing name: %s", err) + continue + } else if err == nil && testcase.err != nil { + failf("parsing succeded: expected error %v", testcase.err) + continue + } else if err != testcase.err { + failf("unexpected error %v, expected %v", err, testcase.err) + continue + } else if err != nil { + continue } - if actual != c.expected { - t.Fatalf("expected %s match %s to be %v, was %v", c.reference, c.pattern, c.expected, actual) + + domain, name := SplitHostname(named) + if domain != testcase.domain { + failf("unexpected domain: got %q, expected %q", domain, testcase.domain) + } + if name != testcase.name { + failf("unexpected name: got %q, expected %q", name, testcase.name) } } } diff --git a/vendor/github.com/docker/distribution/reference/regexp.go b/vendor/github.com/docker/distribution/reference/regexp.go index 9a7d366bc..786034932 100644 --- a/vendor/github.com/docker/distribution/reference/regexp.go +++ b/vendor/github.com/docker/distribution/reference/regexp.go @@ -19,18 +19,18 @@ var ( alphaNumericRegexp, optional(repeated(separatorRegexp, alphaNumericRegexp))) - // hostnameComponentRegexp restricts the registry hostname component of a - // repository name to start with a component as defined by hostnameRegexp + // domainComponentRegexp restricts the registry domain component of a + // repository name to start with a component as defined by DomainRegexp // and followed by an optional port. - hostnameComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`) + domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`) - // hostnameRegexp defines the structure of potential hostname components + // DomainRegexp defines the structure of potential domain components // that may be part of image names. This is purposely a subset of what is // allowed by DNS to ensure backwards compatibility with Docker image // names. - hostnameRegexp = expression( - hostnameComponentRegexp, - optional(repeated(literal(`.`), hostnameComponentRegexp)), + DomainRegexp = expression( + domainComponentRegexp, + optional(repeated(literal(`.`), domainComponentRegexp)), optional(literal(`:`), match(`[0-9]+`))) // TagRegexp matches valid tag names. From docker/docker:graph/tags.go. @@ -48,17 +48,17 @@ var ( anchoredDigestRegexp = anchored(DigestRegexp) // NameRegexp is the format for the name component of references. The - // regexp has capturing groups for the hostname and name part omitting + // regexp has capturing groups for the domain and name part omitting // the separating forward slash from either. NameRegexp = expression( - optional(hostnameRegexp, literal(`/`)), + optional(DomainRegexp, literal(`/`)), nameComponentRegexp, optional(repeated(literal(`/`), nameComponentRegexp))) // anchoredNameRegexp is used to parse a name value, capturing the - // hostname and trailing components. + // domain and trailing components. anchoredNameRegexp = anchored( - optional(capture(hostnameRegexp), literal(`/`)), + optional(capture(DomainRegexp), literal(`/`)), capture(nameComponentRegexp, optional(repeated(literal(`/`), nameComponentRegexp)))) @@ -68,6 +68,25 @@ var ( ReferenceRegexp = anchored(capture(NameRegexp), optional(literal(":"), capture(TagRegexp)), optional(literal("@"), capture(DigestRegexp))) + + // IdentifierRegexp is the format for string identifier used as a + // content addressable identifier using sha256. These identifiers + // are like digests without the algorithm, since sha256 is used. + IdentifierRegexp = match(`([a-f0-9]{64})`) + + // ShortIdentifierRegexp is the format used to represent a prefix + // of an identifier. A prefix may be used to match a sha256 identifier + // within a list of trusted identifiers. + ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`) + + // anchoredIdentifierRegexp is used to check or match an + // identifier value, anchored at start and end of string. + anchoredIdentifierRegexp = anchored(IdentifierRegexp) + + // anchoredShortIdentifierRegexp is used to check if a value + // is a possible identifier prefix, anchored at start and end + // of string. + anchoredShortIdentifierRegexp = anchored(ShortIdentifierRegexp) ) // match compiles the string to a regular expression. diff --git a/vendor/github.com/docker/distribution/reference/regexp_test.go b/vendor/github.com/docker/distribution/reference/regexp_test.go index 2ec39377a..09bc81927 100644 --- a/vendor/github.com/docker/distribution/reference/regexp_test.go +++ b/vendor/github.com/docker/distribution/reference/regexp_test.go @@ -33,7 +33,7 @@ func checkRegexp(t *testing.T, r *regexp.Regexp, m regexpMatch) { } } -func TestHostRegexp(t *testing.T) { +func TestDomainRegexp(t *testing.T) { hostcases := []regexpMatch{ { input: "test.com", @@ -116,7 +116,7 @@ func TestHostRegexp(t *testing.T) { match: true, }, } - r := regexp.MustCompile(`^` + hostnameRegexp.String() + `$`) + r := regexp.MustCompile(`^` + DomainRegexp.String() + `$`) for i := range hostcases { checkRegexp(t, r, hostcases[i]) } @@ -487,3 +487,67 @@ func TestReferenceRegexp(t *testing.T) { } } + +func TestIdentifierRegexp(t *testing.T) { + fullCases := []regexpMatch{ + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821", + match: true, + }, + { + input: "7EC43B381E5AEFE6E04EFB0B3F0693FF2A4A50652D64AEC573905F2DB5889A1C", + match: false, + }, + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf", + match: false, + }, + { + input: "sha256:da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821", + match: false, + }, + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf98218482", + match: false, + }, + } + + shortCases := []regexpMatch{ + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821", + match: true, + }, + { + input: "7EC43B381E5AEFE6E04EFB0B3F0693FF2A4A50652D64AEC573905F2DB5889A1C", + match: false, + }, + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf", + match: true, + }, + { + input: "sha256:da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821", + match: false, + }, + { + input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf98218482", + match: false, + }, + { + input: "da304", + match: false, + }, + { + input: "da304e", + match: true, + }, + } + + for i := range fullCases { + checkRegexp(t, anchoredIdentifierRegexp, fullCases[i]) + } + + for i := range shortCases { + checkRegexp(t, anchoredShortIdentifierRegexp, shortCases[i]) + } +} diff --git a/vendor/github.com/docker/distribution/registry.go b/vendor/github.com/docker/distribution/registry.go index 1ede31ebb..1da1d533f 100644 --- a/vendor/github.com/docker/distribution/registry.go +++ b/vendor/github.com/docker/distribution/registry.go @@ -35,7 +35,7 @@ type Namespace interface { // reference. Repository(ctx context.Context, name reference.Named) (Repository, error) - // Repositories fills 'repos' with a lexigraphically sorted catalog of repositories + // Repositories fills 'repos' with a lexicographically sorted catalog of repositories // up to the size of 'repos' and returns the value 'n' for the number of entries // which were filled. 'last' contains an offset in the catalog, and 'err' will be // set to io.EOF if there are no more entries to obtain. diff --git a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go b/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go index 9979abae6..a9616c58a 100644 --- a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go +++ b/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go @@ -4,9 +4,9 @@ import ( "net/http" "regexp" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" + "github.com/opencontainers/go-digest" ) var ( diff --git a/vendor/github.com/docker/distribution/registry/api/v2/urls.go b/vendor/github.com/docker/distribution/registry/api/v2/urls.go index 5e24ca9b5..1337bdb12 100644 --- a/vendor/github.com/docker/distribution/registry/api/v2/urls.go +++ b/vendor/github.com/docker/distribution/registry/api/v2/urls.go @@ -1,6 +1,7 @@ package v2 import ( + "fmt" "net/http" "net/url" "strings" @@ -149,6 +150,8 @@ func (ub *URLBuilder) BuildManifestURL(ref reference.Named) (string, error) { tagOrDigest = v.Tag() case reference.Digested: tagOrDigest = v.Digest().String() + default: + return "", fmt.Errorf("reference must have a tag or digest") } manifestURL, err := route.URL("name", ref.Name(), "reference", tagOrDigest) diff --git a/vendor/github.com/docker/distribution/registry/api/v2/urls_test.go b/vendor/github.com/docker/distribution/registry/api/v2/urls_test.go index 6d8973fad..4f854b23b 100644 --- a/vendor/github.com/docker/distribution/registry/api/v2/urls_test.go +++ b/vendor/github.com/docker/distribution/registry/api/v2/urls_test.go @@ -1,8 +1,10 @@ package v2 import ( + "fmt" "net/http" "net/url" + "reflect" "testing" "github.com/docker/distribution/reference" @@ -11,35 +13,48 @@ import ( type urlBuilderTestCase struct { description string expectedPath string + expectedErr error build func() (string, error) } func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { - fooBarRef, _ := reference.ParseNamed("foo/bar") + fooBarRef, _ := reference.WithName("foo/bar") return []urlBuilderTestCase{ { description: "test base url", expectedPath: "/v2/", + expectedErr: nil, build: urlBuilder.BuildBaseURL, }, { description: "test tags url", expectedPath: "/v2/foo/bar/tags/list", + expectedErr: nil, build: func() (string, error) { return urlBuilder.BuildTagsURL(fooBarRef) }, }, { - description: "test manifest url", + description: "test manifest url tagged ref", expectedPath: "/v2/foo/bar/manifests/tag", + expectedErr: nil, build: func() (string, error) { ref, _ := reference.WithTag(fooBarRef, "tag") return urlBuilder.BuildManifestURL(ref) }, }, + { + description: "test manifest url bare ref", + expectedPath: "", + expectedErr: fmt.Errorf("reference must have a tag or digest"), + build: func() (string, error) { + return urlBuilder.BuildManifestURL(fooBarRef) + }, + }, { description: "build blob url", expectedPath: "/v2/foo/bar/blobs/sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5", + expectedErr: nil, build: func() (string, error) { ref, _ := reference.WithDigest(fooBarRef, "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5") return urlBuilder.BuildBlobURL(ref) @@ -48,6 +63,7 @@ func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { { description: "build blob upload url", expectedPath: "/v2/foo/bar/blobs/uploads/", + expectedErr: nil, build: func() (string, error) { return urlBuilder.BuildBlobUploadURL(fooBarRef) }, @@ -55,6 +71,7 @@ func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { { description: "build blob upload url with digest and size", expectedPath: "/v2/foo/bar/blobs/uploads/?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000", + expectedErr: nil, build: func() (string, error) { return urlBuilder.BuildBlobUploadURL(fooBarRef, url.Values{ "size": []string{"10000"}, @@ -65,6 +82,7 @@ func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { { description: "build blob upload chunk url", expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part", + expectedErr: nil, build: func() (string, error) { return urlBuilder.BuildBlobUploadChunkURL(fooBarRef, "uuid-part") }, @@ -72,6 +90,7 @@ func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { { description: "build blob upload chunk url with digest and size", expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000", + expectedErr: nil, build: func() (string, error) { return urlBuilder.BuildBlobUploadChunkURL(fooBarRef, "uuid-part", url.Values{ "size": []string{"10000"}, @@ -101,9 +120,14 @@ func TestURLBuilder(t *testing.T) { for _, testCase := range makeURLBuilderTestCases(urlBuilder) { url, err := testCase.build() - if err != nil { - t.Fatalf("%s: error building url: %v", testCase.description, err) + expectedErr := testCase.expectedErr + if !reflect.DeepEqual(expectedErr, err) { + t.Fatalf("%s: Expecting %v but got error %v", testCase.description, expectedErr, err) } + if expectedErr != nil { + continue + } + expectedURL := testCase.expectedPath if !relative { expectedURL = root + expectedURL @@ -136,8 +160,12 @@ func TestURLBuilderWithPrefix(t *testing.T) { for _, testCase := range makeURLBuilderTestCases(urlBuilder) { url, err := testCase.build() - if err != nil { - t.Fatalf("%s: error building url: %v", testCase.description, err) + expectedErr := testCase.expectedErr + if !reflect.DeepEqual(expectedErr, err) { + t.Fatalf("%s: Expecting %v but got error %v", testCase.description, expectedErr, err) + } + if expectedErr != nil { + continue } expectedURL := testCase.expectedPath @@ -383,8 +411,12 @@ func TestBuilderFromRequest(t *testing.T) { for _, testCase := range makeURLBuilderTestCases(builder) { buildURL, err := testCase.build() - if err != nil { - t.Fatalf("[relative=%t, request=%q, case=%q]: error building url: %v", relative, tr.name, testCase.description, err) + expectedErr := testCase.expectedErr + if !reflect.DeepEqual(expectedErr, err) { + t.Fatalf("%s: Expecting %v but got error %v", testCase.description, expectedErr, err) + } + if expectedErr != nil { + continue } expectedURL := testCase.expectedPath @@ -452,8 +484,12 @@ func TestBuilderFromRequestWithPrefix(t *testing.T) { for _, testCase := range makeURLBuilderTestCases(builder) { buildURL, err := testCase.build() - if err != nil { - t.Fatalf("%s: error building url: %v", testCase.description, err) + expectedErr := testCase.expectedErr + if !reflect.DeepEqual(expectedErr, err) { + t.Fatalf("%s: Expecting %v but got error %v", testCase.description, expectedErr, err) + } + if expectedErr != nil { + continue } var expectedURL string diff --git a/vendor/github.com/docker/distribution/registry/auth/token/token_test.go b/vendor/github.com/docker/distribution/registry/auth/token/token_test.go index cbfe2a6b4..03dce6fa6 100644 --- a/vendor/github.com/docker/distribution/registry/auth/token/token_test.go +++ b/vendor/github.com/docker/distribution/registry/auth/token/token_test.go @@ -454,6 +454,27 @@ func TestAccessController(t *testing.T) { if userInfo.Name != "foo" { t.Fatalf("expected user name %q, got %q", "foo", userInfo.Name) } + + // 5. Supply a token with full admin rights, which is represented as "*". + token, err = makeTestToken( + issuer, service, + []*ResourceActions{{ + Type: testAccess.Type, + Name: testAccess.Name, + Actions: []string{"*"}, + }}, + rootKeys[0], 1, time.Now(), time.Now().Add(5*time.Minute), + ) + if err != nil { + t.Fatal(err) + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.compactRaw())) + + _, err = accessController.Authorized(ctx, testAccess) + if err != nil { + t.Fatalf("accessController returned unexpected error: %s", err) + } } // This tests that newAccessController can handle PEM blocks in the certificate diff --git a/vendor/github.com/docker/distribution/registry/client/auth/session.go b/vendor/github.com/docker/distribution/registry/client/auth/session.go index d6d884ffd..3ca5e8b3e 100644 --- a/vendor/github.com/docker/distribution/registry/client/auth/session.go +++ b/vendor/github.com/docker/distribution/registry/client/auth/session.go @@ -155,7 +155,9 @@ type RepositoryScope struct { // using the scope grammar func (rs RepositoryScope) String() string { repoType := "repository" - if rs.Class != "" { + // Keep existing format for image class to maintain backwards compatibility + // with authorization servers which do not support the expanded grammar. + if rs.Class != "" && rs.Class != "image" { repoType = fmt.Sprintf("%s(%s)", repoType, rs.Class) } return fmt.Sprintf("%s:%s:%s", repoType, rs.Repository, strings.Join(rs.Actions, ",")) diff --git a/vendor/github.com/docker/distribution/registry/client/repository.go b/vendor/github.com/docker/distribution/registry/client/repository.go index 1ebd0b183..b82a968e2 100644 --- a/vendor/github.com/docker/distribution/registry/client/repository.go +++ b/vendor/github.com/docker/distribution/registry/client/repository.go @@ -15,12 +15,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/client/transport" "github.com/docker/distribution/registry/storage/cache" "github.com/docker/distribution/registry/storage/cache/memory" + "github.com/opencontainers/go-digest" ) // Registry provides an interface for calling Repositories, which returns a catalog of repositories. @@ -268,7 +268,7 @@ func descriptorFromResponse(response *http.Response) (distribution.Descriptor, e return desc, nil } - dgst, err := digest.ParseDigest(digestHeader) + dgst, err := digest.Parse(digestHeader) if err != nil { return distribution.Descriptor{}, err } @@ -475,7 +475,7 @@ func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...dis return nil, distribution.ErrManifestNotModified } else if SuccessStatus(resp.StatusCode) { if contentDgst != nil { - dgst, err := digest.ParseDigest(resp.Header.Get("Docker-Content-Digest")) + dgst, err := digest.Parse(resp.Header.Get("Docker-Content-Digest")) if err == nil { *contentDgst = dgst } @@ -553,7 +553,7 @@ func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options . if SuccessStatus(resp.StatusCode) { dgstHeader := resp.Header.Get("Docker-Content-Digest") - dgst, err := digest.ParseDigest(dgstHeader) + dgst, err := digest.Parse(dgstHeader) if err != nil { return "", err } @@ -661,7 +661,7 @@ func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (distribut if err != nil { return distribution.Descriptor{}, err } - dgstr := digest.Canonical.New() + dgstr := digest.Canonical.Digester() n, err := io.Copy(writer, io.TeeReader(bytes.NewReader(p), dgstr.Hash())) if err != nil { return distribution.Descriptor{}, err diff --git a/vendor/github.com/docker/distribution/registry/client/repository_test.go b/vendor/github.com/docker/distribution/registry/client/repository_test.go index a232e03ec..f22fa33d4 100644 --- a/vendor/github.com/docker/distribution/registry/client/repository_test.go +++ b/vendor/github.com/docker/distribution/registry/client/repository_test.go @@ -16,7 +16,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -25,6 +24,7 @@ import ( "github.com/docker/distribution/testutil" "github.com/docker/distribution/uuid" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) func testServer(rrm testutil.RequestResponseMap) (string, func()) { @@ -100,7 +100,7 @@ func addTestCatalog(route string, content []byte, link string, m *testutil.Reque func TestBlobDelete(t *testing.T) { dgst, _ := newRandomBlob(1024) var m testutil.RequestResponseMap - repo, _ := reference.ParseNamed("test.example.com/repo1") + repo, _ := reference.WithName("test.example.com/repo1") m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ Method: "DELETE", @@ -139,7 +139,7 @@ func TestBlobFetch(t *testing.T) { defer c() ctx := context.Background() - repo, _ := reference.ParseNamed("test.example.com/repo1") + repo, _ := reference.WithName("test.example.com/repo1") r, err := NewRepository(ctx, repo, e, nil) if err != nil { t.Fatal(err) @@ -160,7 +160,7 @@ func TestBlobFetch(t *testing.T) { func TestBlobExistsNoContentLength(t *testing.T) { var m testutil.RequestResponseMap - repo, _ := reference.ParseNamed("biff") + repo, _ := reference.WithName("biff") dgst, content := newRandomBlob(1024) m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ @@ -219,7 +219,7 @@ func TestBlobExists(t *testing.T) { defer c() ctx := context.Background() - repo, _ := reference.ParseNamed("test.example.com/repo1") + repo, _ := reference.WithName("test.example.com/repo1") r, err := NewRepository(ctx, repo, e, nil) if err != nil { t.Fatal(err) @@ -251,7 +251,7 @@ func TestBlobUploadChunked(t *testing.T) { b1[512:513], b1[513:1024], } - repo, _ := reference.ParseNamed("test.example.com/uploadrepo") + repo, _ := reference.WithName("test.example.com/uploadrepo") uuids := []string{uuid.Generate().String()} m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ @@ -366,7 +366,7 @@ func TestBlobUploadChunked(t *testing.T) { func TestBlobUploadMonolithic(t *testing.T) { dgst, b1 := newRandomBlob(1024) var m testutil.RequestResponseMap - repo, _ := reference.ParseNamed("test.example.com/uploadrepo") + repo, _ := reference.WithName("test.example.com/uploadrepo") uploadID := uuid.Generate().String() m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ @@ -474,9 +474,9 @@ func TestBlobUploadMonolithic(t *testing.T) { func TestBlobMount(t *testing.T) { dgst, content := newRandomBlob(1024) var m testutil.RequestResponseMap - repo, _ := reference.ParseNamed("test.example.com/uploadrepo") + repo, _ := reference.WithName("test.example.com/uploadrepo") - sourceRepo, _ := reference.ParseNamed("test.example.com/sourcerepo") + sourceRepo, _ := reference.WithName("test.example.com/sourcerepo") canonicalRef, _ := reference.WithDigest(sourceRepo, dgst) m = append(m, testutil.RequestResponseMapping{ @@ -678,7 +678,7 @@ func checkEqualManifest(m1, m2 *schema1.SignedManifest) error { func TestV1ManifestFetch(t *testing.T) { ctx := context.Background() - repo, _ := reference.ParseNamed("test.example.com/repo") + repo, _ := reference.WithName("test.example.com/repo") m1, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6) var m testutil.RequestResponseMap _, pl, err := m1.Payload() @@ -755,7 +755,7 @@ func TestV1ManifestFetch(t *testing.T) { } func TestManifestFetchWithEtag(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo/by/tag") + repo, _ := reference.WithName("test.example.com/repo/by/tag") _, d1, p1 := newRandomSchemaV1Manifest(repo, "latest", 6) var m testutil.RequestResponseMap addTestManifestWithEtag(repo, "latest", p1, &m, d1.String()) @@ -785,7 +785,7 @@ func TestManifestFetchWithEtag(t *testing.T) { } func TestManifestDelete(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo/delete") + repo, _ := reference.WithName("test.example.com/repo/delete") _, dgst1, _ := newRandomSchemaV1Manifest(repo, "latest", 6) _, dgst2, _ := newRandomSchemaV1Manifest(repo, "latest", 6) var m testutil.RequestResponseMap @@ -825,7 +825,7 @@ func TestManifestDelete(t *testing.T) { } func TestManifestPut(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo/delete") + repo, _ := reference.WithName("test.example.com/repo/delete") m1, dgst, _ := newRandomSchemaV1Manifest(repo, "other", 6) _, payload, err := m1.Payload() @@ -890,7 +890,7 @@ func TestManifestPut(t *testing.T) { } func TestManifestTags(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo/tags/list") + repo, _ := reference.WithName("test.example.com/repo/tags/list") tagsList := []byte(strings.TrimSpace(` { "name": "test.example.com/repo/tags/list", @@ -952,7 +952,7 @@ func TestManifestTags(t *testing.T) { } func TestObtainsErrorForMissingTag(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo") + repo, _ := reference.WithName("test.example.com/repo") var m testutil.RequestResponseMap var errors errcode.Errors @@ -998,7 +998,7 @@ func TestManifestTagsPaginated(t *testing.T) { s := httptest.NewServer(http.NotFoundHandler()) defer s.Close() - repo, _ := reference.ParseNamed("test.example.com/repo/tags/list") + repo, _ := reference.WithName("test.example.com/repo/tags/list") tagsList := []string{"tag1", "tag2", "funtag"} var m testutil.RequestResponseMap for i := 0; i < 3; i++ { @@ -1067,7 +1067,7 @@ func TestManifestTagsPaginated(t *testing.T) { } func TestManifestUnauthorized(t *testing.T) { - repo, _ := reference.ParseNamed("test.example.com/repo") + repo, _ := reference.WithName("test.example.com/repo") _, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6) var m testutil.RequestResponseMap diff --git a/vendor/github.com/docker/distribution/registry/handlers/api_test.go b/vendor/github.com/docker/distribution/registry/handlers/api_test.go index 9d64fbbf4..c8e756de6 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/api_test.go +++ b/vendor/github.com/docker/distribution/registry/handlers/api_test.go @@ -3,6 +3,7 @@ package handlers import ( "bytes" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -21,7 +22,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/configuration" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" @@ -29,16 +29,24 @@ import ( "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" + storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/docker/distribution/registry/storage/driver/factory" _ "github.com/docker/distribution/registry/storage/driver/testdriver" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) var headerConfig = http.Header{ "X-Content-Type-Options": []string{"nosniff"}, } +const ( + // digestSha256EmptyTar is the canonical sha256 digest of empty data + digestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +) + // TestCheckAPI hits the base endpoint (/v2/) ensures we return the specified // 200 OK response. func TestCheckAPI(t *testing.T) { @@ -272,7 +280,7 @@ func makeBlobArgs(t *testing.T) blobArgs { layerFile: layerFile, layerDigest: layerDigest, } - args.imageName, _ = reference.ParseNamed("foo/bar") + args.imageName, _ = reference.WithName("foo/bar") return args } @@ -514,7 +522,7 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv { // Now, push just a chunk layerFile.Seek(0, 0) - canonicalDigester := digest.Canonical.New() + canonicalDigester := digest.Canonical.Digester() if _, err := io.Copy(canonicalDigester.Hash(), layerFile); err != nil { t.Fatalf("error copying to digest: %v", err) } @@ -552,10 +560,7 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv { }) // Verify the body - verifier, err := digest.NewDigestVerifier(layerDigest) - if err != nil { - t.Fatalf("unexpected error getting digest verifier: %s", err) - } + verifier := layerDigest.Verifier() io.Copy(verifier, resp.Body) if !verifier.Verified() { @@ -675,7 +680,7 @@ func testBlobDelete(t *testing.T, env *testEnv, args blobArgs) { pushLayer(t, env.builder, imageName, layerDigest, uploadURLBase, layerFile) layerFile.Seek(0, os.SEEK_SET) - canonicalDigester := digest.Canonical.New() + canonicalDigester := digest.Canonical.Digester() if _, err := io.Copy(canonicalDigester.Hash(), layerFile); err != nil { t.Fatalf("error copying to digest: %v", err) } @@ -700,7 +705,7 @@ func TestDeleteDisabled(t *testing.T) { env := newTestEnv(t, false) defer env.Shutdown() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") // "build" our layer file layerFile, layerDigest, err := testutil.CreateRandomTarFile() if err != nil { @@ -727,7 +732,7 @@ func TestDeleteReadOnly(t *testing.T) { env := newTestEnv(t, true) defer env.Shutdown() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") // "build" our layer file layerFile, layerDigest, err := testutil.CreateRandomTarFile() if err != nil { @@ -757,7 +762,7 @@ func TestStartPushReadOnly(t *testing.T) { defer env.Shutdown() env.app.readOnly = true - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") layerUploadURL, err := env.builder.BuildBlobUploadURL(imageName) if err != nil { @@ -795,8 +800,8 @@ type manifestArgs struct { } func TestManifestAPI(t *testing.T) { - schema1Repo, _ := reference.ParseNamed("foo/schema1") - schema2Repo, _ := reference.ParseNamed("foo/schema2") + schema1Repo, _ := reference.WithName("foo/schema1") + schema2Repo, _ := reference.WithName("foo/schema2") deleteEnabled := false env1 := newTestEnv(t, deleteEnabled) @@ -813,9 +818,96 @@ func TestManifestAPI(t *testing.T) { testManifestAPIManifestList(t, env2, schema2Args) } +// storageManifestErrDriverFactory implements the factory.StorageDriverFactory interface. +type storageManifestErrDriverFactory struct{} + +const ( + repositoryWithManifestNotFound = "manifesttagnotfound" + repositoryWithManifestInvalidPath = "manifestinvalidpath" + repositoryWithManifestBadLink = "manifestbadlink" + repositoryWithGenericStorageError = "genericstorageerr" +) + +func (factory *storageManifestErrDriverFactory) Create(parameters map[string]interface{}) (storagedriver.StorageDriver, error) { + // Initialize the mock driver + var errGenericStorage = errors.New("generic storage error") + return &mockErrorDriver{ + returnErrs: []mockErrorMapping{ + { + pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestNotFound), + content: nil, + err: storagedriver.PathNotFoundError{}, + }, + { + pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestInvalidPath), + content: nil, + err: storagedriver.InvalidPathError{}, + }, + { + pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithManifestBadLink), + content: []byte("this is a bad sha"), + err: nil, + }, + { + pathMatch: fmt.Sprintf("%s/_manifests/tags", repositoryWithGenericStorageError), + content: nil, + err: errGenericStorage, + }, + }, + }, nil +} + +type mockErrorMapping struct { + pathMatch string + content []byte + err error +} + +// mockErrorDriver implements StorageDriver to force storage error on manifest request +type mockErrorDriver struct { + storagedriver.StorageDriver + returnErrs []mockErrorMapping +} + +func (dr *mockErrorDriver) GetContent(ctx context.Context, path string) ([]byte, error) { + for _, returns := range dr.returnErrs { + if strings.Contains(path, returns.pathMatch) { + return returns.content, returns.err + } + } + return nil, errors.New("Unknown storage error") +} + +func TestGetManifestWithStorageError(t *testing.T) { + factory.Register("storagemanifesterror", &storageManifestErrDriverFactory{}) + config := configuration.Configuration{ + Storage: configuration.Storage{ + "storagemanifesterror": configuration.Parameters{}, + "maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{ + "enabled": false, + }}, + }, + } + config.HTTP.Headers = headerConfig + env1 := newTestEnvWithConfig(t, &config) + defer env1.Shutdown() + + repo, _ := reference.WithName(repositoryWithManifestNotFound) + testManifestWithStorageError(t, env1, repo, http.StatusNotFound, v2.ErrorCodeManifestUnknown) + + repo, _ = reference.WithName(repositoryWithGenericStorageError) + testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown) + + repo, _ = reference.WithName(repositoryWithManifestInvalidPath) + testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown) + + repo, _ = reference.WithName(repositoryWithManifestBadLink) + testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown) +} + func TestManifestDelete(t *testing.T) { - schema1Repo, _ := reference.ParseNamed("foo/schema1") - schema2Repo, _ := reference.ParseNamed("foo/schema2") + schema1Repo, _ := reference.WithName("foo/schema1") + schema2Repo, _ := reference.WithName("foo/schema2") deleteEnabled := true env := newTestEnv(t, deleteEnabled) @@ -827,7 +919,7 @@ func TestManifestDelete(t *testing.T) { } func TestManifestDeleteDisabled(t *testing.T) { - schema1Repo, _ := reference.ParseNamed("foo/schema1") + schema1Repo, _ := reference.WithName("foo/schema1") deleteEnabled := false env := newTestEnv(t, deleteEnabled) defer env.Shutdown() @@ -835,7 +927,7 @@ func TestManifestDeleteDisabled(t *testing.T) { } func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference.Named) { - ref, _ := reference.WithDigest(imageName, digest.DigestSha256EmptyTar) + ref, _ := reference.WithDigest(imageName, digestSha256EmptyTar) manifestURL, err := env.builder.BuildManifestURL(ref) if err != nil { t.Fatalf("unexpected error getting manifest url: %v", err) @@ -850,6 +942,26 @@ func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference. checkResponse(t, "status of disabled delete of manifest", resp, http.StatusMethodNotAllowed) } +func testManifestWithStorageError(t *testing.T, env *testEnv, imageName reference.Named, expectedStatusCode int, expectedErrorCode errcode.ErrorCode) { + tag := "latest" + tagRef, _ := reference.WithTag(imageName, tag) + manifestURL, err := env.builder.BuildManifestURL(tagRef) + if err != nil { + t.Fatalf("unexpected error getting manifest url: %v", err) + } + + // ----------------------------- + // Attempt to fetch the manifest + resp, err := http.Get(manifestURL) + if err != nil { + t.Fatalf("unexpected error getting manifest: %v", err) + } + defer resp.Body.Close() + checkResponse(t, "getting non-existent manifest", resp, expectedStatusCode) + checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode) + return +} + func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs { tag := "thetag" args := manifestArgs{imageName: imageName} @@ -1218,7 +1330,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name Config: distribution.Descriptor{ Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b", Size: 3253, - MediaType: schema2.MediaTypeConfig, + MediaType: schema2.MediaTypeImageConfig, }, Layers: []distribution.Descriptor{ { @@ -2075,7 +2187,7 @@ func doPushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst dig // pushLayer pushes the layer content returning the url on success. func pushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst digest.Digest, uploadURLBase string, body io.Reader) string { - digester := digest.Canonical.New() + digester := digest.Canonical.Digester() resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, io.TeeReader(body, digester.Hash())) if err != nil { @@ -2142,7 +2254,7 @@ func doPushChunk(t *testing.T, uploadURLBase string, body io.Reader) (*http.Resp uploadURL := u.String() - digester := digest.Canonical.New() + digester := digest.Canonical.Digester() req, err := http.NewRequest("PATCH", uploadURL, io.TeeReader(body, digester.Hash())) if err != nil { @@ -2291,7 +2403,7 @@ func checkErr(t *testing.T, err error, msg string) { } func createRepository(env *testEnv, t *testing.T, imageName string, tag string) digest.Digest { - imageNameRef, err := reference.ParseNamed(imageName) + imageNameRef, err := reference.WithName(imageName) if err != nil { t.Fatalf("unable to parse reference: %v", err) } @@ -2362,7 +2474,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) { env := newTestEnvMirror(t, deleteEnabled) defer env.Shutdown() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") tag := "latest" tagRef, _ := reference.WithTag(imageName, tag) manifestURL, err := env.builder.BuildManifestURL(tagRef) @@ -2408,7 +2520,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) { checkResponse(t, fmt.Sprintf("starting layer push to cache %v", imageName), resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode) // Blob Delete - ref, _ := reference.WithDigest(imageName, digest.DigestSha256EmptyTar) + ref, _ := reference.WithDigest(imageName, digestSha256EmptyTar) blobURL, err := env.builder.BuildBlobURL(ref) resp, err = httpDelete(blobURL) checkResponse(t, "deleting blob from cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode) @@ -2455,7 +2567,7 @@ func TestProxyManifestGetByTag(t *testing.T) { } truthConfig.HTTP.Headers = headerConfig - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") tag := "latest" truthEnv := newTestEnvWithConfig(t, &truthConfig) diff --git a/vendor/github.com/docker/distribution/registry/handlers/app.go b/vendor/github.com/docker/distribution/registry/handlers/app.go index 0f30603f0..5b4c9f37d 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/app.go +++ b/vendor/github.com/docker/distribution/registry/handlers/app.go @@ -100,7 +100,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App { app.register(v2.RouteNameBase, func(ctx *Context, r *http.Request) http.Handler { return http.HandlerFunc(apiBase) }) - app.register(v2.RouteNameManifest, imageManifestDispatcher) + app.register(v2.RouteNameManifest, manifestDispatcher) app.register(v2.RouteNameCatalog, catalogDispatcher) app.register(v2.RouteNameTags, tagsDispatcher) app.register(v2.RouteNameBlob, blobDispatcher) @@ -213,6 +213,10 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App { options = append(options, storage.EnableRedirect) } + if !config.Validation.Enabled { + config.Validation.Enabled = !config.Validation.Disabled + } + // configure validation if config.Validation.Enabled { if len(config.Validation.Manifests.URLs.Allow) == 0 && len(config.Validation.Manifests.URLs.Deny) == 0 { @@ -592,24 +596,19 @@ func (app *App) configureSecret(configuration *configuration.Configuration) { func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() // ensure that request body is always closed. - // Instantiate an http context here so we can track the error codes - // returned by the request router. - ctx := defaultContextManager.context(app, w, r) + // Prepare the context with our own little decorations. + ctx := r.Context() + ctx = ctxu.WithRequest(ctx, r) + ctx, w = ctxu.WithResponseWriter(ctx, w) + ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx)) + r = r.WithContext(ctx) defer func() { status, ok := ctx.Value("http.response.status").(int) if ok && status >= 200 && status <= 399 { - ctxu.GetResponseLogger(ctx).Infof("response completed") + ctxu.GetResponseLogger(r.Context()).Infof("response completed") } }() - defer defaultContextManager.release(ctx) - - // NOTE(stevvooe): Total hack to get instrumented responsewriter from context. - var err error - w, err = ctxu.GetResponseWriter(ctx) - if err != nil { - ctxu.GetLogger(ctx).Warnf("response writer not found in context") - } // Set a header with the Docker Distribution API Version for all responses. w.Header().Add("Docker-Distribution-API-Version", "registry/2.0") @@ -645,8 +644,11 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler { // Add username to request logging context.Context = ctxu.WithLogger(context.Context, ctxu.GetLogger(context.Context, auth.UserNameKey)) + // sync up context on the request. + r = r.WithContext(context) + if app.nameRequired(r) { - nameRef, err := reference.ParseNamed(getName(context)) + nameRef, err := reference.WithName(getName(context)) if err != nil { ctxu.GetLogger(context).Errorf("error parsing reference from context: %v", err) context.Errors = append(context.Errors, distribution.ErrRepositoryNameInvalid{ @@ -752,7 +754,7 @@ func (app *App) logError(context context.Context, errors errcode.Errors) { // context constructs the context object for the application. This only be // called once per request. func (app *App) context(w http.ResponseWriter, r *http.Request) *Context { - ctx := defaultContextManager.context(app, w, r) + ctx := r.Context() ctx = ctxu.WithVars(ctx, r) ctx = ctxu.WithLogger(ctx, ctxu.GetLogger(ctx, "vars.name", @@ -857,8 +859,11 @@ func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listene // nameRequired returns true if the route requires a name. func (app *App) nameRequired(r *http.Request) bool { route := mux.CurrentRoute(r) + if route == nil { + return true + } routeName := route.GetName() - return route == nil || (routeName != v2.RouteNameBase && routeName != v2.RouteNameCatalog) + return routeName != v2.RouteNameBase && routeName != v2.RouteNameCatalog } // apiBase implements a simple yes-man for doing overall checks against the @@ -897,12 +902,10 @@ func appendAccessRecords(records []auth.Access, method string, repo string) []au Action: "push", }) case "DELETE": - // DELETE access requires full admin rights, which is represented - // as "*". This may not be ideal. records = append(records, auth.Access{ Resource: resource, - Action: "*", + Action: "delete", }) } return records diff --git a/vendor/github.com/docker/distribution/registry/handlers/app_test.go b/vendor/github.com/docker/distribution/registry/handlers/app_test.go index 385fa4c6b..12c0b61c1 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/app_test.go +++ b/vendor/github.com/docker/distribution/registry/handlers/app_test.go @@ -229,9 +229,9 @@ func TestAppendAccessRecords(t *testing.T) { Resource: expectedResource, Action: "push", } - expectedAllRecord := auth.Access{ + expectedDeleteRecord := auth.Access{ Resource: expectedResource, - Action: "*", + Action: "delete", } records := []auth.Access{} @@ -271,7 +271,7 @@ func TestAppendAccessRecords(t *testing.T) { records = []auth.Access{} result = appendAccessRecords(records, "DELETE", repo) - expectedResult = []auth.Access{expectedAllRecord} + expectedResult = []auth.Access{expectedDeleteRecord} if ok := reflect.DeepEqual(result, expectedResult); !ok { t.Fatalf("Actual access record differs from expected") } diff --git a/vendor/github.com/docker/distribution/registry/handlers/blob.go b/vendor/github.com/docker/distribution/registry/handlers/blob.go index fb250acd2..5c31cc767 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/blob.go +++ b/vendor/github.com/docker/distribution/registry/handlers/blob.go @@ -5,10 +5,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // blobDispatcher uses the request context to build a blobHandler. diff --git a/vendor/github.com/docker/distribution/registry/handlers/blobupload.go b/vendor/github.com/docker/distribution/registry/handlers/blobupload.go index 3afb47398..963fe4e7d 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/blobupload.go +++ b/vendor/github.com/docker/distribution/registry/handlers/blobupload.go @@ -7,12 +7,12 @@ import ( "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/storage" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // blobUploadDispatcher constructs and returns the blob upload handler for the @@ -211,7 +211,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht return } - dgst, err := digest.ParseDigest(dgstStr) + dgst, err := digest.Parse(dgstStr) if err != nil { // no digest? return error, but allow retry. buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail("digest parsing failed")) @@ -329,12 +329,12 @@ func (buh *blobUploadHandler) blobUploadResponse(w http.ResponseWriter, r *http. // successful, the blob is linked into the blob store and 201 Created is // returned with the canonical url of the blob. func (buh *blobUploadHandler) createBlobMountOption(fromRepo, mountDigest string) (distribution.BlobCreateOption, error) { - dgst, err := digest.ParseDigest(mountDigest) + dgst, err := digest.Parse(mountDigest) if err != nil { return nil, err } - ref, err := reference.ParseNamed(fromRepo) + ref, err := reference.WithName(fromRepo) if err != nil { return nil, err } diff --git a/vendor/github.com/docker/distribution/registry/handlers/context.go b/vendor/github.com/docker/distribution/registry/handlers/context.go index 552db2df6..6c1be5b31 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/context.go +++ b/vendor/github.com/docker/distribution/registry/handlers/context.go @@ -3,14 +3,13 @@ package handlers import ( "fmt" "net/http" - "sync" "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" + "github.com/opencontainers/go-digest" "golang.org/x/net/context" ) @@ -62,7 +61,7 @@ func getDigest(ctx context.Context) (dgst digest.Digest, err error) { return "", errDigestNotAvailable } - d, err := digest.ParseDigest(dgstStr) + d, err := digest.Parse(dgstStr) if err != nil { ctxu.GetLogger(ctx).Errorf("error parsing digest=%q: %v", dgstStr, err) return "", err @@ -91,62 +90,3 @@ func getUserName(ctx context.Context, r *http.Request) string { return username } - -// contextManager allows us to associate net/context.Context instances with a -// request, based on the memory identity of http.Request. This prepares http- -// level context, which is not application specific. If this is called, -// (*contextManager).release must be called on the context when the request is -// completed. -// -// Providing this circumvents a lot of necessity for dispatchers with the -// benefit of instantiating the request context much earlier. -// -// TODO(stevvooe): Consider making this facility a part of the context package. -type contextManager struct { - contexts map[*http.Request]context.Context - mu sync.Mutex -} - -// defaultContextManager is just a global instance to register request contexts. -var defaultContextManager = newContextManager() - -func newContextManager() *contextManager { - return &contextManager{ - contexts: make(map[*http.Request]context.Context), - } -} - -// context either returns a new context or looks it up in the manager. -func (cm *contextManager) context(parent context.Context, w http.ResponseWriter, r *http.Request) context.Context { - cm.mu.Lock() - defer cm.mu.Unlock() - - ctx, ok := cm.contexts[r] - if ok { - return ctx - } - - if parent == nil { - parent = ctxu.Background() - } - - ctx = ctxu.WithRequest(parent, r) - ctx, w = ctxu.WithResponseWriter(ctx, w) - ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx)) - cm.contexts[r] = ctx - - return ctx -} - -// releases frees any associated with resources from request. -func (cm *contextManager) release(ctx context.Context) { - cm.mu.Lock() - defer cm.mu.Unlock() - - r, err := ctxu.GetRequest(ctx) - if err != nil { - ctxu.GetLogger(ctx).Errorf("no request found in context during release") - return - } - delete(cm.contexts, r) -} diff --git a/vendor/github.com/docker/distribution/registry/handlers/images.go b/vendor/github.com/docker/distribution/registry/handlers/manifests.go similarity index 84% rename from vendor/github.com/docker/distribution/registry/handlers/images.go rename to vendor/github.com/docker/distribution/registry/handlers/manifests.go index 9518f6855..f406903fa 100644 --- a/vendor/github.com/docker/distribution/registry/handlers/images.go +++ b/vendor/github.com/docker/distribution/registry/handlers/manifests.go @@ -8,7 +8,6 @@ import ( "github.com/docker/distribution" ctxu "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" @@ -17,6 +16,7 @@ import ( "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" "github.com/gorilla/handlers" + "github.com/opencontainers/go-digest" ) // These constants determine which architecture and OS to choose from a @@ -26,36 +26,36 @@ const ( defaultOS = "linux" ) -// imageManifestDispatcher takes the request context and builds the -// appropriate handler for handling image manifest requests. -func imageManifestDispatcher(ctx *Context, r *http.Request) http.Handler { - imageManifestHandler := &imageManifestHandler{ +// manifestDispatcher takes the request context and builds the +// appropriate handler for handling manifest requests. +func manifestDispatcher(ctx *Context, r *http.Request) http.Handler { + manifestHandler := &manifestHandler{ Context: ctx, } reference := getReference(ctx) - dgst, err := digest.ParseDigest(reference) + dgst, err := digest.Parse(reference) if err != nil { // We just have a tag - imageManifestHandler.Tag = reference + manifestHandler.Tag = reference } else { - imageManifestHandler.Digest = dgst + manifestHandler.Digest = dgst } mhandler := handlers.MethodHandler{ - "GET": http.HandlerFunc(imageManifestHandler.GetImageManifest), - "HEAD": http.HandlerFunc(imageManifestHandler.GetImageManifest), + "GET": http.HandlerFunc(manifestHandler.GetManifest), + "HEAD": http.HandlerFunc(manifestHandler.GetManifest), } if !ctx.readOnly { - mhandler["PUT"] = http.HandlerFunc(imageManifestHandler.PutImageManifest) - mhandler["DELETE"] = http.HandlerFunc(imageManifestHandler.DeleteImageManifest) + mhandler["PUT"] = http.HandlerFunc(manifestHandler.PutManifest) + mhandler["DELETE"] = http.HandlerFunc(manifestHandler.DeleteManifest) } return mhandler } -// imageManifestHandler handles http operations on image manifests. -type imageManifestHandler struct { +// manifestHandler handles http operations on image manifests. +type manifestHandler struct { *Context // One of tag or digest gets set, depending on what is present in context. @@ -63,8 +63,8 @@ type imageManifestHandler struct { Digest digest.Digest } -// GetImageManifest fetches the image manifest from the storage backend, if it exists. -func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http.Request) { +// GetManifest fetches the image manifest from the storage backend, if it exists. +func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request) { ctxu.GetLogger(imh).Debug("GetImageManifest") manifests, err := imh.Repository.Manifests(imh) if err != nil { @@ -77,7 +77,11 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http tags := imh.Repository.Tags(imh) desc, err := tags.Get(imh, imh.Tag) if err != nil { - imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + if _, ok := err.(distribution.ErrTagUnknown); ok { + imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + } else { + imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) + } return } imh.Digest = desc.Digest @@ -94,7 +98,11 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http } manifest, err = manifests.Get(imh, imh.Digest, options...) if err != nil { - imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + if _, ok := err.(distribution.ErrManifestUnknownRevision); ok { + imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + } else { + imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) + } return } @@ -161,7 +169,11 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http manifest, err = manifests.Get(imh, manifestDigest) if err != nil { - imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + if _, ok := err.(distribution.ErrManifestUnknownRevision); ok { + imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) + } else { + imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) + } return } @@ -171,6 +183,8 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http if err != nil { return } + } else { + imh.Digest = manifestDigest } } @@ -186,12 +200,16 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http w.Write(p) } -func (imh *imageManifestHandler) convertSchema2Manifest(schema2Manifest *schema2.DeserializedManifest) (distribution.Manifest, error) { +func (imh *manifestHandler) convertSchema2Manifest(schema2Manifest *schema2.DeserializedManifest) (distribution.Manifest, error) { targetDescriptor := schema2Manifest.Target() blobs := imh.Repository.Blobs(imh) configJSON, err := blobs.Get(imh, targetDescriptor.Digest) if err != nil { - imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err)) + if err == distribution.ErrBlobUnknown { + imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err)) + } else { + imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) + } return nil, err } @@ -231,8 +249,8 @@ func etagMatch(r *http.Request, etag string) bool { return false } -// PutImageManifest validates and stores an image in the registry. -func (imh *imageManifestHandler) PutImageManifest(w http.ResponseWriter, r *http.Request) { +// PutManifest validates and stores a manifest in the registry. +func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request) { ctxu.GetLogger(imh).Debug("PutImageManifest") manifests, err := imh.Repository.Manifests(imh) if err != nil { @@ -348,7 +366,7 @@ func (imh *imageManifestHandler) PutImageManifest(w http.ResponseWriter, r *http // applyResourcePolicy checks whether the resource class matches what has // been authorized and allowed by the policy configuration. -func (imh *imageManifestHandler) applyResourcePolicy(manifest distribution.Manifest) error { +func (imh *manifestHandler) applyResourcePolicy(manifest distribution.Manifest) error { allowedClasses := imh.App.Config.Policy.Repository.Classes if len(allowedClasses) == 0 { return nil @@ -360,7 +378,7 @@ func (imh *imageManifestHandler) applyResourcePolicy(manifest distribution.Manif class = "image" case *schema2.DeserializedManifest: switch m.Config.MediaType { - case schema2.MediaTypeConfig: + case schema2.MediaTypeImageConfig: class = "image" case schema2.MediaTypePluginConfig: class = "plugin" @@ -413,8 +431,8 @@ func (imh *imageManifestHandler) applyResourcePolicy(manifest distribution.Manif } -// DeleteImageManifest removes the manifest with the given digest from the registry. -func (imh *imageManifestHandler) DeleteImageManifest(w http.ResponseWriter, r *http.Request) { +// DeleteManifest removes the manifest with the given digest from the registry. +func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Request) { ctxu.GetLogger(imh).Debug("DeleteImageManifest") manifests, err := imh.Repository.Manifests(imh) diff --git a/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore.go b/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore.go index 6cd572133..c3f1b92f1 100644 --- a/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore.go +++ b/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore.go @@ -9,9 +9,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" + "github.com/opencontainers/go-digest" ) // todo(richardscothern): from cache control header or config file diff --git a/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore_test.go b/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore_test.go index 8e3a06920..0bba01a6f 100644 --- a/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore_test.go +++ b/vendor/github.com/docker/distribution/registry/proxy/proxyblobstore_test.go @@ -11,13 +11,13 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" "github.com/docker/distribution/registry/storage" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver/filesystem" "github.com/docker/distribution/registry/storage/driver/inmemory" + "github.com/opencontainers/go-digest" ) var sbsMu sync.Mutex @@ -115,7 +115,7 @@ func (te *testEnv) RemoteStats() *map[string]int { // Populate remote store and record the digests func makeTestEnv(t *testing.T, name string) *testEnv { - nameRef, err := reference.ParseNamed(name) + nameRef, err := reference.WithName(name) if err != nil { t.Fatalf("unable to parse reference: %s", err) } diff --git a/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore.go b/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore.go index f08e285db..e0a9f7d3f 100644 --- a/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore.go +++ b/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/proxy/scheduler" + "github.com/opencontainers/go-digest" ) // todo(richardscothern): from cache control header or config diff --git a/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore_test.go b/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore_test.go index 067e845a2..ca0845b90 100644 --- a/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore_test.go +++ b/vendor/github.com/docker/distribution/registry/proxy/proxymanifeststore_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -19,6 +18,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type statsManifest struct { @@ -83,7 +83,7 @@ func (m *mockChallenger) challengeManager() challenge.Manager { } func newManifestStoreTestEnv(t *testing.T, name, tag string) *manifestStoreTestEnv { - nameRef, err := reference.ParseNamed(name) + nameRef, err := reference.WithName(name) if err != nil { t.Fatalf("unable to parse reference: %s", err) } diff --git a/vendor/github.com/docker/distribution/registry/registry.go b/vendor/github.com/docker/distribution/registry/registry.go index 2adcb1e3e..ee3d6b0bd 100644 --- a/vendor/github.com/docker/distribution/registry/registry.go +++ b/vendor/github.com/docker/distribution/registry/registry.go @@ -12,7 +12,7 @@ import ( "rsc.io/letsencrypt" log "github.com/Sirupsen/logrus" - "github.com/Sirupsen/logrus/formatters/logstash" + logstash "github.com/bshuster-repo/logrus-logstash-hook" "github.com/bugsnag/bugsnag-go" "github.com/docker/distribution/configuration" "github.com/docker/distribution/context" diff --git a/vendor/github.com/docker/distribution/registry/storage/blob_test.go b/vendor/github.com/docker/distribution/registry/storage/blob_test.go index 767526bb2..a263dd6cd 100644 --- a/vendor/github.com/docker/distribution/registry/storage/blob_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/blob_test.go @@ -13,18 +13,18 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver/testdriver" "github.com/docker/distribution/testutil" + "github.com/opencontainers/go-digest" ) // TestWriteSeek tests that the current file size can be // obtained using Seek func TestWriteSeek(t *testing.T) { ctx := context.Background() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") driver := testdriver.New() registry, err := NewRegistry(ctx, driver, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableDelete, EnableRedirect) if err != nil { @@ -60,7 +60,7 @@ func TestSimpleBlobUpload(t *testing.T) { } ctx := context.Background() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") driver := testdriver.New() registry, err := NewRegistry(ctx, driver, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableDelete, EnableRedirect) if err != nil { @@ -255,7 +255,7 @@ func TestSimpleBlobUpload(t *testing.T) { // other tests. func TestSimpleBlobRead(t *testing.T) { ctx := context.Background() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") driver := testdriver.New() registry, err := NewRegistry(ctx, driver, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableDelete, EnableRedirect) if err != nil { @@ -366,8 +366,8 @@ func TestBlobMount(t *testing.T) { } ctx := context.Background() - imageName, _ := reference.ParseNamed("foo/bar") - sourceImageName, _ := reference.ParseNamed("foo/source") + imageName, _ := reference.WithName("foo/bar") + sourceImageName, _ := reference.WithName("foo/source") driver := testdriver.New() registry, err := NewRegistry(ctx, driver, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableDelete, EnableRedirect) if err != nil { @@ -518,7 +518,7 @@ func TestBlobMount(t *testing.T) { // TestLayerUploadZeroLength uploads zero-length func TestLayerUploadZeroLength(t *testing.T) { ctx := context.Background() - imageName, _ := reference.ParseNamed("foo/bar") + imageName, _ := reference.WithName("foo/bar") driver := testdriver.New() registry, err := NewRegistry(ctx, driver, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableDelete, EnableRedirect) if err != nil { @@ -530,7 +530,7 @@ func TestLayerUploadZeroLength(t *testing.T) { } bs := repository.Blobs(ctx) - simpleUpload(t, bs, []byte{}, digest.DigestSha256EmptyTar) + simpleUpload(t, bs, []byte{}, digestSha256Empty) } func simpleUpload(t *testing.T, bs distribution.BlobIngester, blob []byte, expectedDigest digest.Digest) { diff --git a/vendor/github.com/docker/distribution/registry/storage/blobserver.go b/vendor/github.com/docker/distribution/registry/storage/blobserver.go index 2655e0113..739bf3cb3 100644 --- a/vendor/github.com/docker/distribution/registry/storage/blobserver.go +++ b/vendor/github.com/docker/distribution/registry/storage/blobserver.go @@ -7,8 +7,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // TODO(stevvooe): This should configurable in the future. diff --git a/vendor/github.com/docker/distribution/registry/storage/blobstore.go b/vendor/github.com/docker/distribution/registry/storage/blobstore.go index 4274cc9e8..9f9071ca6 100644 --- a/vendor/github.com/docker/distribution/registry/storage/blobstore.go +++ b/vendor/github.com/docker/distribution/registry/storage/blobstore.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // blobStore implements the read side of the blob store interface over a @@ -145,7 +145,7 @@ func (bs *blobStore) readlink(ctx context.Context, path string) (digest.Digest, return "", err } - linked, err := digest.ParseDigest(string(content)) + linked, err := digest.Parse(string(content)) if err != nil { return "", err } diff --git a/vendor/github.com/docker/distribution/registry/storage/blobwriter.go b/vendor/github.com/docker/distribution/registry/storage/blobwriter.go index 668a6fc9b..d51e27ad3 100644 --- a/vendor/github.com/docker/distribution/registry/storage/blobwriter.go +++ b/vendor/github.com/docker/distribution/registry/storage/blobwriter.go @@ -10,14 +10,19 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) var ( errResumableDigestNotAvailable = errors.New("resumable digest not available") ) +const ( + // digestSha256Empty is the canonical sha256 digest of empty data + digestSha256Empty = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +) + // blobWriter is used to control the various aspects of resumable // blob upload. type blobWriter struct { @@ -234,12 +239,8 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri // paths. We may be able to make the size-based check a stronger // guarantee, so this may be defensive. if !verified { - digester := digest.Canonical.New() - - digestVerifier, err := digest.NewDigestVerifier(desc.Digest) - if err != nil { - return distribution.Descriptor{}, err - } + digester := digest.Canonical.Digester() + verifier := desc.Digest.Verifier() // Read the file from the backend driver and validate it. fr, err := newFileReader(ctx, bw.driver, bw.path, desc.Size) @@ -250,12 +251,12 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri tr := io.TeeReader(fr, digester.Hash()) - if _, err := io.Copy(digestVerifier, tr); err != nil { + if _, err := io.Copy(verifier, tr); err != nil { return distribution.Descriptor{}, err } canonical = digester.Digest() - verified = digestVerifier.Verified() + verified = verifier.Verified() } } @@ -313,7 +314,7 @@ func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor // If no data was received, we may not actually have a file on disk. Check // the size here and write a zero-length file to blobPath if this is the // case. For the most part, this should only ever happen with zero-length - // tars. + // blobs. if _, err := bw.blobStore.driver.Stat(ctx, bw.path); err != nil { switch err := err.(type) { case storagedriver.PathNotFoundError: @@ -321,8 +322,8 @@ func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor // get a hash, then the underlying file is deleted, we risk moving // a zero-length blob into a nonzero-length blob location. To // prevent this horrid thing, we employ the hack of only allowing - // to this happen for the digest of an empty tar. - if desc.Digest == digest.DigestSha256EmptyTar { + // to this happen for the digest of an empty blob. + if desc.Digest == digestSha256Empty { return bw.blobStore.driver.PutContent(ctx, blobPath, []byte{}) } diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go b/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go index a563c02a1..0bbd52957 100644 --- a/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go +++ b/vendor/github.com/docker/distribution/registry/storage/cache/cachecheck/suite.go @@ -6,8 +6,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/cache" + "github.com/opencontainers/go-digest" ) // CheckBlobDescriptorCache takes a cache implementation through a common set diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go b/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go index 94ca8a90c..f647616bc 100644 --- a/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go +++ b/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go @@ -2,7 +2,7 @@ package cache import ( "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" "github.com/docker/distribution" ) diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go b/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go index cf125e187..b2fcaf4e8 100644 --- a/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go +++ b/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache" + "github.com/opencontainers/go-digest" ) type inMemoryBlobDescriptorCacheProvider struct { @@ -26,7 +26,7 @@ func NewInMemoryBlobDescriptorCacheProvider() cache.BlobDescriptorCacheProvider } func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { - if _, err := reference.ParseNamed(repo); err != nil { + if _, err := reference.ParseNormalizedNamed(repo); err != nil { return nil, err } diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go b/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go index cb264b098..5a5819ac7 100644 --- a/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go +++ b/vendor/github.com/docker/distribution/registry/storage/cache/redis/redis.go @@ -5,10 +5,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache" "github.com/garyburd/redigo/redis" + "github.com/opencontainers/go-digest" ) // redisBlobStatService provides an implementation of @@ -41,7 +41,7 @@ func NewRedisBlobDescriptorCacheProvider(pool *redis.Pool) cache.BlobDescriptorC // RepositoryScoped returns the scoped cache. func (rbds *redisBlobDescriptorService) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) { - if _, err := reference.ParseNamed(repo); err != nil { + if _, err := reference.ParseNormalizedNamed(repo); err != nil { return nil, err } diff --git a/vendor/github.com/docker/distribution/registry/storage/catalog_test.go b/vendor/github.com/docker/distribution/registry/storage/catalog_test.go index c69c0cdc1..90dc12cec 100644 --- a/vendor/github.com/docker/distribution/registry/storage/catalog_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/catalog_test.go @@ -8,12 +8,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" + "github.com/opencontainers/go-digest" ) type setupEnv struct { @@ -68,7 +68,7 @@ func setupFS(t *testing.T) *setupEnv { } func makeRepo(ctx context.Context, t *testing.T, name string, reg distribution.Namespace) { - named, err := reference.ParseNamed(name) + named, err := reference.WithName(name) if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/docker/distribution/digest/digester_resumable_test.go b/vendor/github.com/docker/distribution/registry/storage/digester_resumable_test.go similarity index 83% rename from vendor/github.com/docker/distribution/digest/digester_resumable_test.go rename to vendor/github.com/docker/distribution/registry/storage/digester_resumable_test.go index 6ba21c801..54ece3c48 100644 --- a/vendor/github.com/docker/distribution/digest/digester_resumable_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/digester_resumable_test.go @@ -1,10 +1,11 @@ // +build !noresumabledigest -package digest +package storage import ( "testing" + digest "github.com/opencontainers/go-digest" "github.com/stevvooe/resumable" _ "github.com/stevvooe/resumable/sha256" ) @@ -13,7 +14,7 @@ import ( // is exposed through the digester type, which is just a hash plus a Digest // method. func TestResumableDetection(t *testing.T) { - d := Canonical.New() + d := digest.Canonical.Digester() if _, ok := d.Hash().(resumable.Hash); !ok { t.Fatalf("expected digester to implement resumable.Hash: %#v, %v", d, d.Hash()) diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/azure/azure.go b/vendor/github.com/docker/distribution/registry/storage/driver/azure/azure.go index 930b76a17..45d2b1e5c 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/azure/azure.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/azure/azure.go @@ -86,7 +86,8 @@ func New(accountName, accountKey, container, realm string) (*Driver, error) { blobClient := api.GetBlobService() // Create registry container - if _, err = blobClient.CreateContainerIfNotExists(container, azure.ContainerAccessTypePrivate); err != nil { + containerRef := blobClient.GetContainerReference(container) + if _, err = containerRef.CreateIfNotExists(); err != nil { return nil, err } @@ -117,19 +118,33 @@ func (d *driver) GetContent(ctx context.Context, path string) ([]byte, error) { // PutContent stores the []byte content at a location designated by "path". func (d *driver) PutContent(ctx context.Context, path string, contents []byte) error { - if _, err := d.client.DeleteBlobIfExists(d.container, path, nil); err != nil { - return err + if limit := 64 * 1024 * 1024; len(contents) > limit { // max size for block blobs uploaded via single "Put Blob" + return fmt.Errorf("uploading %d bytes with PutContent is not supported; limit: %d bytes", len(contents), limit) } - writer, err := d.Writer(ctx, path, false) - if err != nil { - return err + + // Historically, blobs uploaded via PutContent used to be of type AppendBlob + // (https://github.com/docker/distribution/pull/1438). We can't replace + // these blobs atomically via a single "Put Blob" operation without + // deleting them first. Once we detect they are BlockBlob type, we can + // overwrite them with an atomically "Put Blob" operation. + // + // While we delete the blob and create a new one, there will be a small + // window of inconsistency and if the Put Blob fails, we may end up with + // losing the existing data while migrating it to BlockBlob type. However, + // expectation is the clients pushing will be retrying when they get an error + // response. + props, err := d.client.GetBlobProperties(d.container, path) + if err != nil && !is404(err) { + return fmt.Errorf("failed to get blob properties: %v", err) } - defer writer.Close() - _, err = writer.Write(contents) - if err != nil { - return err + if err == nil && props.BlobType != azure.BlobTypeBlock { + if err := d.client.DeleteBlob(d.container, path, nil); err != nil { + return fmt.Errorf("failed to delete legacy blob (%s): %v", props.BlobType, err) + } } - return writer.Commit() + + r := bytes.NewReader(contents) + return d.client.CreateBlockBlobFromReader(d.container, path, uint64(len(contents)), r, nil) } // Reader retrieves an io.ReadCloser for the content stored at "path" with a @@ -223,7 +238,9 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo, if !strings.HasSuffix(virtContainerPath, "/") { virtContainerPath += "/" } - blobs, err := d.client.ListBlobs(d.container, azure.ListBlobsParameters{ + + containerRef := d.client.GetContainerReference(d.container) + blobs, err := containerRef.ListBlobs(azure.ListBlobsParameters{ Prefix: virtContainerPath, MaxResults: 1, }) @@ -360,8 +377,9 @@ func (d *driver) listBlobs(container, virtPath string) ([]string, error) { out := []string{} marker := "" + containerRef := d.client.GetContainerReference(d.container) for { - resp, err := d.client.ListBlobs(d.container, azure.ListBlobsParameters{ + resp, err := containerRef.ListBlobs(azure.ListBlobsParameters{ Marker: marker, Prefix: virtPath, }) diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator.go b/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator.go index 185160a4b..1e929f836 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator.go @@ -38,11 +38,7 @@ func (r *regulator) enter() { func (r *regulator) exit() { r.L.Lock() - // We only need to signal to a waiting FS operation if we're already at the - // limit of threads used - if r.available == 0 { - r.Signal() - } + r.Signal() r.available++ r.L.Unlock() } diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator_test.go b/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator_test.go new file mode 100644 index 000000000..e4c0ad586 --- /dev/null +++ b/vendor/github.com/docker/distribution/registry/storage/driver/base/regulator_test.go @@ -0,0 +1,67 @@ +package base + +import ( + "sync" + "testing" + "time" +) + +func TestRegulatorEnterExit(t *testing.T) { + const limit = 500 + + r := NewRegulator(nil, limit).(*regulator) + + for try := 0; try < 50; try++ { + run := make(chan struct{}) + + var firstGroupReady sync.WaitGroup + var firstGroupDone sync.WaitGroup + firstGroupReady.Add(limit) + firstGroupDone.Add(limit) + for i := 0; i < limit; i++ { + go func() { + r.enter() + firstGroupReady.Done() + <-run + r.exit() + firstGroupDone.Done() + }() + } + firstGroupReady.Wait() + + // now we exhausted all the limit, let's run a little bit more + var secondGroupReady sync.WaitGroup + var secondGroupDone sync.WaitGroup + for i := 0; i < 50; i++ { + secondGroupReady.Add(1) + secondGroupDone.Add(1) + go func() { + secondGroupReady.Done() + r.enter() + r.exit() + secondGroupDone.Done() + }() + } + secondGroupReady.Wait() + + // allow the first group to return resources + close(run) + + done := make(chan struct{}) + go func() { + secondGroupDone.Wait() + close(done) + }() + select { + case <-done: + case <-time.After(5 * time.Second): + t.Fatal("some r.enter() are still locked") + } + + firstGroupDone.Wait() + + if r.available != limit { + t.Fatalf("r.available: got %d, want %d", r.available, limit) + } + } +} diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/oss/oss.go b/vendor/github.com/docker/distribution/registry/storage/driver/oss/oss.go index 4d215928b..9797f42d0 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/oss/oss.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/oss/oss.go @@ -351,7 +351,8 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) { prefix = "/" } - listResponse, err := d.Bucket.List(d.ossPath(path), "/", "", listMax) + ossPath := d.ossPath(path) + listResponse, err := d.Bucket.List(ossPath, "/", "", listMax) if err != nil { return nil, parseError(opath, err) } @@ -369,7 +370,7 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) { } if listResponse.IsTruncated { - listResponse, err = d.Bucket.List(d.ossPath(path), "/", listResponse.NextMarker, listMax) + listResponse, err = d.Bucket.List(ossPath, "/", listResponse.NextMarker, listMax) if err != nil { return nil, err } @@ -378,6 +379,11 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) { } } + // This is to cover for the cases when the first key equal to ossPath. + if len(files) > 0 && files[0] == strings.Replace(ossPath, d.ossPath(""), prefix, 1) { + files = files[1:] + } + if opath != "/" { if len(files) == 0 && len(directories) == 0 { // Treat empty response as missing directory, since we don't actually diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3.go b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3.go index c9d19c46c..19407d807 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3.go @@ -98,6 +98,7 @@ type DriverParameters struct { StorageClass string UserAgent string ObjectACL string + SessionToken string } func init() { @@ -107,7 +108,9 @@ func init() { "us-west-1", "us-west-2", "eu-west-1", + "eu-west-2", "eu-central-1", + "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", @@ -115,6 +118,7 @@ func init() { "sa-east-1", "cn-north-1", "us-gov-west-1", + "ca-central-1", } { validRegions[region] = struct{}{} } @@ -328,6 +332,8 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { objectACL = objectACLString } + sessionToken := "" + params := DriverParameters{ fmt.Sprint(accessKey), fmt.Sprint(secretKey), @@ -346,6 +352,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { storageClass, fmt.Sprint(userAgent), objectACL, + fmt.Sprint(sessionToken), } return New(params) @@ -395,6 +402,7 @@ func New(params DriverParameters) (*Driver, error) { Value: credentials.Value{ AccessKeyID: params.AccessKey, SecretAccessKey: params.SecretKey, + SessionToken: params.SessionToken, }, }, &credentials.EnvProvider{}, @@ -698,15 +706,11 @@ func (d *driver) copy(ctx context.Context, sourcePath string, destPath string) e return nil } - // Even in the worst case, a multipart copy should take no more - // than a few minutes, so 30 minutes is very conservative. - expires := time.Now().Add(time.Duration(30) * time.Minute) createResp, err := d.S3.CreateMultipartUpload(&s3.CreateMultipartUploadInput{ Bucket: aws.String(d.Bucket), Key: aws.String(d.s3Path(destPath)), ContentType: d.getContentType(), ACL: d.getACL(), - Expires: aws.Time(expires), SSEKMSKeyId: d.getSSEKMSKeyID(), ServerSideEncryption: d.getEncryptionMode(), StorageClass: d.getStorageClass(), diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_test.go b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_test.go index eb7ee5195..363a22eb4 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_test.go @@ -36,6 +36,7 @@ func init() { objectACL := os.Getenv("S3_OBJECT_ACL") root, err := ioutil.TempDir("", "driver-") regionEndpoint := os.Getenv("REGION_ENDPOINT") + sessionToken := os.Getenv("AWS_SESSION_TOKEN") if err != nil { panic(err) } @@ -84,6 +85,7 @@ func init() { storageClass, driverName + "-test", objectACL, + sessionToken, } return New(parameters) diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_v2_signer.go b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_v2_signer.go index 7cabe07e2..cb8010874 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_v2_signer.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/s3-aws/s3_v2_signer.go @@ -137,6 +137,9 @@ func (v2 *signer) Sign() error { host, canonicalPath := parsedURL.Host, parsedURL.Path v2.Request.Header["Host"] = []string{host} v2.Request.Header["date"] = []string{v2.Time.In(time.UTC).Format(time.RFC1123)} + if credValue.SessionToken != "" { + v2.Request.Header["x-amz-security-token"] = []string{credValue.SessionToken} + } smap = make(map[string]string) for k, v := range headers { diff --git a/vendor/github.com/docker/distribution/registry/storage/driver/s3-goamz/s3.go b/vendor/github.com/docker/distribution/registry/storage/driver/s3-goamz/s3.go index 33751c168..b16ca49a7 100644 --- a/vendor/github.com/docker/distribution/registry/storage/driver/s3-goamz/s3.go +++ b/vendor/github.com/docker/distribution/registry/storage/driver/s3-goamz/s3.go @@ -266,10 +266,8 @@ func New(params DriverParameters) (*Driver, error) { if params.V4Auth { s3obj.Signature = aws.V4Signature - } else { - if params.Region.Name == "eu-central-1" { - return nil, fmt.Errorf("The eu-central-1 region only works with v4 authentication") - } + } else if mustV4Auth(params.Region.Name) { + return nil, fmt.Errorf("The %s region only works with v4 authentication", params.Region.Name) } bucket := s3obj.Bucket(params.Bucket) @@ -443,14 +441,14 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) { directories = append(directories, strings.Replace(commonPrefix[0:len(commonPrefix)-1], d.s3Path(""), prefix, 1)) } - if listResponse.IsTruncated { - listResponse, err = d.Bucket.List(d.s3Path(path), "/", listResponse.NextMarker, listMax) - if err != nil { - return nil, err - } - } else { + if !listResponse.IsTruncated { break } + + listResponse, err = d.Bucket.List(d.s3Path(path), "/", listResponse.NextMarker, listMax) + if err != nil { + return nil, err + } } if opath != "/" { @@ -557,11 +555,6 @@ func parseError(path string, err error) error { return err } -func hasCode(err error, code string) bool { - s3err, ok := err.(*aws.Error) - return ok && s3err.Code == code -} - func (d *driver) getOptions() s3.Options { return s3.Options{ SSE: d.Encrypt, @@ -573,6 +566,17 @@ func getPermissions() s3.ACL { return s3.Private } +// mustV4Auth checks whether must use v4 auth in specific region. +// Please see documentation at http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html +func mustV4Auth(region string) bool { + switch region { + case "eu-central-1", "cn-north-1", "us-east-2", + "ca-central-1", "ap-south-1", "ap-northeast-2", "eu-west-2": + return true + } + return false +} + func (d *driver) getContentType() string { return "application/octet-stream" } diff --git a/vendor/github.com/docker/distribution/registry/storage/filereader_test.go b/vendor/github.com/docker/distribution/registry/storage/filereader_test.go index 5926020cc..e522d6056 100644 --- a/vendor/github.com/docker/distribution/registry/storage/filereader_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/filereader_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver/inmemory" + "github.com/opencontainers/go-digest" ) func TestSimpleRead(t *testing.T) { @@ -41,11 +41,7 @@ func TestSimpleRead(t *testing.T) { t.Fatalf("error allocating file reader: %v", err) } - verifier, err := digest.NewDigestVerifier(dgst) - if err != nil { - t.Fatalf("error getting digest verifier: %s", err) - } - + verifier := dgst.Verifier() io.Copy(verifier, fr) if !verifier.Verified() { diff --git a/vendor/github.com/docker/distribution/registry/storage/garbagecollect.go b/vendor/github.com/docker/distribution/registry/storage/garbagecollect.go index 7cf0298e1..392898933 100644 --- a/vendor/github.com/docker/distribution/registry/storage/garbagecollect.go +++ b/vendor/github.com/docker/distribution/registry/storage/garbagecollect.go @@ -5,9 +5,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) func emit(format string, a ...interface{}) { @@ -27,7 +27,7 @@ func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, regis emit(repoName) var err error - named, err := reference.ParseNamed(repoName) + named, err := reference.WithName(repoName) if err != nil { return fmt.Errorf("failed to parse repo name %s: %v", repoName, err) } diff --git a/vendor/github.com/docker/distribution/registry/storage/garbagecollect_test.go b/vendor/github.com/docker/distribution/registry/storage/garbagecollect_test.go index 925f1a10f..2e36fddb0 100644 --- a/vendor/github.com/docker/distribution/registry/storage/garbagecollect_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/garbagecollect_test.go @@ -7,12 +7,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type image struct { @@ -39,7 +39,7 @@ func makeRepository(t *testing.T, registry distribution.Namespace, name string) ctx := context.Background() // Initialize a dummy repository - named, err := reference.ParseNamed(name) + named, err := reference.WithName(name) if err != nil { t.Fatalf("Failed to parse name %s: %v", name, err) } diff --git a/vendor/github.com/docker/distribution/registry/storage/linkedblobstore.go b/vendor/github.com/docker/distribution/registry/storage/linkedblobstore.go index 6a5e8d033..a1929eed3 100644 --- a/vendor/github.com/docker/distribution/registry/storage/linkedblobstore.go +++ b/vendor/github.com/docker/distribution/registry/storage/linkedblobstore.go @@ -8,10 +8,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/storage/driver" "github.com/docker/distribution/uuid" + "github.com/opencontainers/go-digest" ) // linkPathFunc describes a function that can resolve a link based on the @@ -321,7 +321,7 @@ func (lbs *linkedBlobStore) newBlobUpload(ctx context.Context, uuid, path string blobStore: lbs, id: uuid, startedAt: startedAt, - digester: digest.Canonical.New(), + digester: digest.Canonical.Digester(), fileWriter: fw, driver: lbs.driver, path: path, diff --git a/vendor/github.com/docker/distribution/registry/storage/linkedblobstore_test.go b/vendor/github.com/docker/distribution/registry/storage/linkedblobstore_test.go index f0f63d87b..a059a7781 100644 --- a/vendor/github.com/docker/distribution/registry/storage/linkedblobstore_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/linkedblobstore_test.go @@ -9,14 +9,14 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" "github.com/docker/distribution/reference" "github.com/docker/distribution/testutil" ) func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) { - fooRepoName, _ := reference.ParseNamed("nm/foo") + fooRepoName, _ := reference.WithName("nm/foo") fooEnv := newManifestStoreTestEnv(t, fooRepoName, "thetag") ctx := context.Background() stats, err := mockRegistry(t, fooEnv.registry) @@ -54,7 +54,7 @@ func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) { } // create another repository nm/bar - barRepoName, _ := reference.ParseNamed("nm/bar") + barRepoName, _ := reference.WithName("nm/bar") barRepo, err := fooEnv.registry.Repository(ctx, barRepoName) if err != nil { t.Fatalf("unexpected error getting repo: %v", err) @@ -94,7 +94,7 @@ func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) { clearStats(stats) // create yet another repository nm/baz - bazRepoName, _ := reference.ParseNamed("nm/baz") + bazRepoName, _ := reference.WithName("nm/baz") bazRepo, err := fooEnv.registry.Repository(ctx, bazRepoName) if err != nil { t.Fatalf("unexpected error getting repo: %v", err) diff --git a/vendor/github.com/docker/distribution/registry/storage/manifestlisthandler.go b/vendor/github.com/docker/distribution/registry/storage/manifestlisthandler.go index e24062cd0..aee73b85f 100644 --- a/vendor/github.com/docker/distribution/registry/storage/manifestlisthandler.go +++ b/vendor/github.com/docker/distribution/registry/storage/manifestlisthandler.go @@ -6,8 +6,8 @@ import ( "encoding/json" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/manifestlist" + "github.com/opencontainers/go-digest" ) // manifestListHandler is a ManifestHandler that covers schema2 manifest lists. diff --git a/vendor/github.com/docker/distribution/registry/storage/manifeststore.go b/vendor/github.com/docker/distribution/registry/storage/manifeststore.go index 9e8065bb7..4cca5157a 100644 --- a/vendor/github.com/docker/distribution/registry/storage/manifeststore.go +++ b/vendor/github.com/docker/distribution/registry/storage/manifeststore.go @@ -6,11 +6,11 @@ import ( "encoding/json" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" + "github.com/opencontainers/go-digest" ) // A ManifestHandler gets and puts manifests of a particular type. diff --git a/vendor/github.com/docker/distribution/registry/storage/manifeststore_test.go b/vendor/github.com/docker/distribution/registry/storage/manifeststore_test.go index cbd30c044..e398058be 100644 --- a/vendor/github.com/docker/distribution/registry/storage/manifeststore_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/manifeststore_test.go @@ -8,7 +8,6 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" @@ -17,6 +16,7 @@ import ( "github.com/docker/distribution/registry/storage/driver/inmemory" "github.com/docker/distribution/testutil" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) type manifestStoreTestEnv struct { @@ -60,7 +60,7 @@ func TestManifestStorage(t *testing.T) { } func testManifestStorage(t *testing.T, options ...RegistryOption) { - repoName, _ := reference.ParseNamed("foo/bar") + repoName, _ := reference.WithName("foo/bar") env := newManifestStoreTestEnv(t, repoName, "thetag", options...) ctx := context.Background() ms, err := env.repository.Manifests(ctx) diff --git a/vendor/github.com/docker/distribution/registry/storage/paths.go b/vendor/github.com/docker/distribution/registry/storage/paths.go index 1b142b88f..b6d9b9b56 100644 --- a/vendor/github.com/docker/distribution/registry/storage/paths.go +++ b/vendor/github.com/docker/distribution/registry/storage/paths.go @@ -5,7 +5,7 @@ import ( "path" "strings" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) const ( diff --git a/vendor/github.com/docker/distribution/registry/storage/paths_test.go b/vendor/github.com/docker/distribution/registry/storage/paths_test.go index f739552aa..677a34b9f 100644 --- a/vendor/github.com/docker/distribution/registry/storage/paths_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/paths_test.go @@ -3,7 +3,7 @@ package storage import ( "testing" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) func TestPathMapper(t *testing.T) { diff --git a/vendor/github.com/docker/distribution/registry/storage/purgeuploads.go b/vendor/github.com/docker/distribution/registry/storage/purgeuploads.go index 7576b189c..925b1ae9b 100644 --- a/vendor/github.com/docker/distribution/registry/storage/purgeuploads.go +++ b/vendor/github.com/docker/distribution/registry/storage/purgeuploads.go @@ -80,7 +80,7 @@ func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriv } - uuid, isContainingDir := uUIDFromPath(filePath) + uuid, isContainingDir := uuidFromPath(filePath) if uuid == "" { // Cannot reliably delete return nil @@ -111,10 +111,10 @@ func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriv return uploads, errors } -// uUIDFromPath extracts the upload UUID from a given path +// uuidFromPath extracts the upload UUID from a given path // If the UUID is the last path component, this is the containing // directory for all upload files -func uUIDFromPath(path string) (string, bool) { +func uuidFromPath(path string) (string, bool) { components := strings.Split(path, "/") for i := len(components) - 1; i >= 0; i-- { if u, err := uuid.Parse(components[i]); err == nil { diff --git a/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler.go b/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler.go index 9fe71bb4d..05c53254f 100644 --- a/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler.go +++ b/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler.go @@ -8,9 +8,9 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" + "github.com/opencontainers/go-digest" ) var ( diff --git a/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler_test.go b/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler_test.go index 5051fa3de..6536f9d3c 100644 --- a/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/schema2manifesthandler_test.go @@ -20,7 +20,7 @@ func TestVerifyManifestForeignLayer(t *testing.T) { repo := makeRepository(t, registry, "test") manifestService := makeManifestService(t, repo) - config, err := repo.Blobs(ctx).Put(ctx, schema2.MediaTypeConfig, nil) + config, err := repo.Blobs(ctx).Put(ctx, schema2.MediaTypeImageConfig, nil) if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/docker/distribution/registry/storage/signedmanifesthandler.go b/vendor/github.com/docker/distribution/registry/storage/signedmanifesthandler.go index 30d330824..6ca1c6c8c 100644 --- a/vendor/github.com/docker/distribution/registry/storage/signedmanifesthandler.go +++ b/vendor/github.com/docker/distribution/registry/storage/signedmanifesthandler.go @@ -6,10 +6,10 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // signedManifestHandler is a ManifestHandler that covers schema1 manifests. It diff --git a/vendor/github.com/docker/distribution/registry/storage/tagstore.go b/vendor/github.com/docker/distribution/registry/storage/tagstore.go index 4386ffcac..d73278869 100644 --- a/vendor/github.com/docker/distribution/registry/storage/tagstore.go +++ b/vendor/github.com/docker/distribution/registry/storage/tagstore.go @@ -5,8 +5,8 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) var _ distribution.TagService = &tagStore{} diff --git a/vendor/github.com/docker/distribution/registry/storage/tagstore_test.go b/vendor/github.com/docker/distribution/registry/storage/tagstore_test.go index 554a46bf7..396441eec 100644 --- a/vendor/github.com/docker/distribution/registry/storage/tagstore_test.go +++ b/vendor/github.com/docker/distribution/registry/storage/tagstore_test.go @@ -22,7 +22,7 @@ func testTagStore(t *testing.T) *tagsTestEnv { t.Fatal(err) } - repoRef, _ := reference.ParseNamed("a/b") + repoRef, _ := reference.WithName("a/b") repo, err := reg.Repository(ctx, repoRef) if err != nil { t.Fatal(err) diff --git a/vendor/github.com/docker/distribution/registry/storage/vacuum.go b/vendor/github.com/docker/distribution/registry/storage/vacuum.go index 3bdfebf27..42c8ef605 100644 --- a/vendor/github.com/docker/distribution/registry/storage/vacuum.go +++ b/vendor/github.com/docker/distribution/registry/storage/vacuum.go @@ -4,8 +4,8 @@ import ( "path" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/registry/storage/driver" + "github.com/opencontainers/go-digest" ) // vacuum contains functions for cleaning up repositories and blobs @@ -29,7 +29,7 @@ type Vacuum struct { // RemoveBlob removes a blob from the filesystem func (v Vacuum) RemoveBlob(dgst string) error { - d, err := digest.ParseDigest(dgst) + d, err := digest.Parse(dgst) if err != nil { return err } diff --git a/vendor/github.com/docker/distribution/testutil/manifests.go b/vendor/github.com/docker/distribution/testutil/manifests.go index c4f9fef53..8afe82e48 100644 --- a/vendor/github.com/docker/distribution/testutil/manifests.go +++ b/vendor/github.com/docker/distribution/testutil/manifests.go @@ -5,12 +5,12 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/docker/libtrust" + "github.com/opencontainers/go-digest" ) // MakeManifestList constructs a manifest list out of a list of manifest digests @@ -73,7 +73,7 @@ func MakeSchema1Manifest(digests []digest.Digest) (distribution.Manifest, error) func MakeSchema2Manifest(repository distribution.Repository, digests []digest.Digest) (distribution.Manifest, error) { ctx := context.Background() blobStore := repository.Blobs(ctx) - builder := schema2.NewManifestBuilder(blobStore, []byte{}) + builder := schema2.NewManifestBuilder(blobStore, schema2.MediaTypeImageConfig, []byte{}) for _, digest := range digests { builder.AppendReference(distribution.Descriptor{Digest: digest}) } diff --git a/vendor/github.com/docker/distribution/testutil/tarfile.go b/vendor/github.com/docker/distribution/testutil/tarfile.go index a8ba01553..cb93602f3 100644 --- a/vendor/github.com/docker/distribution/testutil/tarfile.go +++ b/vendor/github.com/docker/distribution/testutil/tarfile.go @@ -10,7 +10,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/digest" + "github.com/opencontainers/go-digest" ) // CreateRandomTarFile creates a random tarfile, returning it as an diff --git a/vendor/github.com/docker/distribution/vendor.conf b/vendor/github.com/docker/distribution/vendor.conf new file mode 100644 index 000000000..2af461111 --- /dev/null +++ b/vendor/github.com/docker/distribution/vendor.conf @@ -0,0 +1,43 @@ +github.com/Azure/azure-sdk-for-go 088007b3b08cc02b27f2eadfdcd870958460ce7e +github.com/Azure/go-autorest ec5f4903f77ed9927ac95b19ab8e44ada64c1356 +github.com/Sirupsen/logrus d26492970760ca5d33129d2d799e34be5c4782eb +github.com/aws/aws-sdk-go c6fc52983ea2375810aa38ddb5370e9cdf611716 +github.com/bshuster-repo/logrus-logstash-hook 5f729f2fb50a301153cae84ff5c58981d51c095a +github.com/bugsnag/bugsnag-go b1d153021fcd90ca3f080db36bec96dc690fb274 +github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702 +github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782 +github.com/denverdino/aliyungo afedced274aa9a7fcdd47ac97018f0f8db4e5de2 +github.com/dgrijalva/jwt-go a601269ab70c205d26370c16f7c81e9017c14e04 +github.com/docker/goamz f0a21f5b2e12f83a505ecf79b633bb2035cf6f85 +github.com/docker/libtrust fa567046d9b14f6aa788882a950d69651d230b21 +github.com/garyburd/redigo 535138d7bcd717d6531c701ef5933d98b1866257 +github.com/go-ini/ini 2ba15ac2dc9cdf88c110ec2dc0ced7fa45f5678c +github.com/golang/protobuf 8d92cf5fc15a4382f8964b08e1f42a75c0591aa3 +github.com/gorilla/context 14f550f51af52180c2eefed15e5fd18d63c0a64a +github.com/gorilla/handlers 60c7bfde3e33c201519a200a4507a158cc03a17b +github.com/gorilla/mux 599cba5e7b6137d46ddf58fb1765f5d928e69604 +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d +github.com/miekg/dns 271c58e0c14f552178ea321a545ff9af38930f39 +github.com/mitchellh/mapstructure 482a9fd5fa83e8c4e7817413b80f3eb8feec03ef +github.com/ncw/swift b964f2ca856aac39885e258ad25aec08d5f64ee6 +github.com/spf13/cobra 312092086bed4968099259622145a0c9ae280064 +github.com/spf13/pflag 5644820622454e71517561946e3d94b9f9db6842 +github.com/stevvooe/resumable 2aaf90b2ceea5072cb503ef2a620b08ff3119870 +github.com/xenolf/lego a9d8cec0e6563575e5868a005359ac97911b5985 +github.com/yvasiyarov/go-metrics 57bccd1ccd43f94bb17fdd8bf3007059b802f85e +github.com/yvasiyarov/gorelic a9bba5b9ab508a086f9a12b8c51fab68478e2128 +github.com/yvasiyarov/newrelic_platform_go b21fdbd4370f3717f3bbd2bf41c223bc273068e6 +golang.org/x/crypto c10c31b5e94b6f7a0283272dc2bb27163dcea24b +golang.org/x/net 4876518f9e71663000c348837735820161a42df7 +golang.org/x/oauth2 045497edb6234273d67dbc25da3f2ddbc4c4cacf +golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb +google.golang.org/api 9bf6e6e569ff057f75d9604a46c52928f17d2b54 +google.golang.org/appengine 12d5545dc1cfa6047a286d5e853841b6471f4c19 +google.golang.org/cloud 975617b05ea8a58727e6c1a06b6161ff4185a9f2 +google.golang.org/grpc d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994 +gopkg.in/check.v1 64131543e7896d5bcc6bd5a76287eb75ea96c673 +gopkg.in/square/go-jose.v1 40d457b439244b546f023d056628e5184136899b +gopkg.in/yaml.v2 bef53efd0c76e49e6de55ead051f886bea7e9420 +rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git +github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb