Compare commits

..

460 commits

Author SHA1 Message Date
Arko Dasgupta
f5cdc24dd3
Merge pull request #3245 from olegburov/reopen-pr-2973
Reopen PR #2973 (Support ECS TaskRole in S3 storage driver).
2020-10-28 17:30:56 -07:00
olegburov
34f1322664 Fix hardcoded credential provides.
Signed-off-by: olegburov <oleg.burov@outlook.com>
2020-09-02 17:32:34 -07:00
Manish Tomar
2800ab0224
Merge pull request #2973 from redmatter/support-ecs-instance-profile-in-s3-driver
Support ECS TaskRole in S3 storage driver
2020-08-26 15:24:20 -07:00
Manish Tomar
5dc1f65acc
Merge pull request #3224 from AndreasHassing/fix/bad-pointer-windows-EnableVirtualTerminalProcessing
Update logrus to v1.6.0, fixes #3223
2020-08-24 15:04:52 -07:00
Manish Tomar
fe1ffa86bc
Merge pull request #3226 from thaJeztah/bump_go_digest
vendor: opencontainers/go-digest v1.0.0
2020-08-24 10:50:21 -07:00
Sebastiaan van Stijn
8a8d91529d
vendor: opencontainers/go-digest v1.0.0
full diff: https://github.com/opencontainers/go-digest/compare/v1.0.0-rc1...v1.0.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-08-24 18:46:53 +02:00
Andreas Hassing
9466dd4e5a Update logrus to v1.6.0
Fixes #3223 by bumping logrus to v1.6.0, which in turn bumps
github.com/konsorten/go-windows-terminal-sequences to v1.0.3
wherein the fix to bad pointer is found.

Signed-off-by: Andreas Hassing <andreas@famhassing.dk>
2020-08-24 13:14:04 +02:00
Manish Tomar
0316f34bf2
Merge pull request #3118 from lawliet89/bump-aws-sdk
Bump AWS SDK to v1.34.9
2020-08-21 15:57:08 -07:00
Yong Wen Chua
e1464fd317
Bump AWS SDK
Fixes https://github.com/docker/distribution/issues/3097

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
2020-08-21 17:35:24 +08:00
Derek McGowan
35b26def43
Merge pull request #3173 from adamwg/catalog-no-layers-upstream
catalog: List repositories with no unique layers
2020-08-07 23:12:18 -07:00
Adam Wolfe Gordon
a784441b62 catalog: List repositories with no unique layers
A repository need not contain any unique layers, if its images use only layers
mounted from other repositories. But, the catalog endpoint was looking for the
_layers directory to indicate that a directory was a repository.

Use the _manifests directory as the marker instead, since any repository with
revisions will contain a _manifests directory.

Signed-off-by: Adam Wolfe Gordon <awg@digitalocean.com>
2020-08-04 11:38:49 -06:00
Manish Tomar
1d0ea8ed7b
Merge pull request #3140 from linux-on-ibm-z/travis-s390x
Add s390x support for travis
2020-07-30 16:15:55 -07:00
Derek McGowan
208d68bd5c
Merge pull request #3209 from zhipengzuo/master
clean up code because err is always nil
2020-07-22 09:18:06 -07:00
zhipengzuo
f361d443b7 clean up code because err is always nil
Signed-off-by: zhipengzuo <zuozhipeng@baidu.com>
2020-07-22 10:54:46 +08:00
Derek McGowan
53e18a9d9b
Merge pull request #3196 from thaJeztah/add_redirect
docs: add redirect for old URL
2020-07-08 16:08:24 -07:00
Sebastiaan van Stijn
7728c5e445
docs: add redirect for old URL
Looks like there's some projects refering to this old URL:
https://grep.app/search?q=https%3A//docs.docker.com/reference/api/registry_api/

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-07-08 12:18:31 +02:00
Andrew Bulford
9690d843fa Support ECS TaskRole in S3 storage driver
Instead of constructing the list of credential providers manually, if we
use the default list we can take advantage of the AWS SDK checking the
environment and returning either the EC2RoleProvider or the generic HTTP
credentials provider, configured to use the ECS credentials endpoint.

Also, use the `defaults.Config()` function instead of `aws.NewConfig()`,
as this results in an initialised HTTP client which prevents a fatal
error when retrieving credentials from the ECS credentials endpoint.

Fixes #2960

Signed-off-by: Andrew Bulford <andrew.bulford@redmatter.com>
2020-07-01 08:42:56 +01:00
Sebastiaan van Stijn
62d0fd45e7
Merge pull request #3187 from bloodorangeio/fix-ci
Fix CI failures, upgrade to Go 1.14+
2020-06-29 19:14:34 +02:00
jdolitsky
81ba770eff Fix CI failures, upgrade to Go 1.14+
- Modify Travis manifest to use Go 1.14.x
- Hardcode version of golangci-lint in setup script
- Hardcode version of go-md2man in setup script

Signed-off-by: jdolitsky <393494+jdolitsky@users.noreply.github.com>
2020-06-26 10:59:50 -05:00
srajmane
a2ed1b5e80 Added dist: bionic, updated go version to 1.14.x and set GO111MODULE=on
Signed-off-by: Snehal Rajmane <srajmane@us.ibm.com>
2020-04-29 03:25:24 -07:00
srajmane
55f88c35b9 Adding s390x support.
Signed-off-by: Snehal Rajmane <srajmane@us.ibm.com>
2020-04-07 07:59:19 -07:00
Derek McGowan
742aab907b
Merge pull request #3127 from dmage/err-shadow
Fix err shadowing in gcs driver
2020-03-19 10:36:57 -07:00
Derek McGowan
17a394f9af
Merge pull request #3128 from dmcgowan/gosimple-fix
Fix gosimple checks
2020-03-18 16:06:17 -07:00
Derek McGowan
78c2ab6646
Fix gosimple checks
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-18 15:52:34 -07:00
Oleg Bulatov
cdb4ba947a
Fix err shadowing in gcs driver
Signed-off-by: Oleg Bulatov <oleg@bulatov.me>
2020-03-18 11:41:34 +01:00
Derek McGowan
303f1899bb
Merge pull request #3121 from wy65701436/upgrade-oci-library
Update oci library
2020-03-10 14:58:43 -07:00
wang yan
bf56f348be Update oci library
1, update go-digest to v1.0.0-rc1
2, update image-spec to v1.0.1

Signed-off-by: wang yan <wangyan@vmware.com>
2020-03-10 23:19:29 +08:00
Derek McGowan
581be91482
Merge pull request #3113 from dmcgowan/upstream-redis-fixes
Redis cache fixes and metrics
2020-03-09 13:36:53 -07:00
Derek McGowan
be29c05a1e
Remove deprecated cache metrics code
The metrics tracker in cached blob statter was replaced with prometheus
metrics and no longer needed.
Remove unused log wrapping.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-09 13:11:54 -07:00
Derek McGowan
495a4af7cf
Fix goimports
Separate fix for cherry-picked code

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 17:51:37 -08:00
Grant Watters
74d442a058
Consider redis.ErrNil as distribution.ErrBlobUnknown for Stat HGET
* Update redis.go

If the dgst key does not exist in the cache when calling HGET, `redis.String` will return an `ErrNil` which we need to translate into `distribution.ErrBlobUnknown` so that the error being returned can be properly handled. This will ensure that `SetDescriptor` is properly called from `cachedBlobStatter::Stat` for `repositoryScopedRedisBlobDescriptorService` which will update the redis cache and be considered as a Miss rather than an Error.

cc @manishtomar

* Update suite.go

Add unit test to ensure missing blobs for scoped repo properly return ErrBlobUnknown when HGET returns redis.ErrNil.

(cherry picked from commit dca6b9526a1d30dd218a9f321c4f84ecc4b5e62e)
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 17:51:37 -08:00
Manish Tomar
795892662b
redis metrics
* redis metrics

it is working but metrics are not very useful since default buckets
start from 5ms and almost all of them are in that range.

* remove extra comment

(cherry picked from commit ba1a1d74e7eb047dd1056548ccf0695e8846782c)
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 17:51:37 -08:00
Manish Tomar
ce101280fe
fix redis caching issue
* fix redis caching issue

earlier redis cache was updated when there was any error including any
temporary connectivity issue. This would trigger set calls which would
further increase load and possibly connectivity errors from redis
leaving the system with continuous errors and high latency. Now the
cache is updated only when it is genuine cache miss. Other errors do not
trigger a cache update.

* add back tracker Hit() and Miss() calls

*squashed commits*
(cherry picked from commit 6f3e1c10260ef59ba4e9c42e939329fad9fdd8c3)
(cherry picked from commit 6738ff3320cf82cc2df919a95a1bde2f7789a501)

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 17:51:37 -08:00
Derek McGowan
4c7c63b557
Add cache unit test
Test base functionality of the cache statter

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 17:51:37 -08:00
Derek McGowan
492a10376c
Merge pull request #3111 from dmcgowan/update-report-issues
Update reporting issues guidelines
2020-03-04 14:39:19 -08:00
Derek McGowan
c79aa81772
Merge pull request #2550 from halcyonCorsair/halcyonCorsair/use-go-events-1
Use go-events package
2020-03-04 14:38:15 -08:00
Elliot Pahl
800cb95821
Use go-events package
TBD: Queue not converted yet

Signed-off-by: Elliot Pahl <elliot.pahl@gmail.com>
2020-03-04 12:49:32 -08:00
Derek McGowan
2d1126ecc1
Merge pull request #3080 from thaJeztah/bump_go_metrics
vendor: update docker/go-metrics v0.0.1
2020-03-04 10:21:48 -08:00
Derek McGowan
3b4d1e3ddf
Merge pull request #3110 from dmcgowan/update-maintainers
Update governance and maintainers
2020-03-04 10:19:46 -08:00
Derek McGowan
1e25ecefe4
Update governance and maintainers
Update format of governance and bring in language from containerd.
Update maintainers to reflect active maintainers.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-04 10:04:38 -08:00
Derek McGowan
db3c418ada
Update reporting issues guidelines
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-03-03 16:56:46 -08:00
Sebastiaan van Stijn
98dcc5195e
vendor: update docker/go-metrics v0.0.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-03-02 20:14:15 +01:00
Derek McGowan
6b972e50fe
Merge pull request #2272 from naveedjamil/fips
Increase Unit Test Code Coverage
2020-02-22 17:40:41 -08:00
Derek McGowan
e65b3f1316
Fix CI for test updates
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2020-02-22 17:27:55 -08:00
Naveed Jamil
efdba4f210
Increase Unit Test Code Coverage
Unit test coverge was increased to cover the usages of crypto. This helps to ensure that everything is working fine with fips mode enabled.
Also updated sha1 to sha256 in registry/storage/driver/testsuites/testsuites.go because sha1 is not supported in fips mode.

Signed-off-by: Naveed Jamil <naveed.jamil@tenpearl.com>
2020-02-22 17:09:00 -08:00
Derek McGowan
e9a023180f
Merge pull request #3071 from dmcgowan/update-readme-docs
Update readme and contributing docs
2020-02-22 16:58:53 -08:00
Derek McGowan
f1cb8a56c8
Merge pull request #3105 from thaJeztah/bump_golang_1.13.8
Update Golang 1.13.8
2020-02-22 16:54:49 -08:00
Derek McGowan
bfa6b923e7
Merge pull request #3020 from kd7lxl/updatefrequency
Fix typo cloudfront updatefrenquency
2020-02-22 16:54:03 -08:00
Derek McGowan
f593b8d975
Merge pull request #2446 from legionus/docker-configuration-ptr
Fix the pointer initialization
2020-02-22 16:42:17 -08:00
Sebastiaan van Stijn
1f77c9a57f
Update Golang 1.13.8
full diff: https://github.com/golang/go/compare/go1.13.7...go1.13.8

go1.13.8 (released 2020/02/12) includes fixes to the runtime, the crypto/x509,
and net/http packages. See the Go 1.13.8 milestone on the issue tracker for details.

https://github.com/golang/go/issues?q=milestone%3AGo1.13.8+label%3ACherryPickApproved

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-22 17:59:03 +01:00
Derek McGowan
861aa2a621
Merge pull request #3089 from thaJeztah/bump_golang_1.13.7
Update Golang 1.13.7, golang.org/x/crypto (CVE-2020-0601, CVE-2020-7919)
2020-02-21 18:08:27 -08:00
Sebastiaan van Stijn
9b6a019081
prevent dev-tools from updating go.mod
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-21 23:47:14 +01:00
Sebastiaan van Stijn
7e290869e7
vendor: update golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d (CVE-2020-7919)
Includes 69ecbb4d6d
(forward-port of 8b5121be2f),
which fixes CVE-2020-7919:

- Panic in crypto/x509 certificate parsing and golang.org/x/crypto/cryptobyte
  On 32-bit architectures, a malformed input to crypto/x509 or the ASN.1 parsing
  functions of golang.org/x/crypto/cryptobyte can lead to a panic.
  The malformed certificate can be delivered via a crypto/tls connection to a
  client, or to a server that accepts client certificates. net/http clients can
  be made to crash by an HTTPS server, while net/http servers that accept client
  certificates will recover the panic and are unaffected.
  Thanks to Project Wycheproof for providing the test cases that led to the
  discovery of this issue. The issue is CVE-2020-7919 and Go issue golang.org/issue/36837.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-21 23:45:56 +01:00
Sebastiaan van Stijn
016549532f
Dockerfile: use alpine 3.11
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-21 23:45:54 +01:00
Sebastiaan van Stijn
974375f66c
re-vendor with go 1.13
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-21 23:45:52 +01:00
Sebastiaan van Stijn
4ae059c714
Update Golang 1.13.7 (CVE-2020-0601, CVE-2020-7919)
full diff: https://github.com/golang/go/compare/go1.13.4...go1.13.7

go1.13.7 (released 2020/01/28) includes two security fixes. One mitigates
the CVE-2020-0601 certificate verification bypass on Windows. The other affects
only 32-bit architectures.

https://github.com/golang/go/issues?q=milestone%3AGo1.13.7+label%3ACherryPickApproved

- X.509 certificate validation bypass on Windows 10
  A Windows vulnerability allows attackers to spoof valid certificate chains when
  the system root store is in use. These releases include a mitigation for Go
  applications, but it’s strongly recommended that affected users install the
  Windows security update to protect their system.
  This issue is CVE-2020-0601 and Go issue golang.org/issue/36834.
- Panic in crypto/x509 certificate parsing and golang.org/x/crypto/cryptobyte
  On 32-bit architectures, a malformed input to crypto/x509 or the ASN.1 parsing
  functions of golang.org/x/crypto/cryptobyte can lead to a panic.
  The malformed certificate can be delivered via a crypto/tls connection to a
  client, or to a server that accepts client certificates. net/http clients can
  be made to crash by an HTTPS server, while net/http servers that accept client
  certificates will recover the panic and are unaffected.
  Thanks to Project Wycheproof for providing the test cases that led to the
  discovery of this issue. The issue is CVE-2020-7919 and Go issue golang.org/issue/36837.
  This is also fixed in version v0.0.0-20200124225646-8b5121be2f68 of golang.org/x/crypto/cryptobyte.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-21 23:45:49 +01:00
Derek McGowan
d054b13dc3
Merge pull request #3086 from thaJeztah/forward_port_ISS-2819
[master] Use same env var in Dockerfile and Makefile
2020-02-21 10:24:25 -08:00
Derek McGowan
244d5246c2
Merge pull request #3023 from sayboras/feature/golangci-lint
Migrate to golangci-lint
2020-02-21 10:21:15 -08:00
sayboras
66809646d9 Migrate to golangci-lint
Signed-off-by: Tam Mach <sayboras@yahoo.com>
2020-02-14 08:11:16 +11:00
Ryan Abrams
23f6bdd743
Use same env var in Dockerfile and Makefile
Ensures that build tags get set in the Dockerfile so that OSS and GCS drivers
are built into the official registry binary.

Closes #2819

Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
(cherry picked from commit bf74e4f91d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-22 10:54:02 +01:00
Derek McGowan
a837179414
Merge pull request #3072 from fermayo/fix-TestRegistryAsCacheMutationAPIs
Fix TestRegistryAsCacheMutationAPIs
2019-12-15 20:48:56 -08:00
Fernando Mayo Fernandez
6ca7b9e9fa
Fix TestRegistryAsCacheMutationAPIs
Use a synthetic upstream registry when creating the testing mirror configuration
to avoid the test fail when trying to reach http://example.com

Signed-off-by: Fernando Mayo Fernandez <fernando@undefinedlabs.com>
2019-12-15 13:51:25 +01:00
Derek McGowan
f5e84a4939
Update readme and contributing docs
Update project details to align more closely with community
updates in OCI and containerd.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2019-12-13 17:20:45 -08:00
Tom Hayward
0f5e2753a6 Fix typo cloudfront updatefrenquency
Signed-off-by: Tom Hayward <thayward@infoblox.com>
2019-12-13 12:11:42 -08:00
Derek McGowan
bdf3438b52
Merge pull request #2985 from novas0x2a/default-transport
make it possible to wrap the client transport in another one
2019-12-13 11:36:12 -08:00
Derek McGowan
29c300c106
Merge pull request #3050 from ducksecops/patch-1
bump golang to 1.13.4
2019-12-13 11:09:05 -08:00
Derek McGowan
4798651387
Merge pull request #3053 from adrian-plata/table-fix
Fixing broken table
2019-12-13 11:08:00 -08:00
Derek McGowan
f18781257e
Merge pull request #3061 from guillaumerose/reconciliate
Add pathspec for repo _layers directory and allow Repository.BlobStore to enumerate over blobs
2019-12-06 11:27:13 -08:00
Guillaume Rose
c9c3324300 Add unit tests for BlobEnumerator
Signed-off-by: Guillaume Rose <guillaume.rose@docker.com>
2019-12-06 09:38:13 +01:00
Manish Tomar
5538da4923 fixes to make layersPathSpec work
Signed-off-by: Guillaume Rose <guillaume.rose@docker.com>
2019-12-05 20:48:33 +01:00
Manish Tomar
fa7d949408 allow Repository.BlobStore to enumerate over blobs
Signed-off-by: Guillaume Rose <guillaume.rose@docker.com>
2019-12-05 20:48:33 +01:00
Manish Tomar
cf77113795 add pathspec for repo _layers directory
Signed-off-by: Guillaume Rose <guillaume.rose@docker.com>
2019-12-05 20:48:33 +01:00
Adrian Plata
b4694b0d2d Fixing broken table
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
2019-11-26 17:38:40 -08:00
ducksecops
070cc010f7 bump golang to 1.13.4
Signed-off-by: Daniel Sutton <daniel@ducksecops.uk>
2019-11-13 23:15:11 +00:00
Derek McGowan
dee21c0394
Merge pull request #2991 from ad-m/patch-1
use latest version of alpine when building the Docker container
2019-10-24 15:54:08 -07:00
Ryan Abrams
ae2e973db9
Merge pull request #2748 from manishtomar/tag-digests
API to retrive tag's digests
2019-10-08 12:14:56 -07:00
Ryan Abrams
14b96e55d8
Merge pull request #3003 from laverya/fix-build-badges
use travis, not circle, build badge
2019-09-05 08:29:32 -07:00
Ryan Abrams
f656e60de5
Merge pull request #2984 from bouk/rempo
registry: Fix typo in RepositoryRemover warning
2019-09-05 08:23:18 -07:00
Ryan Abrams
740d4d1211
Merge pull request #2918 from dmathieu/test-blob-writer-write
Test httpBlobUpload.Write method
2019-09-05 08:16:36 -07:00
Andrew Lavery
cc97b94f5d
use travis, not circle, build badge
Signed-off-by: Andrew Lavery <laverya@umich.edu>
2019-09-04 15:38:24 -07:00
Derek McGowan
aeaeb84407
Merge pull request #3000 from adrian-plata/master
Adding deprecated schema instructions
2019-09-03 11:54:37 -07:00
Adrian Plata
07a50201c9 Adding deprecated schema instructions
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
2019-09-03 11:44:28 -07:00
Bouke van der Bijl
1c481d34d9 registry: Fix typo in RepositoryRemover warning
Signed-off-by: Bouke van der Bijl <me@bou.ke>
2019-09-02 16:07:34 +00:00
Adam Dobrawy
a994bb839d use latest version of alpine when building the Docker container
Signed-off-by: Adam Dobrawy <naczelnik@jawnosc.tk>
2019-08-30 00:58:36 +02:00
Mike Lundy
c486db2d71
make it possible to wrap the client transport in another one
Signed-off-by: Mike Lundy <mike@fluffypenguin.org>
2019-08-22 17:37:47 -04:00
Ryan Abrams
1fb7fffdb2
Merge pull request #2950 from terinjokes/patches/swift-segment-hash
swift: correct segment path generation
2019-07-11 15:35:31 -07:00
Ryan Abrams
10f726344d
Merge pull request #2955 from alex-laties/master
allow for VERSION and REVISION to be passed in during docker builds
2019-07-11 15:30:23 -07:00
Ryan Abrams
8063102951
Merge pull request #2917 from dmathieu/repository-blob-resume
Implement Repository Blobs upload resuming
2019-07-11 15:28:05 -07:00
Derek McGowan
438b67feef
Merge pull request #2947 from tariq1890/update_versions
Update the versions of several dependencies
2019-07-08 13:33:36 -07:00
Ryan Abrams
be07be9904
Merge pull request #2522 from tifayuki/notification_metrics
Add notification metrics
2019-06-28 11:10:51 -07:00
Alex Laties
92d213d2c1 allow for VERSION and REVISION to be passed in during docker builds
Signed-off-by: Alex Laties <agl@tumblr.com>
2019-06-26 18:06:51 -04:00
Damien Mathieu
dd3bdee21c implement Repository Blobs upload resuming
Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-26 09:46:49 +02:00
Ryan Abrams
90dfea7952
Merge pull request #2921 from dmathieu/repository-serve-blob
Implement Repository ServeBlob
2019-06-25 19:07:38 -07:00
Ryan Abrams
6c72ec2e85
Merge pull request #2927 from dmathieu/blob-create-uuid
Handle Blob Create when the underlying registry doesn't provide 'Docker-Upload-UUID'
2019-06-25 19:06:46 -07:00
Ryan Abrams
ec84b86013
Merge pull request #2930 from dmathieu/extract-blob-resume
Extract blob upload resume into its own method
2019-06-25 19:06:16 -07:00
Damien Mathieu
898b1f2a53 test httpBlobUpload.Write method
Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:32:58 +02:00
Damien Mathieu
c5d5f938e3 fast-stop ServeBlob if we're doing a HEAD request
A registry pointing to ECR is having issues if we try loading the blob

Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:30:22 +02:00
Damien Mathieu
3800c47fd2 Implement Repository ServeBlob
Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:30:22 +02:00
Damien Mathieu
a45e5cb13f handle create blob if the uuid couldn't be retrieved from headers or URL
Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:29:38 +02:00
Damien Mathieu
8b31a894bd deduce blob UUID from location if it wasn't provided in the headers
Some registries (ECR) don't provide a `Docker-Upload-UUID` when creating
a blob. So we can't rely on that header. Fallback to reading it from the
URL.

Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:29:38 +02:00
Damien Mathieu
94097512db extract blob upload resume into its own method
I've found this logic being in a single method to be quite hard to get.
I believe extracting it makes it easier to read, as we can then more
easily see what the main method does and possibly ignore the intricacies
of `ResumeBlobUpload`.

Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-06-25 09:25:56 +02:00
Terin Stock
b23dd1ef37 swift: correct segment path generation
When uploading segments to Swift, the registry generates a random file,
by taking the hash of the container path and 32-bytes of random data.
The registry attempts to shard across multiple directory paths, by
taking the first three hex characters as leader.

The implementation in registry, unfortunately, takes the hash of
nothing, and appends it to the path and random data. This results in all
segments being created in one directory.

Fixes: #2407
Fixes: #2311
Signed-off-by: Terin Stock <terinjokes@gmail.com>
2019-06-22 23:44:43 -07:00
Ryan Abrams
79f6bcbe16
Merge pull request #2946 from tariq1890/upd_alpine
use latest version of alpine when building the Docker container
2019-06-20 10:38:41 -07:00
Tariq Ibrahim
afe29bb697
update the golang compiler version and the versions of several dependencies
Signed-off-by: Tariq Ibrahim <tariq181290@gmail.com>
2019-06-19 22:43:52 -07:00
Tariq Ibrahim
45b2d0498d
use latest version of alpine when building the Docker container
Signed-off-by: Tariq Ibrahim <tariq181290@gmail.com>
2019-06-19 22:21:07 -07:00
Ryan Abrams
84f47e7bb3
Merge pull request #2900 from sevki/no-token-err-fix
fix no error returned in fetchTokenWithOAuth
2019-06-19 19:16:18 -07:00
Ryan Abrams
6c329e56a2
Merge pull request #2920 from dmathieu/blob_writer_offset
Append the written bytes to the blob writer's size
2019-06-19 19:14:49 -07:00
Ryan Abrams
71309e96e4
Merge pull request #2809 from andyzhangx/ssl
change default Dockerfile to install ssl utils
2019-06-19 19:14:14 -07:00
Ryan Abrams
0c394fdd84
Merge pull request #2861 from yuwaMSFT2/master
Fixes #2835 Process Accept header MIME types in case-insensitive way
2019-06-19 19:09:29 -07:00
Ryan Abrams
d80a17d8e0
Merge pull request #2879 from tbe/fix-s3-ceph
Fix s3 driver for supporting ceph radosgw
2019-06-19 19:09:07 -07:00
Ryan Abrams
55287010ce
Merge pull request #2894 from jabrown85/fix-offset-typos
Fix typo: offest -> offset
2019-06-19 19:08:22 -07:00
Ryan Abrams
c2254191d4
Merge pull request #2941 from tariq1890/gomod
migrate to go modules from vndr
2019-06-19 18:41:26 -07:00
Tariq Ibrahim
5223c27422
migrate to go modules from vndr
Signed-off-by: Tariq Ibrahim <tariq181290@gmail.com>
2019-06-19 12:24:07 -07:00
Ryan Abrams
dcfe05ce6c
Merge pull request #2926 from tariq1890/no_rsc
replace rsc.io/letsencrypt in favour of golang.org/x/crypto
2019-06-05 15:34:28 -07:00
Tariq Ibrahim
8f9c8094fb
replace rsc.io/letsencrypt in favour of golang.org/x/crypto
Signed-off-by: Tariq Ibrahim <tariq181290@gmail.com>
2019-06-04 12:04:18 -07:00
Damien Mathieu
0e2d080a8a append the written bytes to the blob writer's size
Any byte written should append to the size. Otherwise, the full Size is
always zero.

Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>
2019-05-09 14:17:58 +02:00
Ryan Abrams
3226863cbc
Merge pull request #2849 from Shawnpku/master
support Alibaba Cloud CDN storage middleware
2019-04-16 18:43:06 -07:00
Sevki Hasirci
5afbf32400 fix no error returned in fetchTokenWithOAuth
fetchTokenWithBasicAuth checks if a token is in the token response
but fetchTokenWithOAuth does not

these changes implements the same behaviour for the latter
returning a `ErrNoToken` if a token is not found in the resposne

Signed-off-by: Sevki Hasirci <sevki@cloudflare.com>
2019-04-14 11:05:59 +01:00
Jesse Brown
74f429a5ad Fix typo: offest -> offset
Signed-off-by: Jesse Brown <jabrown85@gmail.com>
2019-04-05 14:20:20 -05:00
Shawn Chen
51bb5cee5b import alicdn package
Signed-off-by: Shawn Chen <chen8132@gmail.com>
2019-03-19 15:06:02 +08:00
Shawn Chen
fd77cf43a6 change package name & format document
Signed-off-by: Shawn Chen <chen8132@gmail.com>
2019-03-18 11:35:46 +08:00
Thomas Berger
c18c6c33b2 S3 Driver: added comment for missing KeyCount workaround
Signed-off-by: Thomas Berger <loki@lokis-chaos.de>
2019-03-15 21:05:21 +01:00
Eohyung Lee
f877726503 Fix s3 driver for supporting ceph radosgw
Radosgw does not support S3 `GET Bucket` API v2 API but v1.
This API has backward compatibility, so most of this API is working
correctly but we can not get `KeyCount` in v1 API and which is only
for v2 API.

Signed-off-by: Eohyung Lee <liquidnuker@gmail.com>
2019-03-08 12:45:20 +01:00
Ryan Abrams
6d62eb1d4a
Merge pull request #2837 from vishesh92/fix-cloudfront-middleware
Fix cloudfront middleware
2019-03-04 16:42:08 -08:00
Shawn Chen
3390f32aec fix Context issue
Signed-off-by: Shawn Chen <chen8132@gmail.com>
2019-03-04 17:48:32 +08:00
Shawn Chen
ae91d1f429 fix ci issue
Signed-off-by: Shawn Chen <chen8132@gmail.com>
2019-03-04 17:17:57 +08:00
Shawnpku
6e10631d9c fix default cdn auth duration
Signed-off-by: Shawnpku <chen8132@gmail.com>
2019-03-04 14:53:48 +08:00
Vishesh Jindal
e1e72e9563
Fix cloudfront documentation formatting
Signed-off-by: Vishesh Jindal <vishesh92@gmail.com>
2019-03-02 08:58:52 +05:30
Vishesh Jindal
f9a0506191
Bugfix: Make ipfilteredby not required
Signed-off-by: Vishesh Jindal <vishesh92@gmail.com>
2019-03-02 08:58:52 +05:30
Ryan Abrams
d3ddc3572c
Merge pull request #2854 from manishtomar/log-authed-name
Log authorized username
2019-03-01 14:45:43 -08:00
Ryan Abrams
c192a281f8
Merge pull request #2813 from lucab/ups/spec-json-binary
registry: fix binary JSON content-type
2019-03-01 14:26:54 -08:00
Yu Wang
a683c7c235 Fixes #2835 Process Accept header MIME types in case-insensitive way
Use mime.ParseMediaType to parse the media types in Accept header in manifest request. Ignore the failed ones.

Signed-off-by: Yu Wang <yuwa@microsoft.com>
2019-02-21 15:11:41 -08:00
Shawnpku
bbc9885aa2 fix func name
Signed-off-by: Shawnpku <chen8132@gmail.com>
2019-02-20 15:54:21 +08:00
Honglin Feng
92a6436714 rename the metrics label
Signed-off-by: Honglin Feng <tifayuki@gmail.com>
2019-02-17 12:46:10 +08:00
Honglin Feng
d5a615b8c9 update the event number
Signed-off-by: Honglin Feng <tifayuki@gmail.com>
2019-02-15 21:55:17 +08:00
Honglin Feng
09a63caa37 run go fmt and goimports
Signed-off-by: Honglin Feng <tifayuki@gmail.com>
2019-02-15 21:14:57 +08:00
Honglin Feng
228bafca0b run go fmt
Signed-off-by: Honglin Feng <tifayuki@gmail.com>
2019-02-15 21:14:57 +08:00
Honglin Feng
76da6290b0 add label to the metrics
Signed-off-by: Honglin Feng <tifayuki@gmail.com>
2019-02-15 21:14:57 +08:00
tifayuki
8b70616846 Add notification metrics
It adds notification related prometheus metrics, including:
  - total count for events/success/failure/error
  - total count for notification per each status code
  - gauge of the pending notification queue

Signed-off-by: tifayuki <tifayuki@gmail.com>
2019-02-15 21:14:57 +08:00
Manish Tomar
ec6566c02b Log authorized username
This is useful to know which user pulled/pushed which repo.

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2019-02-13 08:49:37 -08:00
Shawnpku
3aa2a282f7 support alicdn middleware
Signed-off-by: Shawnpku <chen8132@gmail.com>
2019-02-11 15:11:26 +08:00
Derek McGowan
0d3efadf01
Merge pull request #2840 from manishtomar/fix-lint
Fix gometalint errors
2019-02-04 16:58:09 -08:00
Manish Tomar
48818fdea7 Remove err nil check
since type checking nil will not panic and return appropriately

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2019-02-04 16:42:44 -08:00
Ryan Abrams
411d6bcfd2
Merge pull request #2786 from thaJeztah/add_normalize_util
Add reference. ParseDockerRef utility function
2019-02-04 16:19:21 -08:00
Manish Tomar
da8db4666b Fix gometalint errors
Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2019-02-04 16:01:04 -08:00
Derek McGowan
b75069ef13
Merge pull request #2791 from AliyunContainerService/support-oss-byok
Support BYOK for OSS storage driver
2019-01-16 16:37:37 -08:00
Ryan Abrams
b1fd12d0c1
Merge pull request #2808 from gregrebholz/feat/tls1.2only
Registry - make minimum TLS version user configurable
2019-01-14 09:31:36 -08:00
Luca Bruno
15b0204758
registry: fix binary JSON content-type
This fixes registry endpoints to return the proper `application/json`
content-type for JSON content, also updating spec examples for that.

As per IETF specification and IANA registry [0], the `application/json`
type is a binary media, so the content-type label does not need any
text-charset selector. Additionally, the media type definition
explicitly states that it has no required nor optional parameters,
which makes the current registry headers non-compliant.

[0]: https://www.iana.org/assignments/media-types/application/json

Signed-off-by: Luca Bruno <lucab@debian.org>
2019-01-14 09:04:42 +00:00
Greg Rebholz
cdb62b2b77 Registry - make minimum TLS version user configurable
Signed-off-by: J. Gregory Rebholz <gregrebholz@gmail.com>
2019-01-11 18:11:03 -05:00
andyzhangx
7df881dcbe change default Dockerfile to install ssl utils
Signed-off-by: andyzhangx <xiazhang@microsoft.com>
2019-01-10 03:56:42 +00:00
Derek McGowan
91b0f0559e
Merge pull request #2801 from caervs/ISS-2793
Add docs for autoredirect config parameter
2019-01-07 10:58:55 -08:00
Derek McGowan
980d1a696b
Merge pull request #2800 from davidswu/autoredirect
default autoredirect to false
2019-01-07 10:26:29 -08:00
Ryan Abrams
d1abdeb623 Add docs for autoredirect config parameter
Config parameter is user facing so should be documented.

Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
2019-01-04 13:11:20 -08:00
Sebastiaan van Stijn
0ac367fd6b
Add reference.ParseDockerRef utility function
ParseDockerRef normalizes the image reference following the docker
convention. This is added mainly for backward compatibility. The reference
returned can only be either tagged or digested. For reference contains both tag
and digest, the function returns digested reference, e.g.

    docker.io/library/busybox:latest@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa

will be returned as

    docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-04 21:26:06 +01:00
David Wu
eb1a2cd911 default autoredirect to false
Signed-off-by: David Wu <david.wu@docker.com>
2019-01-04 11:05:12 -08:00
Li Yi
b7839211af Update doc for BYOK support in OSS storage driver
Change-Id: I195f29195f999e3e14ba921fd3435a6dc4788417
Signed-off-by: Li Yi <denverdino@gmail.com>
2018-12-25 09:32:16 +08:00
Li Yi
90bed67126 Support BYOK for OSS storage driver
Change-Id: I423ad03e63bd38aded3abfcba49079ff2fbb3b74
Signed-off-by: Li Yi <denverdino@gmail.com>
2018-12-25 08:30:40 +08:00
Derek McGowan
40b7b5830a
Merge pull request #2775 from caervs/release_notes_2.7
Release notes for 2.7
2018-12-03 16:05:39 -08:00
Ryan Abrams
08c6bbed05 Release notes for 2.7
Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
2018-11-29 16:35:06 -08:00
Derek McGowan
d9e1218235
Merge pull request #2772 from dmcgowan/add-arm-flag
Add GOARM flag to dockerfile
2018-11-29 15:15:00 -08:00
Derek McGowan
63f6c1205d
Add GOARM flag to dockerfile
When building with arm on alpine, GOARM should
be set to 6 by default.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-11-28 10:40:29 -08:00
Derek McGowan
aa985ba889
Merge pull request #2711 from davidswu/autoredirect
add autoredirect auth config
2018-11-27 15:48:25 -08:00
Derek McGowan
dd36fd3622
Merge pull request #2742 from tescherm/configure-bugsnag-logging
add bugsnag logrus hook
2018-11-27 15:08:17 -08:00
Manish Tomar
1251e51ad0 better name and updated tests
- use ManifestDigests name instead of Indexes
- update tests to validate against multiple tags

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-11-01 10:31:08 -07:00
Manish Tomar
9ebf151ac2 API to retrive tag's digests
Add an interface alongside TagStore that provides API to retreive
digests of all manifests that a tag historically pointed to. It also
includes currently linked tag.

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-10-29 18:19:05 -07:00
Matt Tescher
7c4d584e58 add bugsnag logrus hook
Signed-off-by: Matt Tescher <matthew.tescher@docker.com>
2018-10-25 14:52:10 -07:00
Olivier Gambier
93e082742a
Merge pull request #2734 from mgrachev/patch-1
Fix typo
2018-10-24 10:01:56 -07:00
Olivier Gambier
f7046a6d68
Merge pull request #2735 from tonistiigi/update-dockerfile
update Dockerfile to multi-stage
2018-10-24 10:01:01 -07:00
Grachev Mikhail
cd1648d62c Fix typo
Signed-off-by: Mikhail Grachev <work@mgrachev.com>
2018-10-18 17:54:19 +03:00
Tonis Tiigi
8a800e1292 update Dockerfile to multi-stage
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2018-10-15 15:48:05 -07:00
Olivier Gambier
1cb4180b1a
Merge pull request #2729 from liyongxin/master
typo fix about overridden
2018-10-02 15:04:33 -07:00
Olivier Gambier
451cd548a0
Merge pull request #2731 from mirake/fix-typos
Fix typo: commmand -> command
2018-10-02 15:03:57 -07:00
Rui Cao
6335cc258f Fix typo: commmand -> command
Signed-off-by: Rui Cao <ruicao@alauda.io>
2018-09-29 15:12:10 +08:00
Derek McGowan
17b3ff188d
Merge pull request #2730 from dmcgowan/version-update-2.7.0-rc.0
Update version to 2.7.0-rc.0
2018-09-28 16:17:04 -07:00
Derek McGowan
f08b3486c8
Update version to 2.7.0-rc.0
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-09-28 16:07:56 -07:00
Derek McGowan
f3adfea35b
Merge pull request #2721 from dmcgowan/release-notes-2.7.0-rc
Add release notes for 2.7.0 release candidates
2018-09-27 14:41:04 -07:00
Derek McGowan
e1817db884
Merge pull request #2720 from dmcgowan/update-release-process
Update release documents
2018-09-27 14:32:28 -07:00
Yongxin Li
de8636b78c typo fix about overridden
Signed-off-by: Yongxin Li <yxli@alauda.io>
2018-09-27 20:27:09 +08:00
Derek McGowan
97cb7f35b0
Update release documents
Remove redundant AUTHORS file in favor of relying
on .mailmap for keeping track of author names.
Move older changelogs to release directory.
Move release checklist to releases README.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-09-26 18:30:44 -07:00
Derek McGowan
2eb7a17225
Add 2.7.0-rc release notes
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-09-26 11:15:01 -07:00
Derek McGowan
06a4c2f61b
Update mailmap file
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-09-26 11:15:01 -07:00
Olivier Gambier
d37f816427
Merge pull request #2723 from mirake/fix-typos
Fix some typos
2018-09-25 15:34:16 -07:00
Rui Cao
569d18aef9 Fix some typos
Signed-off-by: Rui Cao <ruicao@alauda.io>
2018-09-24 09:05:44 +08:00
David Wu
2e1e6307dd add autoredirect to option
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-20 19:33:06 -07:00
David Wu
b2bd465760 fix checks
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-20 15:24:27 -07:00
Viktor Stanchev
f730f3ab77 add autoredirect auth config
It redirects the user to to the Host header's domain whenever they try to use
token auth.

Signed-off-by: David Wu <david.wu@docker.com>
2018-09-20 14:47:43 -07:00
Olivier Gambier
16128bbac4
Merge pull request #2707 from davidswu/go-1.11
remove dependencies on resumable
2018-09-20 12:47:44 -07:00
Olivier Gambier
b089e91688
Merge pull request #2712 from liyongxin/master
typo fix from existant to existent
2018-09-13 15:03:39 -07:00
liyongxin
6133840f49 typo fix from existant to existent
Signed-off-by: liyongxin <yxli@alauda.io>
Signed-off-by: Yongxin Li <yxli@alauda.io>
2018-09-13 19:37:13 +08:00
David Wu
a927fbdb9b track digest offset in blobwriter
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-12 14:53:27 -07:00
David Wu
d8bde9b97e remove go 1.9 and 1.10 checks from travis
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-11 16:32:27 -07:00
David Wu
bd41413d57 remove closenotifier
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-11 16:14:10 -07:00
David Wu
166874ade9 fix gofmt and goimports
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-11 16:14:10 -07:00
Derek McGowan
a5c2fdc5b8
Merge pull request #2705 from mirake/fix-typo
Fix some typos
2018-09-11 16:12:22 -07:00
David Wu
9da0f07c92 update travis with go 1.11
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-11 08:22:04 -07:00
David Wu
877d706b38 remove dependencies on resumable
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-11 08:21:27 -07:00
ruicao
d1f36d46c9 Fix some typos
Signed-off-by: ruicao <ruicao@alauda.io>
2018-09-07 18:13:53 +08:00
Derek McGowan
642075f42c
Merge pull request #2631 from whoshuu/feature/improve-gcs-driver
Improve gcs driver
2018-09-05 17:48:03 -07:00
Derek McGowan
15de837aa8
Merge pull request #2704 from dmcgowan/fix-2703
Fix registry stripping newlines from manifests
2018-09-05 17:46:56 -07:00
Huu Nguyen
7a195dd5ca Add back include_gcs build constraint
Signed-off-by: Huu Nguyen <whoshuu@gmail.com>
2018-09-05 15:48:30 -07:00
Huu Nguyen
69299d93d9 Use existing jwtConf instead of creating a scoped one
Signed-off-by: Huu Nguyen <whoshuu@gmail.com>
2018-09-05 15:48:30 -07:00
Tony Holdstock-Brown
f9187b2572 Add regulator to GCS
Signed-off-by: Huu Nguyen <whoshuu@gmail.com>
2018-09-05 15:48:30 -07:00
Andrey Kostov
b424c3d870 Better error handling for GCS credential argument addition
Signed-off-by: Andrey Kostov <kostov.andrey@gmail.com>
2018-09-05 15:48:29 -07:00
Andrey Kostov
3f9f073cef Edit configuration.md to add gcs credentials option
Signed-off-by: Andrey Kostov <kostov.andrey@gmail.com>
2018-09-05 15:48:29 -07:00
Andrey Kostov
78238ef1a0 Add credentials argument for GCS driver
Signed-off-by: Andrey Kostov <kostov.andrey@gmail.com>
2018-09-05 15:48:29 -07:00
Olivier Gambier
efa4c3bb5f
Merge pull request #2702 from caervs/fix_path_enumeration
Ignore missing paths during enumeration
2018-09-05 15:44:52 -07:00
Olivier Gambier
6d66d0367e
Merge pull request #2698 from cquon/swift_vendor
Update ncw/swift Vendor Package
2018-09-05 15:26:25 -07:00
Derek McGowan
c88728f217
Fix registry stripping newlines from manifests
Content must be preserved exactly

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-09-05 13:40:42 -07:00
Ryan Abrams
6b73a9ab89 Ignore missing paths during enumeration
It's possible to run into a race condition in which the enumerator lists
lots of repositories and then starts the long process of enumerating through
them. In that time if someone deletes a repo, the enumerator may error out.

Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
2018-09-05 10:17:08 -07:00
Corey Quon
fd32d5f962
update github.com/ncw/swift package in vendor to v1.0.40
Signed-off-by: Corey Quon <corey.quon@gmail.com>
2018-09-05 00:28:40 -07:00
mlmhl
5a74b806f0
update github.com/ncw/swift package in vendor to avoid potential memory leaks
Signed-off-by: mlmhl <409107750@qq.com>
2018-09-05 00:28:40 -07:00
Olivier Gambier
9930542dc5
Merge pull request #2701 from davidswu/metalinter
fix gometalinter
2018-09-04 19:34:41 -07:00
David Wu
8d7e4cd388 fix goimports and gofmt
Signed-off-by: David Wu <david.wu@docker.com>
2018-09-04 17:45:39 -07:00
Olivier Gambier
90705d2fb8
Merge pull request #2362 from twistlock/populate_htpasswd
Create and populate htpasswd file if missing
2018-08-31 00:25:37 -07:00
Derek McGowan
b12bd4004a
Merge pull request #2639 from andrew-leung/manifesteventlayers
Add configurable layers in manifest events
2018-08-28 16:03:05 -07:00
Derek McGowan
059f301d54
Merge pull request #2685 from manishtomar/mani-graceful-shutdown
Graceful shutdown
2018-08-27 14:24:53 -07:00
Manish Tomar
f95ac7db95 fix doc - thanks @dmp42
Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-24 14:57:26 -07:00
Olivier Gambier
3354cf98e3
Merge pull request #2680 from manishtomar/mani-fix-mem-leak
fix memory leak introduced in PR #2648
2018-08-24 14:35:12 -07:00
Derek McGowan
ef859e1b21
Merge pull request #2474 from vikstrous/disable-v1-master
disable schema1 by default, add a config flag to enable it
2018-08-24 10:58:39 -07:00
Olivier Gambier
90070b3367
Merge pull request #2694 from caervs/fix_nginx_spacing
Replace tab with space in nginx config
2018-08-23 16:08:33 -07:00
Ryan Abrams
0101db11ef Replace tab with space in nginx config
Quick follow-up to #9223. This gives better consistency and readability to the
file.

Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
2018-08-23 16:06:46 -07:00
Olivier Gambier
1300e580d1
Merge pull request #2328 from stepyu/patch-1
Fix the sentence
2018-08-23 16:02:07 -07:00
Olivier Gambier
16eb3b658d
Merge pull request #2368 from monikakatiyar16/patch-1
Added nginx config for uploading large sized blobs
2018-08-23 15:59:47 -07:00
Derek McGowan
02bf4a2887
Merge pull request #2689 from dmp42/reviewers
Add new reviewers
2018-08-20 14:24:02 -07:00
Olivier
610440eb19 Add new reviewers
Signed-off-by: Olivier <o+github@gambier.email>
2018-08-20 12:24:15 -07:00
Olivier
ee94aa48d7
Merge pull request #2690 from dmcgowan/remove-aaron-maintainers
Remove Aaron Lehmann from maintainers file
2018-08-20 12:22:46 -07:00
Olivier
53bd46af5c
Merge pull request #2651 from mikebrow/manifest-version-test-on-put
adds validation testing for schema version values
2018-08-20 12:19:40 -07:00
Olivier
6411087274
Merge pull request #2681 from dmcgowan/update-yaml
Update yaml parser
2018-08-20 12:18:21 -07:00
Derek McGowan
0a302c7fa9
Remove Aaron Lehmann from maintainers file
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-20 11:47:54 -07:00
Derek McGowan
633401c9e8
Merge pull request #2687 from davidswu/remove-region-validation
use aws sdk to validate regions
2018-08-20 11:11:49 -07:00
David Wu
0b0d470281 use aws sdk to validate regions
Signed-off-by: David Wu <david.wu@docker.com>
2018-08-20 11:02:14 -07:00
Andrew Leung
5e4b81a578 Use references terminology instead of layers.
Signed-off-by: Andrew Leung <anwleung@gmail.com>
2018-08-20 10:01:40 -07:00
Manish Tomar
40efb602d6
Add support to gracefully shutdown the server
This is done by draining the connections for configured time after registry receives a SIGTERM signal.
This adds a `draintimeout` setting under `HTTP`. Registry doesn't drain
if draintimeout is not provided.

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-20 10:01:26 -07:00
Derek McGowan
9bf62ca7b3
Merge pull request #2678 from caervs/bump_aws
Bump aws sdk to v1.15.11
2018-08-14 19:07:50 -07:00
Derek McGowan
f0ee5720a5
Update yaml parser
Mark the top level Loglevel field as deprecated

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-14 16:42:36 -07:00
Manish Tomar
13f8189f2a fix memory leak introduced in PR #2648
context.App.repoRemover is single registry instance stored throughout
app run. It was wrapped in another remover when processing each request.
This remover happened to be remover got from previous request. This way
every remover created was stored in infinite linked list causing memory
leak. Fixing it by storing the wrapped remover inside the request context
which will get gced when request context is gced. This was introduced in
PR #2648.

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-14 16:41:45 -07:00
Derek McGowan
94deea2951
Merge pull request #2679 from dmcgowan/revert-bad-vendor-update
Revert "Fixed customer facing grammar and spelling"
2018-08-14 14:59:24 -07:00
Derek McGowan
de21eb6c96
Revert "Fixed customer facing grammar and spelling"
This reverts commit a64394ece5.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-14 14:24:01 -07:00
Ryan Abrams
57212c909b Bump aws sdk to v1.15.11
This is the latest official release for this dependency

Signed-off-by: Ryan Abrams <rdabrams@gmail.com>
2018-08-14 12:56:19 -07:00
Olivier
c0995537be
Merge pull request #2674 from Parth/patch-1
Fixed customer facing grammar and spelling
2018-08-14 12:46:29 -07:00
Mike Brown
2fdb2ac270 adds validation testing for schema version values
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-08-14 08:53:54 -05:00
Parth Mehrotra
a64394ece5 Fixed customer facing grammar and spelling
Indentation is spelled wrong as intendation everywhere the word occurs

Can either be:
> "found a tab character that violates indentation"
or
> "found tab characters that violate indentation"

Signed-off-by: Parth Mehrotra <parth@mehrotra.me>
2018-08-11 12:38:35 -04:00
Derek McGowan
5f37adaa41
Merge pull request #2673 from dmp42/TLS
Remove ciphers that do not support perfect forward secrecy
2018-08-10 16:03:59 -07:00
Derek McGowan
88530ef7a0
Merge pull request #2671 from dmp42/goamz
Remove goamz
2018-08-10 15:54:04 -07:00
Olivier
7d9f067716
Merge pull request #2632 from whoshuu/feature/improve-s3-driver
Improve s3 driver
2018-08-10 15:01:11 -07:00
Olivier
d260b18f2f Remove ciphers that do not support perfect forward secrecy
Signed-off-by: Olivier <o+github@gambier.email>
2018-08-10 14:58:51 -07:00
dmp
9caa7a81bc Remove goamz
Signed-off-by: Olivier <o+github@gambier.email>
2018-08-10 11:11:53 -07:00
Olivier
b7446e89bf
Merge pull request #2599 from legionus/storage-inmemory-deadlock
Fix deadlock in the inmemory storage driver
2018-08-09 15:26:12 -07:00
Olivier
0cbe144826
Merge pull request #2602 from dmage/errmessage
Use e.Message field instead of e.Code.Message()
2018-08-09 15:21:32 -07:00
Olivier
4a75b72fd3
Merge pull request #2662 from dmcgowan/enable-structcheck
Enable static checks
2018-08-07 19:01:38 -07:00
Olivier
dc35ae6421
Merge pull request #2598 from dmcgowan/update-maintainers
Update project maintainers file
2018-08-07 18:59:36 -07:00
Olivier
eefe9670bd
Merge pull request #2661 from dmcgowan/enable-goimports
Enable goimports check
2018-08-07 14:59:49 -07:00
Derek McGowan
003aa051b4
Merge pull request #2648 from manishtomar/tag-deleted-event
add repo and tag deletion event
2018-08-07 11:50:56 -07:00
Derek McGowan
db0a4ec1c8
Enable static checks
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-06 14:49:11 -07:00
Derek McGowan
795e11d5fb
Enable goimports check
Validates that goimports has been run on all files

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-06 14:37:44 -07:00
Derek McGowan
32e2260be2
Enable struct check
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-06 13:55:43 -07:00
Manish Tomar
8c05756141 lint fix
Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-06 09:46:42 -07:00
Olivier
dc53e37d98
Merge pull request #2657 from dmcgowan/add-travis-ci
Update build to use travis
2018-08-05 21:14:54 -07:00
Manish Tomar
e4d5a0a17c Add documentation
Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-03 14:08:00 -07:00
Manish Tomar
8f6758278d take handler update
forgot to commit this earlier

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-02 23:13:37 -07:00
Manish Tomar
328069bb4d add support for repo deleted event also
by having another interface RepositoryRemover that is implemented by
registry instance and is injected in app context for event tracking

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-08-02 23:05:05 -07:00
Derek McGowan
dc49f84dcc
Update build to use travis
Update Makefile targets

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-08-01 16:54:54 -07:00
Andrew Leung
54aef6251e Fix typo in manifestLayers variable name
Signed-off-by: Andrew Leung <anwleung@gmail.com>
2018-07-29 08:01:21 -07:00
Derek McGowan
0dae0957e5
Merge pull request #2076 from mikebrow/ocitype
Adds support for oci manifests and manifestlists
2018-07-20 10:21:23 -07:00
Mike Brown
20aecf1d7b added test for initial oci schema version
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-07-19 19:41:31 -05:00
Mike Brown
5f588fbf9b address review comment regarding panic use
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-07-19 16:07:26 -05:00
Manish Tomar
0d8f4ac7b8 add tag deletion event
whenever a tag is deleted an event is sent out via the regular
notification channels

Signed-off-by: Manish Tomar <manish.tomar@docker.com>
2018-07-18 11:34:09 -07:00
Andrew Leung
276fdce3d9 Add configurable layers in manifest events
Signed-off-by: Andrew Leung <anwleung@gmail.com>
2018-06-27 09:27:24 -07:00
Mike Brown
e8d7941ca6 address lint and gofmt issues
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-25 15:45:15 -05:00
Huu Nguyen
f5c6357c6d Update s3_test to account for SkipVerify parameter
Signed-off-by: Huu Nguyen <whoshuu@gmail.com>
2018-06-22 12:00:28 -07:00
Huu Nguyen
7655a3d91f Add option to skip certificate verification for the s3 driver
Signed-off-by: Huu Nguyen <whoshuu@gmail.com>
2018-06-22 12:00:21 -07:00
Mike Brown
321d636e76 Merge pull request #1 from owtaylor/oci-media-types
Handle OCI manifests and image indexes without a media type

Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-19 11:46:49 -05:00
Owen W. Taylor
132abc6de5 Test storing OCI image manifests and indexes with/without a media type
OCI Image manifests and indexes are supported both with and without
an embeded MediaType (the field is reserved according to the spec).
Test storing and retrieving both types from the manifest store.

Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>
2018-06-19 11:24:25 -04:00
Owen W. Taylor
60d9c5dfad Handle OCI manifests and image indexes without a media type
In the OCI image specification, the MediaType field is reserved
and otherwise undefined; assume that manifests without a media
in storage are OCI images or image indexes, and determine which
by looking at what fields are in the JSON. We do keep a check
that when unmarshalling an OCI image or image index, if it has
a MediaType field, it must match that media type of the upload.

Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>
2018-06-19 11:24:25 -04:00
Owen W. Taylor
1d47ef7b80 Check media types when unmarshalling manifests
When unmarshalling manifests from JSON, check that the MediaType field
corresponds to the type that we are unmarshalling as. This makes sure
that when we retrieve a manifest from the manifest store, it will have
the same type as it was handled as before storing it in the manifest
store.

Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>
2018-06-19 11:24:25 -04:00
Mike Brown
f6224f78ba register oci image index
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 15:18:59 -05:00
Mike Brown
ad7ab0853c folow commit 9c88801a12
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
7b47fb13cf update url policy support; testing for annoations in index
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
f186e1da1c adding some support for annotations at the manifest level
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
ec2aa05cdf addressing comments from stevvooe
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
c1532332ad update to image spec v1.0.0
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
6bae7ca597 refactor adding enum for storage types
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
9e3f78b8c8 addresses minor debug comments
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
b0cef05626 removes oci. namespace feature
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
426afb3a4c address get manifest issue with oci. namespace; and comment descriptions
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
fcaffa38bc vendor oci image-spec
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:55:24 -05:00
Mike Brown
c94f28805e OCI media types; annotation support; oci index
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:48:58 -05:00
Mike Brown
6fcea22b0a add an ocischema manifest handler for the registry
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:48:58 -05:00
Mike Brown
9986e8ca7c adds support for oci manifests and manifestlists
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2018-06-18 13:48:58 -05:00
Derek McGowan
749f6afb45
Merge pull request #2603 from yuwaMSFT2/newazuresdk
closes #2496 and #2552
2018-06-11 11:39:26 -07:00
Yu Wang
62797237b9 closes #2496 and #2552
Update Azure SDK with release v16.2.1
Update Azure autorest SDK with release v10.8.1

Signed-off-by: Yu Wang <yuwa@microsoft.com>
2018-06-08 16:53:02 -07:00
Oleg Bulatov
7bc438a534
Use e.Message field instead of e.Code.Message()
Signed-off-by: Oleg Bulatov <oleg@bulatov.me>
2018-06-04 17:29:46 +02:00
Gladkov Alexey
fc7e8f42d7 Fix deadlock in the inmemory storage driver
According golang documentation [1]: no goroutine should expect to be
able to acquire a read lock until the initial read lock is released.

[1] https://golang.org/pkg/sync/#RWMutex

Signed-off-by: Gladkov Alexey <agladkov@redhat.com>
2018-05-30 18:01:08 +02:00
Derek McGowan
86b030c1ca
Update project maintainers file
Include rules and roles in file.
Remove inactive maintainers who have already acknowledged
leaving the maintainer role.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-05-29 16:02:45 -07:00
Derek McGowan
f0cc927784
Merge pull request #2582 from thaJeztah/bump-golang-1.10
Update Golang to 1.10
2018-05-22 10:56:53 -07:00
Sebastiaan van Stijn
7f02f9e450
Update Golang to 1.10
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-05-22 19:42:22 +02:00
Derek McGowan
ed42a4909a
Merge pull request #2594 from dmcgowan/update-integration-test-certs
Update integration test certificates
2018-05-21 17:01:25 -07:00
Derek McGowan
dabcfdc5a6
Update for vndr update
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-05-21 16:33:38 -07:00
Derek McGowan
b4dd9b4376
Update certificates
Set expiration to 10 years

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2018-05-21 16:00:52 -07:00
Derek McGowan
83389a1480
Merge pull request #2556 from justincormack/fewer-gorillas
Remove gorilla/context from vendor.conf
2018-03-27 13:24:08 -07:00
Justin Cormack
fb7b0ddfc3
Remove gorilla/context from vendor.conf
This has been unused since we switched to Go context.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
2018-03-26 15:46:07 -07:00
Olivier Gambier
23bef416bd
Merge pull request #2538 from tianon/challanges
Fix minor "Challanges" typo
2018-03-21 09:58:14 -07:00
Derek McGowan
607ae5d128
Merge pull request #2501 from xiaonancc77/master
Added ignore event types into notifications
2018-03-14 10:37:02 -07:00
Stephen Day
34c706e759
Merge pull request #2549 from miminar/redis-delete-key
redis: delete right size attribute
2018-03-13 16:12:15 -07:00
Michal Minář
492844e09c redis: delete right size attribute
Signed-off-by: Michal Minář <miminar@redhat.com>
2018-03-13 15:25:32 +01:00
elsanli(李楠)
fc1d3647c6 Added ignore event typs into notifications
Signed-off-by: elsanli(李楠) <elsanli@tencent.com>
2018-03-13 16:00:44 +08:00
Tianon Gravi
f2805894c8 Fix minor "Challanges" typo
Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
2018-03-01 11:25:05 -08:00
Stephen Day
6fca8d6e67
Merge pull request #2535 from xiaods/master
fix out of date cli arg for registry version
2018-02-27 15:34:29 -08:00
Deshi Xiao
8b93700d99 fix out of date cli arg for registry version
Signed-off-by: Deshi Xiao <xiaods@gmail.com>
2018-02-28 06:46:06 +08:00
Stephen Day
6664ec7039
Merge pull request #2466 from tifayuki/prometheus_go_metrics
add prometheus metrics
2018-02-09 15:49:04 -08:00
tifayuki
e3c37a46e2 Add Prometheus Metrics
at the first iteration, only the following metrics are collected:

  - HTTP metrics of each API endpoint
  - cache counter for request/hit/miss
  - histogram of storage actions, including:
    GetContent, PutContent, Stat, List, Move, and Delete

Signed-off-by: tifayuki <tifayuki@gmail.com>
2018-02-09 14:27:51 -08:00
Derek McGowan
13076371a6
Merge pull request #2520 from ywk253100/ignore_path_not_found_error
Ignore path not found error when look up tags
2018-02-09 11:19:52 -08:00
Wenkai Yin
005c6e0236 ignore path not found error when look up tags
Signed-off-by: Wenkai Yin <yinw@vmware.com>
2018-02-08 17:32:25 +08:00
Stephen Day
d707ea2428
Merge pull request #2469 from felixbuenemann/letsencrypt-host-whitelist-support
Let's Encrypt Host Whitelist Support
2018-02-06 16:11:20 -08:00
Stephen J Day
1ba5b3b553
registry/storage: ignore missing tag on delete
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2018-02-06 15:25:51 -08:00
Stephen Day
fea8bd5114
Merge pull request #2471 from GarageDeveloper/master
fixes #2249: sanitize tenant and tenantid
2018-02-02 16:29:34 -08:00
Derek McGowan
85b4d46b4f
Merge pull request #2507 from mistyhacks/fix-storage-driver-link
Fixed broken storage driver link
2018-02-01 13:49:34 -08:00
Felix Bünemann
4ecb17cc4c registry: support whitelisting letsencrypt hosts
This adds a configuration setting `HTTP.TLS.LetsEncrypt.Hosts` which can
be set to a list of hosts that the registry will whitelist for retrieving
certificates from Let's Encrypt. HTTPS connections with SNI hostnames
that are not whitelisted will be closed with an "unknown host" error.
It is required to avoid lots of unsuccessful registrations attempts that
are triggered by malicious clients connecting with bogus SNI hostnames.

NOTE: Due to a bug in the deprecated vendored rsc.io/letsencrypt library
clearing the host list requires deleting or editing of the cachefile to
reset the hosts list to null.

Signed-off-by: Felix Buenemann <felix.buenemann@gmail.com>
2018-02-01 21:16:58 +01:00
Misty Stanley-Jones
a4c32bce50 Fixed broken storage driver link
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
2018-01-25 14:54:50 -08:00
Derek McGowan
5cb406d511
Merge pull request #2455 from sargun/make-walk-faster
s3: improve walk performance
2018-01-19 13:00:03 -08:00
Sargun Dhillon
cbcbcb02c5 Remove old walk function
This removes the old global walk function, and changes all
the code to use the per-driver walk functions.

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
2018-01-18 13:06:07 -08:00
Sargun Dhillon
c7b0da2622 Use the new walk method for catalog enumeration
This change is primarily to make GC faster.

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
2018-01-18 11:58:46 -08:00
Derek McGowan
b5db8eeeb8
Merge pull request #2500 from stevvooe/remove-net-context-vestiges
context, registry/handlers: remove net/context references
2018-01-18 10:26:24 -08:00
Stephen J Day
585cdeb571
context, registry/handlers: remove net/context references
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2018-01-17 16:01:41 -08:00
Sargun Dhillon
35b29a609e Use the New Driver Walk method for catalog enumeration
This changes the Walk Method used for catalog enumeration. Just to show
how much an effect this has on our s3 storage:
Original:
List calls: 6839

real    3m16.636s
user    0m0.000s
sys    0m0.016s

New:
ListObjectsV2 Calls: 1805

real    0m49.970s
user    0m0.008s
sys    0m0.000s

This is because it no longer performs a list and stat per item, and instead
is able to use the metadata gained from the list as a replacement to stat.

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
2018-01-07 22:45:17 -08:00
Sargun Dhillon
32ac467992 Introduce Walk Method Per Storage Driver
Move the Walk types into registry/storage/driver, and add a Walk method to each
storage driver. Although this is yet another API to implement, there is a fall
back implementation that relies on List and Stat. For some filesystems this is
very slow.

Also, this WalkDir Method conforms better do a traditional WalkDir (a la filepath).

This change is in preparation for refactoring.

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
2018-01-07 22:45:17 -08:00
Sargun Dhillon
9f664468ea Upgrade AWS library to v1.12.36
This upgrade, and vendors aws-sdk-go to version v1.12.36.
This is because it has new API calls accessible to the S3 client,
specifically S3.ListObjectsV2PagesWithContext

Signed-off-by: Sargun Dhillon <sargun@sargun.me>
2018-01-07 22:45:17 -08:00
Derek McGowan
277ed486c9
Merge pull request #2302 from zetaab/oma
add possibility to clean untagged manifests
2018-01-05 15:27:52 -08:00
Jesse Haka
ff87ad884c add possibility to clean untagged manifests
add tests

add possibility to clean untagged manifests

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

add dry tests

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove underscores

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

fixes

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

opts struct+use camelcase

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

doublecheck manifest in paths.go

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

add gofmt

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

fix lint

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

add log print

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

move log to dryrun as well

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove counter

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove manifest tag references

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

add tag to tests

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

manifestsWithoutTags -> removeUntagged

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove RemoveManifestTagReferences and use removemanifests

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove comment

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

remove pathfor

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

move removemanifest out of manifestenumerator, it does not work correctly if we delete stuff in it

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

add comment

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

fix context -> dcontext

Signed-off-by: Jesse Haka <haka.jesse@gmail.com>

fix gofmt
2018-01-05 12:20:01 +02:00
Stephen Day
db0bc08b85
Merge pull request #2484 from perlun/patch-1
Update CONTRIBUTING.md
2018-01-02 16:07:18 -08:00
Stephen Day
70c5e31509
Merge pull request #2485 from perlun/patch-2
api.md: Fixed incorrect grammar
2018-01-02 16:06:25 -08:00
Per Lundberg
aac2f6c8b7 api.md: Fixed incorrect grammar
I noted this while reading at https://docs.docker.com/registry/spec/api/

Signed-off-by: Per Lundberg <perlun@gmail.com>
2018-01-02 12:49:31 +02:00
Per Lundberg
eaa90a3c6d Update CONTRIBUTING.md
Fixed the headers. They were rendering incorrectly on GitHub for some weird reason; I copied the strings and rewrote the ## characters at the beginning and now they render as they should.

Signed-off-by: Per Lundberg <per.lundberg@ecraft.com>
2017-12-29 14:41:43 +02:00
Viktor Stanchev
e9864ce8b9 disable schema1 by default, add a config flag to enable it
port of #2473

Signed-off-by: Viktor Stanchev <me@viktorstanchev.com>
2017-12-19 10:23:25 -08:00
Raphaël Enrici
8777e97b72 fixes #2249: sanitize tenant and tenantid
If tenant or tenantid are passed as env variables, we systematically use Sprint to make sure they are string and not integer as it would make mapstructure fail.

Signed-off-by: Raphaël Enrici <raphael@root-42.com>
2017-12-17 18:33:34 +01:00
Derek McGowan
f411848591
Merge pull request #2447 from tifayuki/cloudfront-s3-filter
add s3 region filters for cloudfront
2017-12-07 10:04:35 -08:00
tifayuki
e8ecc6dc55 add s3 region filters for cloudfront
Signed-off-by: tifayuki <tifayuki@gmail.com>
2017-12-01 15:58:58 -08:00
Stephen Day
bc3c7b0525
Merge pull request #2435 from zhouhaibing089/digestset-ut
digestset: refine some words on unit test
2017-11-22 16:42:22 -08:00
Stephen Day
8cedd7b3a4
Merge pull request #2448 from kklin/follow-relative-links
Properly follow relative links when listing tags
2017-11-22 16:38:47 -08:00
Stephen Day
1503fa2109
Merge pull request #2431 from mistyhacks/fix-keywords
Fix keyword format for downstream docs
2017-11-22 16:34:27 -08:00
Monika Katiyar
118c8ee1f1 Added nginx configuration for uploading large sized blobs (layer size) to registry when using nginx as reverse proxy from monikakatiyar16
Signed-off-by: Monika Katiyar <monika@jeavio.com>
2017-11-20 15:17:47 +05:30
Kevin Lin
1bfbeca726 Properly follow relative links when listing tags
The previous code assumed that the link returned when listing tags was
always absolute. However, some registries, such as quay.io, return the
link as a relative link (e.g. the second page for the quay.io/coreos/etcd
image is /v2/coreos/etcd/tags/list?next_page=<truncated>&n=50). Because
the relative link was retrieved directly, the fetch failed (with the
error `unsupported protocol scheme ""`).

Signed-off-by: Kevin Lin <kevin@kelda.io>
2017-11-18 22:04:19 -08:00
Gladkov Alexey
e69837454a Add tests for configuration parser
Signed-off-by: Gladkov Alexey <agladkov@redhat.com>
2017-11-15 17:01:19 +01:00
Gladkov Alexey
c9eba1a5bb Fix the pointer initialization
If the overwriteStruct() finds an uninitialized pointer, it tries to initialize it,
but does it incorrectly. It tries to assign a pointer to pointer, instead of pointer.

Signed-off-by: Gladkov Alexey <agladkov@redhat.com>
2017-11-14 15:32:05 +01:00
gbarr01
e5b5e44386 Revert "Add text about win os version ordering"
This reverts commit 1a860d8c19.
2017-11-09 14:49:04 -08:00
gbarr01
1a860d8c19
Add text about win os version ordering 2017-11-09 14:15:00 -08:00
Liron Levin
c785740af7 Create and populate htpasswd file if missing
If htpasswd authentication option is configured but the htpasswd file is
missing, populate it with a default user and automatically generated
password.
The password will be printed to stdout.

Signed-off-by: Liron Levin <liron@twistlock.com>
2017-11-01 12:30:25 +02:00
zhouhaibing089
f74613907d digestset: refine some words on unit test
1. when lookup an entry which is missing, it should say NotFound.
2. when add duplicated entry, the entries size should be increased.
3. when add entry which has different algorithm, it should be allowed.

Signed-off-by: zhouhaibing089 <zhouhaibing089@gmail.com>
2017-10-31 16:33:36 +08:00
Misty Stanley-Jones
fda42e5ef9 Fix keyword format for downstream docs
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
2017-10-24 15:26:28 -07:00
Stephen Day
3800056b88 Merge pull request #2428 from zhouhaibing089/algo-import
cmd/digest: import crypto algorithms
2017-10-23 10:07:44 +02:00
zhouhaibing089
d66208108d cmd/digest: import crypto algorithms
the digest cli does not work if we do not import this two packages,
tested in go1.9. basically, we have to make several algorithms to
be available by calling crypto.RegisterHash in init functions.

Signed-off-by: zhouhaibing089 <zhouhaibing089@gmail.com>
2017-10-14 12:36:55 +08:00
Derek McGowan
7484e51bf6 Merge pull request #2402 from smarterclayton/order_manifest
Allow clients to request specific manifest media types
2017-10-11 10:17:12 -07:00
Clayton Coleman
3c5f85abd1
Allow clients to request specific manifest media types
The current registry/client sends the registered manifest types in
random order. Allow clients to request a single specific manifest type
or a preferred order as per the HTTP spec.

Signed-off-by: Clayton Coleman <ccoleman@redhat.com>
2017-10-03 17:06:11 -04:00
Derek McGowan
bb49a1685d Merge pull request #2416 from stevvooe/feed-the-linter
registry: feed the linter by removing redundant err check
2017-09-29 13:51:02 -07:00
Stephen J Day
4abf680c76
registry: feed the linter by removing redundant err check
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-09-29 13:27:49 -07:00
Derek McGowan
8710fa58ae Merge pull request #2377 from stevvooe/healthcheck-storage-ignore-notfound
registry/handlers: ignore notfound on storage driver healthcheck
2017-09-29 13:14:15 -07:00
Derek McGowan
5db89f0ca6 Merge pull request #2388 from tiborvass/remove-misused-context
Remove context in NewRegistry and NewRepository
2017-09-05 13:44:47 -07:00
Tibor Vass
13e0608bc8 gofmt -w -s registry/client/repository.go
Signed-off-by: Tibor Vass <teabee89@gmail.com>
2017-09-05 13:14:43 -07:00
Tibor Vass
2c58ce1a7f Remove context in NewRegistry and NewRepository
The context parameter was either not used or misused.

Signed-off-by: Tibor Vass <teabee89@gmail.com>
2017-09-05 10:34:56 -07:00
Derek McGowan
30578ca329 Merge pull request #2384 from smarterclayton/client_retry
Support HEAD requests without Docker-Content-Digest header
2017-08-25 15:06:52 -07:00
Clayton Coleman
a2015272c1
Support HEAD requests without Docker-Content-Digest header
A statically hosted registry that responds correctly to GET with a
manifest will load the right digest (by looking at the manifest body and
calculating the digest). If the registry returns a HEAD without
`Docker-Content-Digest`, then the client Tags().Get() call will return
an empty digest.

This commit changes the client to fallback to loading the tag via GET if
the `Docker-Content-Digest` header is not set.

Signed-off-by: Clayton Coleman <ccoleman@redhat.com>
2017-08-25 17:18:01 -04:00
Derek McGowan
d9e0121fef Merge pull request #2382 from smarterclayton/scope_check
If the request already has the scope, don't fetchToken again
2017-08-24 15:50:00 -07:00
Clayton Coleman
23f8ca88e1
If the request already has the scope, don't force token fetch
AuthorizeRequest() injects the 'pull' scope if `from` is set
unconditionally. If the current token already has that scope, it will
be inserted into the scope list twice and `addedScopes` will be set to
true, resulting in a new token being fetched that has no net new scopes.

Instead, check whether `additionalScopes` are actually new.

Signed-off-by: Clayton Coleman <ccoleman@redhat.com>
2017-08-23 19:27:37 -04:00
Stephen J Day
1618b49d5b
registry/handlers: ignore notfound on storage driver healthcheck
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-08-21 15:04:31 -07:00
Stephen Day
5f6282db7d Merge pull request #2371 from lazize/patch-1
Fix registry version argument
2017-08-17 10:56:59 -07:00
Leonardo Azize Martins
3f771adca6 Fix registry version argument
Signed-off-by: Leonardo Azize Martins <leonardo.azize@scania.com>
2017-08-17 08:35:39 +02:00
Derek McGowan
e0b4f55f2b Merge pull request #2366 from stevvooe/remove-logging-dependencies
registry: remove dependency on logrus for client
2017-08-15 11:03:52 -07:00
Stephen J Day
860b28c5b9
registry: remove dependency on logrus for client
To simplify the vendoring story for the client, we have now removed the
requirement for `logrus` and the forked `context` package (usually
imported as `dcontext`). We inject the logger via the metrics tracker
for the blob cache and via options on the token handler. We preserve
logs on the proxy cache for that case. Clients expecting these log
messages may need to be updated accordingly.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-08-15 10:28:38 -07:00
Stephen Day
06fa77aa11 Merge pull request #2360 from stevvooe/remove-context-type
context: remove definition of Context
2017-08-11 16:30:26 -07:00
Stephen J Day
9c88801a12
context: remove definition of Context
Back in the before time, the best practices surrounding usage of Context
weren't quite worked out. We defined our own type to make usage easier.
As this packaged was used elsewhere, it make it more and more
challenging to integrate with the forked `Context` type. Now that it is
available in the standard library, we can just use that one directly.

To make usage more consistent, we now use `dcontext` when referring to
the distribution context package.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-08-11 15:53:31 -07:00
Stephen Day
7a8efe719e Merge pull request #2350 from jonjohnsonjr/spec-typo
Fix typo in api spec
2017-08-04 12:10:18 -07:00
Jon Johnson
3d7803ec8c Fix typo in api spec
Signed-off-by: Jon Johnson <jonjohnson@google.com>
2017-07-28 10:13:32 -07:00
Derek McGowan
edc3ab29cd Merge pull request #2316 from igmor/logrus_case_dep_update
Update logrus and logrus-logstash-hook libraries
2017-07-26 10:46:10 -07:00
Aaron Lehmann
e18fe7d3f4 Merge pull request #2346 from riyazdf/security-list
add CONTRIBUTING info for security issues
2017-07-24 17:40:39 -07:00
Stephen Day
cb851f6598 Merge pull request #2345 from mstanleyjones/put-back-image
Put back v2-registry-auth.png
2017-07-24 15:01:48 -07:00
Riyaz Faizullabhoy
f7fb45f59a add CONTRIBUTING info for security issues
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
2017-07-24 14:58:32 -07:00
Misty Stanley-Jones
1d95716792 Put back v2-registry-auth.png
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
2017-07-24 14:27:16 -07:00
Stephen Day
91c507a39a Merge pull request #2340 from stevvooe/limit-payload-size
registry/{storage,handlers}: limit content sizes
2017-07-20 13:57:55 -07:00
YuJie
20f225005a Fix the sentence
Signed-off-by: YuJie <390282283@qq.com>
2017-07-20 05:52:56 +08:00
Derek McGowan
5cfdfbdce5 Merge pull request #2338 from stevvooe/api-typo
api: url typo in specification
2017-07-18 15:49:00 -07:00
Stephen J Day
5e5156afa3
api: url typo in specification
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-07-18 14:48:55 -07:00
Aaron Lehmann
fb90a182a9 Merge pull request #2336 from fate-grand-order/fixed
fix misspelling "algorithm" for cache/redis/redis.go
2017-07-18 11:56:19 -07:00
fate-grand-order
a11fe173d5 fix misspelling "algorithm" for cache/redis/redis.go
Signed-off-by: Helen Chen <chenjg@harmonycloud.cn>
2017-07-18 16:02:42 +08:00
Stephen J Day
55ea440428
registry/{storage,handlers}: limit content sizes
Under certain circumstances, the use of `StorageDriver.GetContent` can
result in unbounded memory allocations. In particualr, this happens when
accessing a layer through the manifests endpoint.

This problem is mitigated by setting a 4MB limit when using to access
content that may have been accepted from a user. In practice, this means
setting the limit with the use of `BlobProvider.Get` by wrapping
`StorageDriver.GetContent` in a helper that uses `StorageDriver.Reader`
with a `limitReader` that returns an error.

When mitigating this security issue, we also noticed that the size of
manifests uploaded to the registry is also unlimited. We apply similar
logic to the request body of payloads that are full buffered.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-07-06 17:13:39 -07:00
Aaron Lehmann
f86db6b226 Merge pull request #2315 from ipanova/mediatype-typo
Fixing image manifest schema2 medaitype typo in docs.
2017-06-27 11:58:08 -07:00
Aaron Lehmann
caa175c710 Merge pull request #2299 from dmage/regulator
Fix signalling Wait in regulator.enter
2017-06-23 15:25:35 -07:00
Derek McGowan
b9f76758ae Merge pull request #2310 from dmage/digest
Update Docker-Content-Digest if manifest list is rewritten
2017-06-23 15:07:39 -07:00
Igor Morozov
a97d7c0c15 moved Sirupsen to sirupsen on a case sensitive system
Signed-off-by: Igor Morozov <igor@adhoc05-sjc1.prod.uber.internal>
2017-06-23 20:28:48 +00:00
Ina Panova
5ccd03d28a Fixing image manifest schema2 medaitype typo in docs.
Signed-off-by: Ina Panova <ipanova@redhat.com>
2017-06-23 12:25:52 +02:00
Oleg Bulatov
5b1b6afae2 Update Docker-Content-Digest if manifest list is rewritten
If the client doesn't support manifest lists, the registry will
rewrite a manifest list into the old format. The Docker-Content-Digest
header should be updated in this case.

Signed-off-by: Oleg Bulatov <oleg@bulatov.me>
2017-06-16 16:20:14 +02:00
Oleg Bulatov
258345ba0d Fix signalling Wait in regulator.enter
In some conditions, regulator.exit may not send a signal to blocked
regulator.enter.

Let's assume we are in the critical section of regulator.exit and r.available
is equal to 0. And there are three more gorotines. One goroutine also executes
regulator.exit and waits for the lock. Rest run regulator.enter and wait for
the signal.

We send the signal, and after releasing the lock, there will be lock
contention:

  1. Wait from regulator.enter
  2. Lock from regulator.exit

If the winner is Lock from regulator.exit, we will not send another signal to
unlock the second Wait.

Signed-off-by: Oleg Bulatov <obulatov@redhat.com>
2017-06-02 15:41:55 +02:00
Stephen Day
1e2f10eb65 Merge pull request #2281 from sixeyed/patch-1
Add ARGs for cross-compiling
2017-05-24 13:58:24 -07:00
Derek McGowan
a1576d6e21 Merge pull request #2165 from kevinetc123/patch-1
fix some misspells
2017-05-24 11:18:20 -07:00
Derek McGowan
49bb3242da Merge pull request #2282 from mstanleyjones/put-back-architecture-doc
Put architecture.md back into distribution repo
2017-05-23 13:10:21 -07:00
Misty Stanley-Jones
b0f98e9382 Put architecture.md back into distribution repo
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
2017-05-23 11:24:11 -07:00
Derek McGowan
079f5b179d Merge pull request #2276 from nycholas/patch-1
Update README.md
2017-05-23 10:30:50 -07:00
Elton Stoneman
646fc9702c Add ARGs for cross-compiling
Add build args. Defaults to Linux/x64 so no change to existing image, but can build for other platforms - e.g.
```
docker build --build-arg GOOS=windows -t distribution-builder:windows .
```

Signed-off-by: Elton Stoneman <elton@sixeyed.com>
2017-05-23 10:02:15 +01:00
Nycholas de Oliveira e Oliveira
5573a13f15 Update README.md
Signed-off-by: Nycholas de Oliveira e Oliveira <nycholas@gmail.com>
2017-05-18 10:11:41 -03:00
Derek McGowan
a528cc1fc3 Merge pull request #2206 from stevvooe/update-resumable-hash
vendor: update resumable dependency
2017-05-17 13:09:54 -07:00
Stephen J Day
f01bcc8f62
vendor: update resumable dependency
Updates resumable hash implementation to Go 1.8 equivalent. This should
be a major speedup, since it includes a number of optimizations from Go
1.7.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-05-16 15:12:58 -07:00
Stephen Day
83f857ca12 Merge pull request #2207 from docker/update-go-1.8
go 1.8: update dockerfile and circle
2017-05-16 13:16:41 -07:00
Derek McGowan
9098f843d6 Merge pull request #2275 from IamBusy/master
Remove unused function
2017-05-16 11:51:13 -07:00
Derek McGowan
df1e488526
Update registry build to use go 1.8
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2017-05-16 11:33:57 -07:00
william wei
37ca688dc0 Remove unused function
Signed-off-by: william wei <1342247033@qq.com>
2017-05-16 17:47:13 +08:00
Derek McGowan
ce936a8591 Merge pull request #2262 from m-masataka/add_description_of_timeout
DOC:configuration.md: Change description of interval.
2017-05-05 11:45:43 -07:00
Masataka Mizukoshi
7d8dab5fdc DOC:configuration.md: Change description of interval.
Signed-off-by: Masataka Mizukoshi <m.mizukoshi.wakuwaku@gmail.com>
2017-05-04 19:14:29 +00:00
Stephen Day
a40abc69f2 Merge pull request #2245 from aaronlehmann/fetch-origin
[CI] Fetch origin before diffing
2017-05-04 11:51:08 -07:00
Stephen Day
7cc8e701c9 Merge pull request #2264 from luislobo/patch-1
Fixed #htpasswd link
2017-05-04 11:24:27 -07:00
Luis Lobo Borobia
212f47c318
Fixed #htpasswd link
Fixed #htpasswd link

Signed-off-by: Luis Lobo Borobia <luislobo@gmail.com>
2017-05-03 23:19:44 -05:00
Masataka Mizukoshi
05ac637aec DOC:configuration.md: Change description of interval.
Signed-off-by: Masataka Mizukoshi <m.mizukoshi.wakuwaku@gmail.com>
2017-05-01 09:28:32 +00:00
Derek McGowan
1d7824702b Merge pull request #2247 from yuwaMSFT2/revendorazuresdk
closes #2224 re-vendor the latest Azure Storage SDK for better performance
2017-04-27 10:54:25 -07:00
Derek McGowan
b7d5d9bfed Merge pull request #2258 from tt/return-early-to-prevent-nil-pointer-dereference
Return early to prevent nil pointer dereference
2017-04-27 09:38:03 -07:00
Troels Thomsen
1935c8d50b Return early to prevent nil pointer dereference
Signed-off-by: Troels Thomsen <troels@thomsen.io>
2017-04-27 14:59:37 +02:00
Derek McGowan
f4a1d3e0d5 Merge pull request #2230 from tt/support-session-token
Support session token
2017-04-26 12:53:50 -07:00
Troels Thomsen
7f510ae9c9 Support session token
Signed-off-by: Troels Thomsen <troels@thomsen.io>
2017-04-25 19:31:50 +02:00
Derek McGowan
e85ef3c019 Merge pull request #2253 from stevvooe/allow-more-digest-alg-separators
reference: allow more than 1 digest algorithm separator
2017-04-25 09:30:17 -07:00
Stephen J Day
3da015f8aa
reference: allow more than 1 digest algorithm separator
This updates the grammar to allow more than one digest algorithm
separator, matching the regular expression and intended grammar.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-04-24 15:14:12 -07:00
Yu Wang (UC)
ac05d143d8 closes #2224: re-vendor the latest Azure Storage SDK for better performance
Signed-off-by: Yu Wang <yuwa@microsoft.com>
2017-04-14 14:20:18 -07:00
Aaron Lehmann
2f728896a0 [CI] Fetch origin before diffing
It turns out that origin/master may not be up to date in CircleCI
checkouts. Fetch origin so that diffing for the vendor check can be done
correctly.

Note that this doesn't help the case of PRs against branches other than
master, but the worst case is that those will waste a few seconds doing
unnecessary vendor validation. Since those PRs are relatively rare, that
seems fine.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2017-04-12 13:18:06 -07:00
Stephen Day
c3e06c6069 Merge pull request #2239 from stevvooe/use-request-context
register/handlers: remove context manager
2017-04-10 16:14:28 -07:00
Stephen J Day
818ba4babf
vendor: update gorilla/mux to be compatible with Go 1.7
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-04-10 15:27:42 -07:00
Stephen J Day
1f0a9dbca0
register/handlers: remove context manager
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-04-10 15:27:30 -07:00
Stephen Day
a73ed75f5a Merge pull request #2241 from dmcgowan/vendor-fix
Update vendor directory to match expectation of vndr tool
2017-04-10 14:08:28 -07:00
Derek McGowan
b22c6b7a4e Update vendor directory to match expectation of vndr tool
Adds READMEs and enforces vendor is done at repository root

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2017-04-10 12:07:32 -07:00
Stephen Day
7b9ebdc54f Merge pull request #2215 from AlvinFeng/expires
Remove expires tag from s3 upload
2017-04-07 12:14:10 -07:00
Derek McGowan
0dd6ca97af Merge pull request #2238 from SantiagoTorres/fix_readme_broken_link
DOC: README: Fix broken link in migrator
2017-04-06 10:25:25 -07:00
Santiago Torres
364d2e4a5b
DOC: README: Fix broken link in migrator
A stray space in the link for the migrator repository wasn't allowing it
to be rendered properly in markdown viewers. Remove such a space to
avoid this.

Signed-off-by: Santiago Torres-Arias <torresariass@gmail.com>
2017-04-05 19:22:18 -04:00
Derek McGowan
0700fa570d Merge pull request #2219 from dmcgowan/fix-forwarded-logic
Fix forwarded logic
2017-03-21 10:14:25 -07:00
Derek McGowan
81a47d9766 Remove support for X-Forwarded-Port
Partially reverts change adding support for X-Forwarded-Port.
Changes the logic to prefer the standard Forwarded header over
X-Forwarded headers. Prefer forwarded "host" over "for" since
"for" represents the client and not the client's request.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2017-03-20 16:13:33 -07:00
Troels Thomsen
d4c3e88426
Add test for precendence with standard port
Signed-off-by: Troels Thomsen <troels@thomsen.io>
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2017-03-20 16:10:44 -07:00
Derek McGowan
11c74e07e0 Merge pull request #2218 from aaronlehmann/restore-vendor-dir
Makefile: Restore vendor directory after dep-validate
2017-03-20 11:28:17 -07:00
Derek McGowan
d2da3173db Merge pull request #2217 from aaronlehmann/fix-vendor-validation
Fix vendor validation
2017-03-20 11:28:00 -07:00
Aaron Lehmann
299b90b0bd Makefile: Restore vendor directory after dep-validate
Currently, this target makes changes to the vendor directory, which may
overwrite local changes or cause build errors. It's better to restore
the original vendor directory after running the check.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2017-03-20 11:12:03 -07:00
Aaron Lehmann
f6c62456b8 Fix vendor validation
The dep-validate target appears to never get invoked. In the CircleCI
build environment, "master" points to the commit under test. The
circle.yml fragment needs to compare again "origin/master" instead.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2017-03-20 11:11:10 -07:00
Derek McGowan
29e5cd5304 Merge pull request #2216 from fate-grand-order/fixed
fix some typos in notifications/event.go and sinks.go
2017-03-20 10:23:09 -07:00
fate-grand-order
eaf60fffee fix some typos in notifications/event.go and sinks.go
Signed-off-by: fate-grand-order <chenjg@harmonycloud.cn>
2017-03-20 20:23:11 +08:00
Alvin Feng
45bb7c9cc9 Remove expires tag from s3 upload
Signed-off-by: Alvin Feng <alvin4feng@yahoo.com>
2017-03-17 23:41:15 +00:00
Derek McGowan
08b06dc023 Merge pull request #2203 from clnperez/manifest-url-err
Better error message for BuildManifestURL if not tagged or digested
2017-03-03 13:22:46 -08:00
Derek McGowan
4ac39769dc Merge pull request #2155 from dmcgowan/update-release-checklist
Update release checklist with further details
2017-03-03 10:17:23 -08:00
Derek McGowan
d7905dc725 Merge pull request #2200 from fate-grand-order/fixed
fix typos in comment
2017-03-03 10:04:35 -08:00
Christy Perez
0810eba2ad Better error message for BuildManifestURL if not tagged or digested
Since there's no default case, if there's not a tag or digest you get
back a confusing error from the router about it not matching the
expected pattern.

Also redoing the tests for URLs a bit so that they can handle checking
for failures.

Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com>
2017-03-02 11:27:23 -06:00
fate-grand-order
3161f9d1fd fix typos in comment
Signed-off-by: fate-grand-order <chenjg@harmonycloud.cn>
2017-02-27 14:06:18 +08:00
Derek McGowan
50133d6372 Merge pull request #2195 from fate-grand-order/fixed
Use errors.New() to output the error message and fix some typos
2017-02-21 11:08:14 -08:00
fate-grand-order
6a8e2ca84f Use errors.New() to output the error message and fix some typos
Signed-off-by: fate-grand-order <chenjg@harmonycloud.cn>
2017-02-20 10:39:58 +08:00
Derek McGowan
df5327f76f Merge pull request #2187 from nwt/notifications-fix-expvar
notifications: fix expvar for Go 1.7
2017-02-17 11:36:21 -08:00
Derek McGowan
4f87c80073 Merge pull request #2192 from uhayate/refactor-code-style
refactor the code style in distribution/registry/storage/driver/s3-goamz/s3.go
2017-02-15 17:12:16 -08:00
Noah Treuhaft
9a58c91051 notifications: fix expvar for Go 1.7
Remove EndpointConfig.Transport from the return value of the
registry.notifications.endpoints expvar.Func.  It results in an empty
value for that expvar variable under Go 1.7 because it is a non-nil
*http.Transport, which Go 1.7 can no longer encode as JSON.

Signed-off-by: Noah Treuhaft <noah.treuhaft@docker.com>
2017-02-14 10:51:20 -08:00
Aaron Lehmann
62d8d910b5 Merge pull request #2184 from sakeven/master
Check whether must use v4 auth in specific aws region ( storage driver s3-goamz )
2017-02-13 22:29:02 -08:00
sakeven
72bdf0e320 check whether must use v4 auth in specific aws region
Signed-off-by: sakeven <jc5930@sina.cn>
2017-02-14 10:42:20 +08:00
Aaron Lehmann
b38e5838b7 Merge pull request #2185 from yongtang/29936-validate-insecure-registry
Expose `DomainRegexp` from reference
2017-02-13 11:48:09 -08:00
uhayate
75c2e524a1 refactor the code style in distribution/registry/storage/driver/s3-goamz/s3.go
Signed-off-by: uhayate <uhayate.gong@daocloud.io>
2017-02-13 17:29:08 +08:00
kaiwentan
20036597bf fix some misspells
Signed-off-by: kaiwentan <kaiwentan@harmonycloud.cn>
2017-02-08 15:53:01 +08:00
Yong Tang
95daa793b8 Expose DomainRegexp from reference
This fix is based on:
https://github.com/docker/docker/pull/30746#discussion_r99650885

The goal is to reuse the `DomainRegexp` in docker to check
for `<host>:<port>` pattern.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2017-02-07 17:43:28 -08:00
Derek McGowan
b1993c9530 Merge pull request #2179 from Windfarer/master
Fixing acronym's case
2017-02-07 14:24:14 -08:00
Eric Yang
2d20471cd7 fixing acronyms case
Signed-off-by: Eric Yang <qizhao.yang@daocloud.io>
2017-01-31 01:29:30 +08:00
Aaron Lehmann
fb0bebc4b6 Merge pull request #2176 from stevvooe/clean-empty-blob-comments
registry/storage: clean up zero-length blob comments
2017-01-27 15:42:54 -08:00
Stephen J Day
7f565ed65a
registry/storage: clean up zero-length blob comments
A previous inspection of the code surrounding zero-length blobs led to
some interesting question. After inspection, it was found that the hash
was indeed for the empty string (""), and not an empty tar, so the code
was correct. The variable naming and comments have been updated
accordingly.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-01-27 15:28:30 -08:00
Derek McGowan
545102ea07 Merge pull request #2173 from aaronlehmann/tagnameonly
reference: Replace EnsureTagged with TagNameOnly
2017-01-26 14:35:53 -08:00
Aaron Lehmann
245ca4659e reference: Replace EnsureTagged with TagNameOnly
The common use case for this function is to add a default tag if the
reference only has a name. The current behavior only adds the default
tag if there is no *tag*, which requires most callers to check for a
digest. Change the behavior to only add default tags to name-only
references, and change the name to reflect this. The documentation
already described the new behavior, so it does not need to be changed.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2017-01-26 11:46:00 -08:00
Derek McGowan
959659c3fa
Update release checklist with further details
Add details for release checklist for where to put the update
the changelist and which branch to cherry-pick from. Also add
more details around creating the tag and verifying the tag is
correct.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2017-01-18 11:07:35 -08:00
1521 changed files with 421133 additions and 69424 deletions

3
.github/CODE_OF_CONDUCT.md vendored Normal file
View file

@ -0,0 +1,3 @@
## Docker Distribution Community Code of Conduct
Docker Distribution follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

1
.gitignore vendored
View file

@ -35,3 +35,4 @@ bin/*
# Editor/IDE specific files. # Editor/IDE specific files.
*.sublime-project *.sublime-project
*.sublime-workspace *.sublime-workspace
.idea/*

20
.golangci.yml Normal file
View file

@ -0,0 +1,20 @@
linters:
enable:
- structcheck
- varcheck
- staticcheck
- unconvert
- gofmt
- goimports
- golint
- ineffassign
- vet
- unused
- misspell
disable:
- errcheck
run:
deadline: 2m
skip-dirs:
- vendor

View file

@ -16,3 +16,17 @@ davidli <wenquan.li@hp.com> davidli <wenquan.li@hpe.com>
Omer Cohen <git@omer.io> Omer Cohen <git@omerc.net> Omer Cohen <git@omer.io> Omer Cohen <git@omerc.net>
Eric Yang <windfarer@gmail.com> Eric Yang <Windfarer@users.noreply.github.com> Eric Yang <windfarer@gmail.com> Eric Yang <Windfarer@users.noreply.github.com>
Nikita Tarasov <nikita@mygento.ru> Nikita <luckyraul@users.noreply.github.com> Nikita Tarasov <nikita@mygento.ru> Nikita <luckyraul@users.noreply.github.com>
Yu Wang <yuwa@microsoft.com> yuwaMSFT2 <yuwa@microsoft.com>
Yu Wang <yuwa@microsoft.com> Yu Wang (UC) <yuwa@microsoft.com>
Olivier Gambier <olivier@docker.com> dmp <dmp@loaner.local>
Olivier Gambier <olivier@docker.com> Olivier <o+github@gambier.email>
Olivier Gambier <olivier@docker.com> Olivier <dmp42@users.noreply.github.com>
Elsan Li 李楠 <elsanli@tencent.com> elsanli(李楠) <elsanli@tencent.com>
Rui Cao <ruicao@alauda.io> ruicao <ruicao@alauda.io>
Gwendolynne Barr <gwendolynne.barr@docker.com> gbarr01 <gwendolynne.barr@docker.com>
Haibing Zhou 周海兵 <zhouhaibing089@gmail.com> zhouhaibing089 <zhouhaibing089@gmail.com>
Feng Honglin <tifayuki@gmail.com> tifayuki <tifayuki@gmail.com>
Helen Xie <xieyulin821@harmonycloud.cn> Helen-xie <xieyulin821@harmonycloud.cn>
Mike Brown <brownwm@us.ibm.com> Mike Brown <mikebrow@users.noreply.github.com>
Manish Tomar <manish.tomar@docker.com> Manish Tomar <manishtomar@users.noreply.github.com>
Sakeven Jiang <jc5930@sina.cn> sakeven <jc5930@sina.cn>

56
.travis.yml Normal file
View file

@ -0,0 +1,56 @@
dist: bionic
sudo: required
# setup travis so that we can run containers for integration tests
services:
- docker
jobs:
include:
- arch: amd64
- arch: s390x
language: go
go:
- "1.14.x"
go_import_path: github.com/docker/distribution
addons:
apt:
packages:
- python-minimal
env:
- TRAVIS_GOOS=linux DOCKER_BUILDTAGS="include_oss include_gcs" TRAVIS_CGO_ENABLED=1
before_install:
- uname -r
- sudo apt-get -q update
install:
- cd /tmp && go get -u github.com/vbatts/git-validation
# TODO: Add enforcement of license
# - go get -u github.com/kunalkushwaha/ltag
- cd $TRAVIS_BUILD_DIR
script:
- export GOOS=$TRAVIS_GOOS
- export CGO_ENABLED=$TRAVIS_CGO_ENABLED
- DCO_VERBOSITY=-q script/validate/dco
- GOOS=linux GO111MODULE=on script/setup/install-dev-tools
- script/validate/vendor
- go build -i .
- make check
- make build
- make binaries
# Currently takes too long
#- if [ "$GOOS" = "linux" ]; then make test-race ; fi
- if [ "$GOOS" = "linux" ]; then make coverage ; fi
after_success:
- bash <(curl -s https://codecov.io/bash) -F linux
before_deploy:
# Run tests with storage driver configurations

182
AUTHORS
View file

@ -1,182 +0,0 @@
a-palchikov <deemok@gmail.com>
Aaron Lehmann <aaron.lehmann@docker.com>
Aaron Schlesinger <aschlesinger@deis.com>
Aaron Vinson <avinson.public@gmail.com>
Adam Duke <adam.v.duke@gmail.com>
Adam Enger <adamenger@gmail.com>
Adrian Mouat <adrian.mouat@gmail.com>
Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
Alex Chan <alex.chan@metaswitch.com>
Alex Elman <aelman@indeed.com>
Alexey Gladkov <gladkov.alexey@gmail.com>
allencloud <allen.sun@daocloud.io>
amitshukla <ashukla73@hotmail.com>
Amy Lindburg <amy.lindburg@docker.com>
Andrew Hsu <andrewhsu@acm.org>
Andrew Meredith <andymeredith@gmail.com>
Andrew T Nguyen <andrew.nguyen@docker.com>
Andrey Kostov <kostov.andrey@gmail.com>
Andy Goldstein <agoldste@redhat.com>
Anis Elleuch <vadmeste@gmail.com>
Anton Tiurin <noxiouz@yandex.ru>
Antonio Mercado <amercado@thinknode.com>
Antonio Murdaca <runcom@redhat.com>
Anusha Ragunathan <anusha@docker.com>
Arien Holthuizen <aholthuizen@schubergphilis.com>
Arnaud Porterie <arnaud.porterie@docker.com>
Arthur Baars <arthur@semmle.com>
Asuka Suzuki <hello@tanksuzuki.com>
Avi Miller <avi.miller@oracle.com>
Ayose Cazorla <ayosec@gmail.com>
BadZen <dave.trombley@gmail.com>
Ben Bodenmiller <bbodenmiller@hotmail.com>
Ben Firshman <ben@firshman.co.uk>
bin liu <liubin0329@gmail.com>
Brian Bland <brian.bland@docker.com>
burnettk <burnettk@gmail.com>
Carson A <ca@carsonoid.net>
Cezar Sa Espinola <cezarsa@gmail.com>
Charles Smith <charles.smith@docker.com>
Chris Dillon <squarism@gmail.com>
cuiwei13 <cuiwei13@pku.edu.cn>
cyli <cyli@twistedmatrix.com>
Daisuke Fujita <dtanshi45@gmail.com>
Daniel Huhn <daniel@danielhuhn.de>
Darren Shepherd <darren@rancher.com>
Dave Trombley <dave.trombley@gmail.com>
Dave Tucker <dt@docker.com>
David Lawrence <david.lawrence@docker.com>
David Verhasselt <david@crowdway.com>
David Xia <dxia@spotify.com>
davidli <wenquan.li@hp.com>
Dejan Golja <dejan@golja.org>
Derek McGowan <derek@mcgstyle.net>
Diogo Mónica <diogo.monica@gmail.com>
DJ Enriquez <dj.enriquez@infospace.com>
Donald Huang <don.hcd@gmail.com>
Doug Davis <dug@us.ibm.com>
Edgar Lee <edgar.lee@docker.com>
Eric Yang <windfarer@gmail.com>
Fabio Berchtold <jamesclonk@jamesclonk.ch>
Fabio Huser <fabio@fh1.ch>
farmerworking <farmerworking@gmail.com>
Felix Yan <felixonmars@archlinux.org>
Florentin Raud <florentin.raud@gmail.com>
Frank Chen <frankchn@gmail.com>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
gabriell nascimento <gabriell@bluesoft.com.br>
Gleb Schukin <gschukin@ptsecurity.com>
harche <p.harshal@gmail.com>
Henri Gomez <henri.gomez@gmail.com>
Hu Keping <hukeping@huawei.com>
Hua Wang <wanghua.humble@gmail.com>
HuKeping <hukeping@huawei.com>
Ian Babrou <ibobrik@gmail.com>
igayoso <igayoso@gmail.com>
Jack Griffin <jackpg14@gmail.com>
James Findley <jfindley@fastmail.com>
Jason Freidman <jason.freidman@gmail.com>
Jason Heiss <jheiss@aput.net>
Jeff Nickoloff <jeff@allingeek.com>
Jess Frazelle <acidburn@google.com>
Jessie Frazelle <jessie@docker.com>
jhaohai <jhaohai@foxmail.com>
Jianqing Wang <tsing@jianqing.org>
Jihoon Chung <jihoon@gmail.com>
Joao Fernandes <joao.fernandes@docker.com>
John Mulhausen <john@docker.com>
John Starks <jostarks@microsoft.com>
Jon Johnson <jonjohnson@google.com>
Jon Poler <jonathan.poler@apcera.com>
Jonathan Boulle <jonathanboulle@gmail.com>
Jordan Liggitt <jliggitt@redhat.com>
Josh Chorlton <josh.chorlton@docker.com>
Josh Hawn <josh.hawn@docker.com>
Julien Fernandez <julien.fernandez@gmail.com>
Ke Xu <leonhartx.k@gmail.com>
Keerthan Mala <kmala@engineyard.com>
Kelsey Hightower <kelsey.hightower@gmail.com>
Kenneth Lim <kennethlimcp@gmail.com>
Kenny Leung <kleung@google.com>
Li Yi <denverdino@gmail.com>
Liu Hua <sdu.liu@huawei.com>
liuchang0812 <liuchang0812@gmail.com>
Lloyd Ramey <lnr0626@gmail.com>
Louis Kottmann <louis.kottmann@gmail.com>
Luke Carpenter <x@rubynerd.net>
Marcus Martins <marcus@docker.com>
Mary Anthony <mary@docker.com>
Matt Bentley <mbentley@mbentley.net>
Matt Duch <matt@learnmetrics.com>
Matt Moore <mattmoor@google.com>
Matt Robenolt <matt@ydekproductions.com>
Matthew Green <greenmr@live.co.uk>
Michael Prokop <mika@grml.org>
Michal Minar <miminar@redhat.com>
Michal Minář <miminar@redhat.com>
Mike Brown <brownwm@us.ibm.com>
Miquel Sabaté <msabate@suse.com>
Misty Stanley-Jones <misty@apache.org>
Misty Stanley-Jones <misty@docker.com>
Morgan Bauer <mbauer@us.ibm.com>
moxiegirl <mary@docker.com>
Nathan Sullivan <nathan@nightsys.net>
nevermosby <robolwq@qq.com>
Nghia Tran <tcnghia@gmail.com>
Nikita Tarasov <nikita@mygento.ru>
Noah Treuhaft <noah.treuhaft@docker.com>
Nuutti Kotivuori <nuutti.kotivuori@poplatek.fi>
Oilbeater <liumengxinfly@gmail.com>
Olivier Gambier <olivier@docker.com>
Olivier Jacques <olivier.jacques@hp.com>
Omer Cohen <git@omer.io>
Patrick Devine <patrick.devine@docker.com>
Phil Estes <estesp@linux.vnet.ibm.com>
Philip Misiowiec <philip@atlashealth.com>
Pierre-Yves Ritschard <pyr@spootnik.org>
Qiao Anran <qiaoanran@gmail.com>
Randy Barlow <randy@electronsweatshop.com>
Richard Scothern <richard.scothern@docker.com>
Rodolfo Carvalho <rhcarvalho@gmail.com>
Rusty Conover <rusty@luckydinosaur.com>
Sean Boran <Boran@users.noreply.github.com>
Sebastiaan van Stijn <github@gone.nl>
Sebastien Coavoux <s.coavoux@free.fr>
Serge Dubrouski <sergeyfd@gmail.com>
Sharif Nassar <sharif@mrwacky.com>
Shawn Falkner-Horine <dreadpirateshawn@gmail.com>
Shreyas Karnik <karnik.shreyas@gmail.com>
Simon Thulbourn <simon+github@thulbourn.com>
spacexnice <yaoyao.xyy@alibaba-inc.com>
Spencer Rinehart <anubis@overthemonkey.com>
Stan Hu <stanhu@gmail.com>
Stefan Majewsky <stefan.majewsky@sap.com>
Stefan Weil <sw@weilnetz.de>
Stephen J Day <stephen.day@docker.com>
Sungho Moon <sungho.moon@navercorp.com>
Sven Dowideit <SvenDowideit@home.org.au>
Sylvain Baubeau <sbaubeau@redhat.com>
Ted Reed <ted.reed@gmail.com>
tgic <farmer1992@gmail.com>
Thomas Sjögren <konstruktoid@users.noreply.github.com>
Tianon Gravi <admwiggin@gmail.com>
Tibor Vass <teabee89@gmail.com>
Tonis Tiigi <tonistiigi@gmail.com>
Tony Holdstock-Brown <tony@docker.com>
Trevor Pounds <trevor.pounds@gmail.com>
Troels Thomsen <troels@thomsen.io>
Victor Vieux <vieux@docker.com>
Victoria Bialas <victoria.bialas@docker.com>
Vincent Batts <vbatts@redhat.com>
Vincent Demeester <vincent@sbr.pm>
Vincent Giersch <vincent.giersch@ovh.net>
W. Trevor King <wking@tremily.us>
weiyuan.yl <weiyuan.yl@alibaba-inc.com>
xg.song <xg.song@venusource.com>
xiekeyang <xiekeyang@huawei.com>
Yann ROBERT <yann.robert@anantaplex.fr>
yaoyao.xyy <yaoyao.xyy@alibaba-inc.com>
yuexiao-wang <wang.yuexiao@zte.com.cn>
yuzou <zouyu7@huawei.com>
zhouhaibing089 <zhouhaibing089@gmail.com>
姜继忠 <jizhong.jiangjz@alibaba-inc.com>

View file

@ -83,7 +83,7 @@ build:
+ lint + lint
+ build + build
github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar
github.com/Sirupsen/logrus github.com/sirupsen/logrus
github.com/docker/libtrust github.com/docker/libtrust
... ...
github.com/yvasiyarov/gorelic github.com/yvasiyarov/gorelic
@ -108,7 +108,7 @@ directory. This includes formatting, vetting, linting, building,
testing and generating tagged binaries. We can verify this worked by running testing and generating tagged binaries. We can verify this worked by running
the registry binary generated in the "./bin" directory: the registry binary generated in the "./bin" directory:
$ ./bin/registry -version $ ./bin/registry --version
./bin/registry github.com/docker/distribution v2.0.0-alpha.2-80-g16d8b2c.m ./bin/registry github.com/docker/distribution v2.0.0-alpha.2-80-g16d8b2c.m
### Optional build tags ### Optional build tags

View file

@ -1,14 +1,15 @@
# Contributing to the registry # Contributing to the registry
## Before reporting an issue... ## Before reporting an issue...
### If your problem is with... ### If your problem is with...
- automated builds - automated builds or your [Docker Hub](https://hub.docker.com/) account
- your account on the [Docker Hub](https://hub.docker.com/) - Report it to [Hub Support](https://hub.docker.com/support/)
- any other [Docker Hub](https://hub.docker.com/) issue - Distributions of Docker for desktop or Linux
- Report [Mac Desktop issues](https://github.com/docker/for-mac)
Then please do not report your issue here - you should instead report it to [https://support.docker.com](https://support.docker.com) - Report [Windows Desktop issues](https://github.com/docker/for-win)
- Report [Linux issues](https://github.com/docker/for-linux)
### If you... ### If you...
@ -16,10 +17,16 @@ Then please do not report your issue here - you should instead report it to [htt
- can't figure out something - can't figure out something
- are not sure what's going on or what your problem is - are not sure what's going on or what your problem is
Then please do not open an issue here yet - you should first try one of the following support forums: Please ask first in the #distribution channel on Docker community slack.
[Click here for an invite to Docker community slack](https://dockr.ly/slack)
- irc: #docker-distribution on freenode ### Reporting security issues
- mailing-list: <distribution@dockerproject.org> or https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
The Docker maintainers take security seriously. If you discover a security
issue, please bring it to their attention right away!
Please **DO NOT** file a public issue, instead send your report privately to
[security@docker.com](mailto:security@docker.com).
## Reporting an issue properly ## Reporting an issue properly
@ -27,7 +34,7 @@ By following these simple rules you will get better and faster feedback on your
- search the bugtracker for an already reported issue - search the bugtracker for an already reported issue
### If you found an issue that describes your problem: ### If you found an issue that describes your problem:
- please read other user comments first, and confirm this is the same issue: a given error condition might be indicative of different problems - you may also find a workaround in the comments - please read other user comments first, and confirm this is the same issue: a given error condition might be indicative of different problems - you may also find a workaround in the comments
- please refrain from adding "same thing here" or "+1" comments - please refrain from adding "same thing here" or "+1" comments
@ -43,7 +50,7 @@ By following these simple rules you will get better and faster feedback on your
2. copy the output of: 2. copy the output of:
- `docker version` - `docker version`
- `docker info` - `docker info`
- `docker exec <registry-container> registry -version` - `docker exec <registry-container> registry --version`
3. copy the command line you used to launch your Registry 3. copy the command line you used to launch your Registry
4. restart your docker daemon in debug mode (add `-D` to the daemon launch arguments) 4. restart your docker daemon in debug mode (add `-D` to the daemon launch arguments)
5. reproduce your problem and get your docker daemon logs showing the error 5. reproduce your problem and get your docker daemon logs showing the error
@ -51,90 +58,72 @@ By following these simple rules you will get better and faster feedback on your
7. provide any relevant detail about your specific Registry configuration (e.g., storage backend used) 7. provide any relevant detail about your specific Registry configuration (e.g., storage backend used)
8. indicate if you are using an enterprise proxy, Nginx, or anything else between you and your Registry 8. indicate if you are using an enterprise proxy, Nginx, or anything else between you and your Registry
## Contributing a patch for a known bug, or a small correction ## Contributing Code
Contributions should be made via pull requests. Pull requests will be reviewed
by one or more maintainers or reviewers and merged when acceptable.
You should follow the basic GitHub workflow: You should follow the basic GitHub workflow:
1. fork 1. Use your own [fork](https://help.github.com/en/articles/about-forks)
2. commit a change 2. Create your [change](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#successful-changes)
3. make sure the tests pass 3. Test your code
4. PR 4. [Commit](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#commit-messages) your work, always [sign your commits](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#commit-messages)
5. Push your change to your fork and create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork)
Additionally, you must [sign your commits](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work). It's very simple: Refer to [containerd's contribution guide](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#successful-changes)
for tips on creating a successful contribution.
- configure your name with git: `git config user.name "Real Name" && git config user.email mail@example.com` ## Sign your work
- sign your commits using `-s`: `git commit -s -m "My commit"`
Some simple rules to ensure quick merge: The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch or otherwise have the right to pass
it on as an open-source patch. The rules are pretty simple: if you can certify
the below (from [developercertificate.org](http://developercertificate.org/)):
- clearly point to the issue(s) you want to fix in your PR comment (e.g., `closes #12345`) ```
- prefer multiple (smaller) PRs addressing individual issues over a big one trying to address multiple issues at once Developer Certificate of Origin
- if you need to amend your PR following comments, please squash instead of adding more commits Version 1.1
## Contributing new features Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
You are heavily encouraged to first discuss what you want to do. You can do so on the irc channel, or by opening an issue that clearly describes the use case you want to fulfill, or the problem you are trying to solve. Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
If this is a major new feature, you should then submit a proposal that describes your technical solution and reasoning. Developer's Certificate of Origin 1.1
If you did discuss it first, this will likely be greenlighted very fast. It's advisable to address all feedback on this proposal before starting actual work.
Then you should submit your implementation, clearly linking to the issue (and possible proposal). By making a contribution to this project, I certify that:
Your PR will be reviewed by the community, then ultimately by the project maintainers, before being merged. (a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
It's mandatory to: (b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
- interact respectfully with other community members and maintainers - more generally, you are expected to abide by the [Docker community rules](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#docker-community-guidelines) (c) The contribution was provided directly to me by some other
- address maintainers' comments and modify your submission accordingly person who certified (a), (b) or (c) and I have not modified
- write tests for any new code it.
Complying to these simple rules will greatly accelerate the review process, and will ensure you have a pleasant experience in contributing code to the Registry. (d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
Have a look at a great, successful contribution: the [Swift driver PR](https://github.com/docker/distribution/pull/493) Then you just add a line to every git commit message:
## Coding Style Signed-off-by: Joe Smith <joe.smith@email.com>
Unless explicitly stated, we follow all coding guidelines from the Go Use your real name (sorry, no pseudonyms or anonymous contributions.)
community. While some of these standards may seem arbitrary, they somehow seem
to result in a solid, consistent codebase.
It is possible that the code base does not currently comply with these If you set your `user.name` and `user.email` git configs, you can sign your
guidelines. We are not looking for a massive PR that fixes this, since that commit automatically with `git commit -s`.
goes against the spirit of the guidelines. All new contributions should make a
best effort to clean up and make the code base better than they left it.
Obviously, apply your best judgement. Remember, the goal here is to make the
code base easier for humans to navigate and understand. Always keep that in
mind when nudging others to comply.
The rules:
1. All code should be formatted with `gofmt -s`.
2. All code should pass the default levels of
[`golint`](https://github.com/golang/lint).
3. All code should follow the guidelines covered in [Effective
Go](http://golang.org/doc/effective_go.html) and [Go Code Review
Comments](https://github.com/golang/go/wiki/CodeReviewComments).
4. Comment the code. Tell us the why, the history and the context.
5. Document _all_ declarations and methods, even private ones. Declare
expectations, caveats and anything else that may be important. If a type
gets exported, having the comments already there will ensure it's ready.
6. Variable name length should be proportional to its context and no longer.
`noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`.
In practice, short methods will have short variable names and globals will
have longer names.
7. No underscores in package names. If you need a compound name, step back,
and re-examine why you need a compound name. If you still think you need a
compound name, lose the underscore.
8. No utils or helpers packages. If a function is not general enough to
warrant its own package, it has not been written generally enough to be a
part of a util package. Just leave it unexported and well-documented.
9. All tests should run with `go test` and outside tooling should not be
required. No, we don't need another unit testing framework. Assertion
packages are acceptable if they provide _real_ incremental value.
10. Even though we call these "rules" above, they are actually just
guidelines. Since you've read all the rules, you now know that.
If you are having trouble getting into the mood of idiomatic Go, we recommend
reading through [Effective Go](http://golang.org/doc/effective_go.html). The
[Go Blog](http://blog.golang.org/) is also a great resource. Drinking the
kool-aid is a lot easier than going thirsty.

View file

@ -1,17 +1,30 @@
FROM golang:1.8-alpine ARG GO_VERSION=1.13.8
FROM golang:${GO_VERSION}-alpine3.11 AS build
ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution
ENV DOCKER_BUILDTAGS include_oss include_gcs ENV BUILDTAGS include_oss include_gcs
ARG GOOS=linux
ARG GOARCH=amd64
ARG GOARM=6
ARG VERSION
ARG REVISION
RUN set -ex \ RUN set -ex \
&& apk add --no-cache make git build-base && apk add --no-cache make git file
WORKDIR $DISTRIBUTION_DIR WORKDIR $DISTRIBUTION_DIR
COPY . $DISTRIBUTION_DIR COPY . $DISTRIBUTION_DIR
RUN CGO_ENABLED=0 make PREFIX=/go clean binaries && file ./bin/registry | grep "statically linked"
FROM alpine:3.11
RUN set -ex \
&& apk add --no-cache ca-certificates apache2-utils
COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml
COPY --from=build /go/src/github.com/docker/distribution/bin/registry /bin/registry
RUN make PREFIX=/go clean binaries
VOLUME ["/var/lib/registry"] VOLUME ["/var/lib/registry"]
EXPOSE 5000 EXPOSE 5000
ENTRYPOINT ["registry"] ENTRYPOINT ["registry"]

144
GOVERNANCE.md Normal file
View file

@ -0,0 +1,144 @@
# docker/distribution Project Governance
Docker distribution abides by the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
For specific guidance on practical contribution steps please
see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide.
## Maintainership
There are different types of maintainers, with different responsibilities, but
all maintainers have 3 things in common:
1) They share responsibility in the project's success.
2) They have made a long-term, recurring time investment to improve the project.
3) They spend that time doing whatever needs to be done, not necessarily what
is the most interesting or fun.
Maintainers are often under-appreciated, because their work is harder to appreciate.
It's easy to appreciate a really cool and technically advanced feature. It's harder
to appreciate the absence of bugs, the slow but steady improvement in stability,
or the reliability of a release process. But those things distinguish a good
project from a great one.
## Reviewers
A reviewer is a core role within the project.
They share in reviewing issues and pull requests and their LGTM counts towards the
required LGTM count to merge a code change into the project.
Reviewers are part of the organization but do not have write access.
Becoming a reviewer is a core aspect in the journey to becoming a maintainer.
## Adding maintainers
Maintainers are first and foremost contributors that have shown they are
committed to the long term success of a project. Contributors wanting to become
maintainers are expected to be deeply involved in contributing code, pull
request review, and triage of issues in the project for more than three months.
Just contributing does not make you a maintainer, it is about building trust
with the current maintainers of the project and being a person that they can
depend on and trust to make decisions in the best interest of the project.
Periodically, the existing maintainers curate a list of contributors that have
shown regular activity on the project over the prior months. From this list,
maintainer candidates are selected and proposed in a pull request or a
maintainers communication channel.
After a candidate has been announced to the maintainers, the existing
maintainers are given five business days to discuss the candidate, raise
objections and cast their vote. Votes may take place on the communication
channel or via pull request comment. Candidates must be approved by at least 66%
of the current maintainers by adding their vote on the mailing list. The
reviewer role has the same process but only requires 33% of current maintainers.
Only maintainers of the repository that the candidate is proposed for are
allowed to vote.
If a candidate is approved, a maintainer will contact the candidate to invite
the candidate to open a pull request that adds the contributor to the
MAINTAINERS file. The voting process may take place inside a pull request if a
maintainer has already discussed the candidacy with the candidate and a
maintainer is willing to be a sponsor by opening the pull request. The candidate
becomes a maintainer once the pull request is merged.
## Stepping down policy
Life priorities, interests, and passions can change. If you're a maintainer but
feel you must remove yourself from the list, inform other maintainers that you
intend to step down, and if possible, help find someone to pick up your work.
At the very least, ensure your work can be continued where you left off.
After you've informed other maintainers, create a pull request to remove
yourself from the MAINTAINERS file.
## Removal of inactive maintainers
Similar to the procedure for adding new maintainers, existing maintainers can
be removed from the list if they do not show significant activity on the
project. Periodically, the maintainers review the list of maintainers and their
activity over the last three months.
If a maintainer has shown insufficient activity over this period, a neutral
person will contact the maintainer to ask if they want to continue being
a maintainer. If the maintainer decides to step down as a maintainer, they
open a pull request to be removed from the MAINTAINERS file.
If the maintainer wants to remain a maintainer, but is unable to perform the
required duties they can be removed with a vote of at least 66% of the current
maintainers. In this case, maintainers should first propose the change to
maintainers via the maintainers communication channel, then open a pull request
for voting. The voting period is five business days. The voting pull request
should not come as a surpise to any maintainer and any discussion related to
performance must not be discussed on the pull request.
## How are decisions made?
Docker distribution is an open-source project with an open design philosophy.
This means that the repository is the source of truth for EVERY aspect of the
project, including its philosophy, design, road map, and APIs. *If it's part of
the project, it's in the repo. If it's in the repo, it's part of the project.*
As a result, all decisions can be expressed as changes to the repository. An
implementation change is a change to the source code. An API change is a change
to the API specification. A philosophy change is a change to the philosophy
manifesto, and so on.
All decisions affecting distribution, big and small, follow the same 3 steps:
* Step 1: Open a pull request. Anyone can do this.
* Step 2: Discuss the pull request. Anyone can do this.
* Step 3: Merge or refuse the pull request. Who does this depends on the nature
of the pull request and which areas of the project it affects.
## Helping contributors with the DCO
The [DCO or `Sign your work`](./CONTRIBUTING.md#sign-your-work)
requirement is not intended as a roadblock or speed bump.
Some contributors are not as familiar with `git`, or have used a web
based editor, and thus asking them to `git commit --amend -s` is not the best
way forward.
In this case, maintainers can update the commits based on clause (c) of the DCO.
The most trivial way for a contributor to allow the maintainer to do this, is to
add a DCO signature in a pull requests's comment, or a maintainer can simply
note that the change is sufficiently trivial that it does not substantially
change the existing contribution - i.e., a spelling change.
When you add someone's DCO, please also add your own to keep a log.
## I'm a maintainer. Should I make pull requests too?
Yes. Nobody should ever push to master directly. All changes should be
made through a pull request.
## Conflict Resolution
If you have a technical dispute that you feel has reached an impasse with a
subset of the community, any contributor may open an issue, specifically
calling for a resolution vote of the current core maintainers to resolve the
dispute. The same voting quorums required (2/3) for adding and removing
maintainers will apply to conflict resolution.

View file

@ -1,58 +1,16 @@
# Distribution maintainers file # Docker distribution project maintainers & reviewers
# #
# This file describes who runs the docker/distribution project and how. # See GOVERNANCE.md for maintainer versus reviewer roles
# This is a living document - if you see something out of date or missing, speak up!
# #
# It is structured to be consumable by both humans and programs. # MAINTAINERS
# To extract its contents programmatically, use any TOML-compliant parser. # GitHub ID, Name, Email address
"dmcgowan","Derek McGowan","derek@mcgstyle.net"
"manishtomar","Manish Tomar","manish.tomar@docker.com"
"stevvooe","Stephen Day","stevvooe@gmail.com"
# #
# This file is compiled into the MAINTAINERS file in docker/opensource. # REVIEWERS
# # GitHub ID, Name, Email address
[Org] "caervs","Ryan Abrams","rdabrams@gmail.com"
[Org."Core maintainers"] "davidswu","David Wu","dwu7401@gmail.com"
people = [ "RobbKistler","Robb Kistler","robb.kistler@docker.com"
"aaronlehmann", "thajeztah","Sebastiaan van Stijn","github@gone.nl"
"dmcgowan",
"dmp42",
"richardscothern",
"shykes",
"stevvooe",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.dmcgowan]
Name = "Derek McGowan"
Email = "derek@mcgstyle.net"
GitHub = "dmcgowan"
[people.dmp42]
Name = "Olivier Gambier"
Email = "olivier@docker.com"
GitHub = "dmp42"
[people.richardscothern]
Name = "Richard Scothern"
Email = "richard.scothern@gmail.com"
GitHub = "richardscothern"
[people.shykes]
Name = "Solomon Hykes"
Email = "solomon@docker.com"
GitHub = "shykes"
[people.stevvooe]
Name = "Stephen Day"
Email = "stephen.day@docker.com"
GitHub = "stevvooe"

144
Makefile
View file

@ -1,9 +1,21 @@
# Set an output prefix, which is the local directory if not specified # Root directory of the project (absolute path).
PREFIX?=$(shell pwd) ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
# Used to populate version variable in main package. # Used to populate version variable in main package.
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always) VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
REVISION ?= $(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi)
PKG=github.com/docker/distribution
# Project packages.
PACKAGES=$(shell go list -tags "${BUILDTAGS}" ./... | grep -v /vendor/)
INTEGRATION_PACKAGE=${PKG}
COVERAGE_PACKAGES=$(filter-out ${PKG}/registry/storage/driver/%,${PACKAGES})
# Project binaries.
COMMANDS=registry digest registry-api-descriptor-template
# Allow turning off function inlining and variable registerization # Allow turning off function inlining and variable registerization
ifeq (${DISABLE_OPTIMIZATION},true) ifeq (${DISABLE_OPTIMIZATION},true)
@ -11,88 +23,80 @@ ifeq (${DISABLE_OPTIMIZATION},true)
VERSION:="$(VERSION)-noopt" VERSION:="$(VERSION)-noopt"
endif endif
GO_LDFLAGS=-ldflags "-X `go list ./version`.Version=$(VERSION)" WHALE = "+"
.PHONY: all build binaries clean dep-restore dep-save dep-validate fmt lint test test-full vet # Go files
#
TESTFLAGS_RACE=
GOFILES=$(shell find . -type f -name '*.go')
GO_TAGS=$(if $(BUILDTAGS),-tags "$(BUILDTAGS)",)
GO_LDFLAGS=-ldflags '-s -w -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PKG) $(EXTRA_LDFLAGS)'
BINARIES=$(addprefix bin/,$(COMMANDS))
# Flags passed to `go test`
TESTFLAGS ?= -v $(TESTFLAGS_RACE)
TESTFLAGS_PARALLEL ?= 8
.PHONY: all build binaries check clean test test-race test-full integration coverage
.DEFAULT: all .DEFAULT: all
all: fmt vet lint build test binaries
AUTHORS: .mailmap .git/HEAD all: binaries
git log --format='%aN <%aE>' | sort -fu > $@
# This only needs to be generated by hand when cutting full releases. # This only needs to be generated by hand when cutting full releases.
version/version.go: version/version.go:
@echo "$(WHALE) $@"
./version/version.sh > $@ ./version/version.sh > $@
# Required for go 1.5 to build check: ## run all linters (TODO: enable "unused", "varcheck", "ineffassign", "unconvert", "staticheck", "goimports", "structcheck")
GO15VENDOREXPERIMENT := 1 @echo "$(WHALE) $@"
@GO111MODULE=off golangci-lint run
# Go files test: ## run tests, except integration test with test.short
GOFILES=$(shell find . -type f -name '*.go') @echo "$(WHALE) $@"
@go test ${GO_TAGS} -test.short ${TESTFLAGS} $(filter-out ${INTEGRATION_PACKAGE},${PACKAGES})
# Package list test-race: ## run tests, except integration test with test.short and race
PKGS=$(shell go list -tags "${DOCKER_BUILDTAGS}" ./... | grep -v ^github.com/docker/distribution/vendor/) @echo "$(WHALE) $@"
@go test ${GO_TAGS} -race -test.short ${TESTFLAGS} $(filter-out ${INTEGRATION_PACKAGE},${PACKAGES})
# Resolving binary dependencies for specific targets test-full: ## run tests, except integration tests
GOLINT=$(shell which golint || echo '') @echo "$(WHALE) $@"
VNDR=$(shell which vndr || echo '') @go test ${GO_TAGS} ${TESTFLAGS} $(filter-out ${INTEGRATION_PACKAGE},${PACKAGES})
${PREFIX}/bin/registry: $(GOFILES) integration: ## run integration tests
@echo "+ $@" @echo "$(WHALE) $@"
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry @go test ${TESTFLAGS} -parallel ${TESTFLAGS_PARALLEL} ${INTEGRATION_PACKAGE}
${PREFIX}/bin/digest: $(GOFILES) coverage: ## generate coverprofiles from the unit tests
@echo "+ $@" @echo "$(WHALE) $@"
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/digest @rm -f coverage.txt
@go test ${GO_TAGS} -i ${TESTFLAGS} $(filter-out ${INTEGRATION_PACKAGE},${COVERAGE_PACKAGES}) 2> /dev/null
@( for pkg in $(filter-out ${INTEGRATION_PACKAGE},${COVERAGE_PACKAGES}); do \
go test ${GO_TAGS} ${TESTFLAGS} \
-cover \
-coverprofile=profile.out \
-covermode=atomic $$pkg || exit; \
if [ -f profile.out ]; then \
cat profile.out >> coverage.txt; \
rm profile.out; \
fi; \
done )
${PREFIX}/bin/registry-api-descriptor-template: $(GOFILES) FORCE:
@echo "+ $@"
@go build -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry-api-descriptor-template
docs/spec/api.md: docs/spec/api.md.tmpl ${PREFIX}/bin/registry-api-descriptor-template # Build a binary from a cmd.
./bin/registry-api-descriptor-template $< > $@ bin/%: cmd/% FORCE
@echo "$(WHALE) $@${BINARY_SUFFIX}"
@go build ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@${BINARY_SUFFIX} ${GO_LDFLAGS} ${GO_TAGS} ./$<
vet: binaries: $(BINARIES) ## build binaries
@echo "+ $@" @echo "$(WHALE) $@"
@go vet -tags "${DOCKER_BUILDTAGS}" $(PKGS)
fmt:
@echo "+ $@"
@test -z "$$(gofmt -s -l . 2>&1 | grep -v ^vendor/ | tee /dev/stderr)" || \
(echo >&2 "+ please format Go code with 'gofmt -s'" && false)
lint:
@echo "+ $@"
$(if $(GOLINT), , \
$(error Please install golint: `go get -u github.com/golang/lint/golint`))
@test -z "$$($(GOLINT) ./... 2>&1 | grep -v ^vendor/ | tee /dev/stderr)"
build: build:
@echo "+ $@" @echo "$(WHALE) $@"
@go build -tags "${DOCKER_BUILDTAGS}" -v ${GO_LDFLAGS} $(PKGS) @go build ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${GO_LDFLAGS} ${GO_TAGS} $(PACKAGES)
test: clean: ## clean up binaries
@echo "+ $@" @echo "$(WHALE) $@"
@go test -test.short -tags "${DOCKER_BUILDTAGS}" $(PKGS) @rm -f $(BINARIES)
test-full:
@echo "+ $@"
@go test -tags "${DOCKER_BUILDTAGS}" $(PKGS)
binaries: ${PREFIX}/bin/registry ${PREFIX}/bin/digest ${PREFIX}/bin/registry-api-descriptor-template
@echo "+ $@"
clean:
@echo "+ $@"
@rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/digest" "${PREFIX}/bin/registry-api-descriptor-template"
dep-validate:
@echo "+ $@"
$(if $(VNDR), , \
$(error Please install vndr: go get github.com/lk4d4/vndr))
@rm -Rf .vendor.bak
@mv vendor .vendor.bak
@$(VNDR)
@test -z "$$(diff -r vendor .vendor.bak 2>&1 | tee /dev/stderr)" || \
(echo >&2 "+ inconsistent dependencies! what you have in vendor.conf does not match with what you have in vendor" && false)
@rm -Rf .vendor.bak

View file

@ -2,31 +2,32 @@
The Docker toolset to pack, ship, store, and deliver content. The Docker toolset to pack, ship, store, and deliver content.
This repository's main product is the Docker Registry 2.0 implementation This repository's main product is the Open Source Docker Registry implementation
for storing and distributing Docker images. It supersedes the for storing and distributing Docker and OCI images using the
[docker/docker-registry](https://github.com/docker/docker-registry) [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec).
project with a new API design, focused around security and performance. The goal of this project is to provide a simple, secure, and scalable base
for building a registry solution or running a simple private registry.
<img src="https://www.docker.com/sites/default/files/oyster-registry-3.png" width=200px/> <img src="https://www.docker.com/sites/default/files/oyster-registry-3.png" width=200px/>
[![Circle CI](https://circleci.com/gh/docker/distribution/tree/master.svg?style=svg)](https://circleci.com/gh/docker/distribution/tree/master) [![Build Status](https://travis-ci.org/docker/distribution.svg?branch=master)](https://travis-ci.org/docker/distribution)
[![GoDoc](https://godoc.org/github.com/docker/distribution?status.svg)](https://godoc.org/github.com/docker/distribution) [![GoDoc](https://godoc.org/github.com/docker/distribution?status.svg)](https://godoc.org/github.com/docker/distribution)
This repository contains the following components: This repository contains the following components:
|**Component** |Description | |**Component** |Description |
|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **registry** | An implementation of the [Docker Registry HTTP API V2](docs/spec/api.md) for use with docker 1.6+. | | **registry** | An implementation of the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec). |
| **libraries** | A rich set of libraries for interacting with distribution components. Please see [godoc](https://godoc.org/github.com/docker/distribution) for details. **Note**: These libraries are **unstable**. | | **libraries** | A rich set of libraries for interacting with distribution components. Please see [godoc](https://godoc.org/github.com/docker/distribution) for details. **Note**: The interfaces for these libraries are **unstable**. |
| **specifications** | _Distribution_ related specifications are available in [docs/spec](docs/spec) |
| **documentation** | Docker's full documentation set is available at [docs.docker.com](https://docs.docker.com). This repository [contains the subset](docs/) related just to the registry. | | **documentation** | Docker's full documentation set is available at [docs.docker.com](https://docs.docker.com). This repository [contains the subset](docs/) related just to the registry. |
### How does this integrate with Docker engine? ### How does this integrate with Docker, containerd, and other OCI client?
This project should provide an implementation to a V2 API for use in the [Docker Clients implement against the OCI specification and communicate with the
core project](https://github.com/docker/docker). The API should be embeddable registry using HTTP. This project contains an client implementation which
and simplify the process of securely pulling and pushing content from `docker` is currently in use by Docker, however, it is deprecated for the
daemons. [implementation in containerd](https://github.com/containerd/containerd/tree/master/remotes/docker)
and will not support new features.
### What are the long term goals of the Distribution project? ### What are the long term goals of the Distribution project?
@ -43,18 +44,6 @@ system that allow users to:
* Implement their own home made solution through good specs, and solid * Implement their own home made solution through good specs, and solid
extensions mechanism. extensions mechanism.
## More about Registry 2.0
The new registry implementation provides the following benefits:
- faster push and pull
- new, more efficient implementation
- simplified deployment
- pluggable storage backend
- webhook notifications
For information on upcoming functionality, please see [ROADMAP.md](ROADMAP.md).
### Who needs to deploy a registry? ### Who needs to deploy a registry?
By default, Docker users pull images from Docker's public registry instance. By default, Docker users pull images from Docker's public registry instance.
@ -76,56 +65,27 @@ may be the better choice.
For those who have previously deployed their own registry based on the Registry 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, 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 data migration is required. A tool to assist with migration efforts has been
created. For more information see [docker/migrator] created. For more information see [docker/migrator](https://github.com/docker/migrator).
(https://github.com/docker/migrator).
## Contribute ## Contribution
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute
issues, fixes, and patches to this project. If you are contributing code, see issues, fixes, and patches to this project. If you are contributing code, see
the instructions for [building a development environment](BUILDING.md). the instructions for [building a development environment](BUILDING.md).
## Support ## Communication
If any issues are encountered while using the _Distribution_ project, several For async communication and long running discussions please use issues and pull requests on the github repo.
avenues are available for support: This will be the best place to discuss design and implementation.
<table> For sync communication we have a community slack with a #distribution channel that everyone is welcome to join and chat about development.
<tr>
<th align="left">
IRC
</th>
<td>
#docker-distribution on FreeNode
</td>
</tr>
<tr>
<th align="left">
Issue Tracker
</th>
<td>
github.com/docker/distribution/issues
</td>
</tr>
<tr>
<th align="left">
Google Groups
</th>
<td>
https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
</td>
</tr>
<tr>
<th align="left">
Mailing List
</th>
<td>
docker@dockerproject.org
</td>
</tr>
</table>
**Slack:** Catch us in the #distribution channels on dockercommunity.slack.com.
[Click here for an invite to Docker community slack.](https://dockr.ly/slack)
## License ## Licenses
This project is distributed under [Apache License, Version 2.0](LICENSE). The distribution codebase is released under the [Apache 2.0 license](LICENSE).
The README.md file, and files in the "docs" folder are licensed under the
Creative Commons Attribution 4.0 International License. You may obtain a
copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.

View file

@ -1,36 +0,0 @@
## Registry Release Checklist
10. Compile release notes detailing features and since the last release. Update the `CHANGELOG.md` file.
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.
50. Push the signed tag
60. Create a new [release](https://github.com/docker/distribution/releases). In the case of a release candidate, tick the `pre-release` checkbox.
70. Update the registry binary in [distribution library image repo](https://github.com/docker/distribution-library-image) by running the update script and opening a pull request.
80. Update the official image. Add the new version in the [official images repo](https://github.com/docker-library/official-images) by appending a new version to the `registry/registry` file with the git hash pointed to by the signed tag. Update the major version to point to the latest version and the minor version to point to new patch release if necessary.
e.g. to release `2.3.1`
`2.3.1 (new)`
`2.3.0 -> 2.3.0` can be removed
`2 -> 2.3.1`
`2.3 -> 2.3.1`
90. Build a new distribution/registry image on [Docker hub](https://hub.docker.com/u/distribution/dashboard) by adding a new automated build with the new tag and re-building the images.

View file

@ -1,15 +1,16 @@
package distribution package distribution
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"time" "time"
"github.com/docker/distribution/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
var ( var (
@ -66,12 +67,19 @@ type Descriptor struct {
Size int64 `json:"size,omitempty"` Size int64 `json:"size,omitempty"`
// Digest uniquely identifies the content. A byte stream can be verified // Digest uniquely identifies the content. A byte stream can be verified
// against against this digest. // against this digest.
Digest digest.Digest `json:"digest,omitempty"` Digest digest.Digest `json:"digest,omitempty"`
// URLs contains the source URLs of this content. // URLs contains the source URLs of this content.
URLs []string `json:"urls,omitempty"` URLs []string `json:"urls,omitempty"`
// Annotations contains arbitrary metadata relating to the targeted content.
Annotations map[string]string `json:"annotations,omitempty"`
// Platform describes the platform which the image in the manifest runs on.
// This should only be used when referring to a manifest.
Platform *v1.Platform `json:"platform,omitempty"`
// NOTE: Before adding a field here, please ensure that all // NOTE: Before adding a field here, please ensure that all
// other options have been exhausted. Much of the type relationships // other options have been exhausted. Much of the type relationships
// depend on the simplicity of this type. // depend on the simplicity of this type.
@ -152,7 +160,7 @@ type BlobProvider interface {
// BlobServer can serve blobs via http. // BlobServer can serve blobs via http.
type BlobServer interface { 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 // service may decide to redirect the client elsewhere or serve the data
// directly. // directly.
// //

View file

@ -1,97 +0,0 @@
# Pony-up!
machine:
pre:
# Install gvm
- bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/1.0.22/binscripts/gvm-installer)
# Install codecov for coverage
- pip install --user codecov
post:
# go
- gvm install go1.8 --prefer-binary --name=stable
environment:
# Convenient shortcuts to "common" locations
CHECKOUT: /home/ubuntu/$CIRCLE_PROJECT_REPONAME
BASE_DIR: src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
# Trick circle brainflat "no absolute path" behavior
BASE_STABLE: ../../../$HOME/.gvm/pkgsets/stable/global/$BASE_DIR
DOCKER_BUILDTAGS: "include_oss include_gcs"
# Workaround Circle parsing dumb bugs and/or YAML wonkyness
CIRCLE_PAIN: "mode: set"
hosts:
# Not used yet
fancy: 127.0.0.1
dependencies:
pre:
# Copy the code to the gopath of all go versions
- >
gvm use stable &&
mkdir -p "$(dirname $BASE_STABLE)" &&
cp -R "$CHECKOUT" "$BASE_STABLE"
override:
# Install dependencies for every copied clone/go version
- gvm use stable && go get github.com/lk4d4/vndr:
pwd: $BASE_STABLE
post:
# For the stable go version, additionally install linting tools
- >
gvm use stable &&
go get github.com/axw/gocov/gocov github.com/golang/lint/golint
test:
pre:
# Output the go versions we are going to test
# - gvm use old && go version
- gvm use stable && go version
# Ensure validation of dependencies
- gvm use stable && if test -n "`git diff --stat=1000 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 && go install $(go list ./... | grep -v "/vendor/"):
pwd: $BASE_STABLE
# FMT
- gvm use stable && make fmt:
pwd: $BASE_STABLE
# VET
- gvm use stable && make vet:
pwd: $BASE_STABLE
# LINT
- gvm use stable && make lint:
pwd: $BASE_STABLE
override:
# Test stable, and report
- gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | grep -v pluginloader | 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
# coverpkg changes the signature of compiled packages
- gvm use stable; export PACKAGE=github.com/docker/distribution/registry/pluginloader; go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/$PACKAGE/coverage.out $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={}; go test -race -tags "$DOCKER_BUILDTAGS" -test.short $PACKAGE':
timeout: 1000
pwd: $BASE_STABLE
post:
# Report to codecov
- bash <(curl -s https://codecov.io/bash):
pwd: $BASE_STABLE
## Notes
# Do we want these as well?
# - go get code.google.com/p/go.tools/cmd/goimports
# - test -z "$(goimports -l -w ./... | tee /dev/stderr)"
# http://labix.org/gocheck

View file

@ -9,6 +9,9 @@ import (
"github.com/docker/distribution/version" "github.com/docker/distribution/version"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
_ "crypto/sha256"
_ "crypto/sha512"
) )
var ( var (
@ -32,7 +35,7 @@ func init() {
func usage() { func usage() {
fmt.Fprintf(os.Stderr, "usage: %s [files...]\n", os.Args[0]) 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 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 to standard out. If no files are provided, the digest of stdin will
be calculated. be calculated.

View file

@ -21,7 +21,7 @@ import (
"text/template" "text/template"
"github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/api/v2" v2 "github.com/docker/distribution/registry/api/v2"
) )
var spaceRegex = regexp.MustCompile(`\n\s*`) var spaceRegex = regexp.MustCompile(`\n\s*`)

View file

@ -29,6 +29,8 @@ redis:
readtimeout: 10ms readtimeout: 10ms
writetimeout: 10ms writetimeout: 10ms
notifications: notifications:
events:
includereferences: true
endpoints: endpoints:
- name: local-8082 - name: local-8082
url: http://localhost:5003/callback url: http://localhost:5003/callback

View file

@ -31,7 +31,10 @@ storage:
http: http:
addr: :5000 addr: :5000
debug: debug:
addr: localhost:5001 addr: :5001
prometheus:
enabled: true
path: /metrics
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
redis: redis:
@ -44,6 +47,8 @@ redis:
readtimeout: 10ms readtimeout: 10ms
writetimeout: 10ms writetimeout: 10ms
notifications: notifications:
events:
includereferences: true
endpoints: endpoints:
- name: local-5003 - name: local-5003
url: http://localhost:5003/callback url: http://localhost:5003/callback

View file

@ -11,6 +11,10 @@ http:
addr: :5000 addr: :5000
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
auth:
htpasswd:
realm: basic-realm
path: /etc/registry
health: health:
storagedriver: storagedriver:
enabled: true enabled: true

View file

@ -12,11 +12,11 @@ import (
_ "github.com/docker/distribution/registry/storage/driver/filesystem" _ "github.com/docker/distribution/registry/storage/driver/filesystem"
_ "github.com/docker/distribution/registry/storage/driver/gcs" _ "github.com/docker/distribution/registry/storage/driver/gcs"
_ "github.com/docker/distribution/registry/storage/driver/inmemory" _ "github.com/docker/distribution/registry/storage/driver/inmemory"
_ "github.com/docker/distribution/registry/storage/driver/middleware/alicdn"
_ "github.com/docker/distribution/registry/storage/driver/middleware/cloudfront" _ "github.com/docker/distribution/registry/storage/driver/middleware/cloudfront"
_ "github.com/docker/distribution/registry/storage/driver/middleware/redirect" _ "github.com/docker/distribution/registry/storage/driver/middleware/redirect"
_ "github.com/docker/distribution/registry/storage/driver/oss" _ "github.com/docker/distribution/registry/storage/driver/oss"
_ "github.com/docker/distribution/registry/storage/driver/s3-aws" _ "github.com/docker/distribution/registry/storage/driver/s3-aws"
_ "github.com/docker/distribution/registry/storage/driver/s3-goamz"
_ "github.com/docker/distribution/registry/storage/driver/swift" _ "github.com/docker/distribution/registry/storage/driver/swift"
) )

View file

@ -1,6 +1,7 @@
package configuration package configuration
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -29,7 +30,7 @@ type Configuration struct {
} `yaml:"accesslog,omitempty"` } `yaml:"accesslog,omitempty"`
// Level is the granularity at which registry operations are logged. // Level is the granularity at which registry operations are logged.
Level Loglevel `yaml:"level"` Level Loglevel `yaml:"level,omitempty"`
// Formatter overrides the default formatter with another. Options // Formatter overrides the default formatter with another. Options
// include "text", "json" and "logstash". // include "text", "json" and "logstash".
@ -44,13 +45,11 @@ type Configuration struct {
Hooks []LogHook `yaml:"hooks,omitempty"` Hooks []LogHook `yaml:"hooks,omitempty"`
} }
// Loglevel is the level at which registry operations are logged. This is // Loglevel is the level at which registry operations are logged.
// deprecated. Please use Log.Level in the future. //
// Deprecated: Use Log.Level instead.
Loglevel Loglevel `yaml:"loglevel,omitempty"` Loglevel Loglevel `yaml:"loglevel,omitempty"`
// Plugins is a path where plugins are expected to be found
Plugins []string `yaml:"plugins,omitempty"`
// Storage is the configuration for the registry's storage driver // Storage is the configuration for the registry's storage driver
Storage Storage `yaml:"storage"` Storage Storage `yaml:"storage"`
@ -86,6 +85,10 @@ type Configuration struct {
// Location headers // Location headers
RelativeURLs bool `yaml:"relativeurls,omitempty"` RelativeURLs bool `yaml:"relativeurls,omitempty"`
// Amount of time to wait for connection to drain before shutting down when registry
// receives a stop signal
DrainTimeout time.Duration `yaml:"draintimeout,omitempty"`
// TLS instructs the http server to listen with a TLS configuration. // TLS instructs the http server to listen with a TLS configuration.
// This only support simple tls configuration with a cert and key. // This only support simple tls configuration with a cert and key.
// Mostly, this is useful for testing situations or simple deployments // Mostly, this is useful for testing situations or simple deployments
@ -105,6 +108,9 @@ type Configuration struct {
// A file may contain multiple CA certificates encoded as PEM // A file may contain multiple CA certificates encoded as PEM
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
// Specifies the lowest TLS version allowed
MinimumTLS string `yaml:"minimumtls,omitempty"`
// LetsEncrypt is used to configuration setting up TLS through // LetsEncrypt is used to configuration setting up TLS through
// Let's Encrypt instead of manually specifying certificate and // Let's Encrypt instead of manually specifying certificate and
// key. If a TLS certificate is specified, the Let's Encrypt // key. If a TLS certificate is specified, the Let's Encrypt
@ -116,6 +122,10 @@ type Configuration struct {
// Email is the email to use during Let's Encrypt registration // Email is the email to use during Let's Encrypt registration
Email string `yaml:"email,omitempty"` Email string `yaml:"email,omitempty"`
// Hosts specifies the hosts which are allowed to obtain Let's
// Encrypt certificates.
Hosts []string `yaml:"hosts,omitempty"`
} `yaml:"letsencrypt,omitempty"` } `yaml:"letsencrypt,omitempty"`
} `yaml:"tls,omitempty"` } `yaml:"tls,omitempty"`
@ -131,11 +141,16 @@ type Configuration struct {
Debug struct { Debug struct {
// Addr specifies the bind address for the debug server. // Addr specifies the bind address for the debug server.
Addr string `yaml:"addr,omitempty"` Addr string `yaml:"addr,omitempty"`
// Prometheus configures the Prometheus telemetry endpoint.
Prometheus struct {
Enabled bool `yaml:"enabled,omitempty"`
Path string `yaml:"path,omitempty"`
} `yaml:"prometheus,omitempty"`
} `yaml:"debug,omitempty"` } `yaml:"debug,omitempty"`
// HTTP2 configuration options // HTTP2 configuration options
HTTP2 struct { 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. // to connect via http2. If set to true, only http/1.1 is supported.
Disabled bool `yaml:"disabled,omitempty"` Disabled bool `yaml:"disabled,omitempty"`
} `yaml:"http2,omitempty"` } `yaml:"http2,omitempty"`
@ -186,6 +201,8 @@ type Configuration struct {
// TrustKey is the signing key to use for adding the signature to // TrustKey is the signing key to use for adding the signature to
// schema1 manifests. // schema1 manifests.
TrustKey string `yaml:"signingkeyfile,omitempty"` TrustKey string `yaml:"signingkeyfile,omitempty"`
// Enabled determines if schema1 manifests should be pullable
Enabled bool `yaml:"enabled,omitempty"`
} `yaml:"schema1,omitempty"` } `yaml:"schema1,omitempty"`
} `yaml:"compatibility,omitempty"` } `yaml:"compatibility,omitempty"`
@ -238,7 +255,7 @@ type LogHook struct {
// Levels set which levels of log message will let hook executed. // Levels set which levels of log message will let hook executed.
Levels []string `yaml:"levels,omitempty"` Levels []string `yaml:"levels,omitempty"`
// MailOptions allows user to configurate email parameters. // MailOptions allows user to configure email parameters.
MailOptions MailOptions `yaml:"options,omitempty"` MailOptions MailOptions `yaml:"options,omitempty"`
} }
@ -332,7 +349,7 @@ type Health struct {
type v0_1Configuration Configuration type v0_1Configuration Configuration
// UnmarshalYAML implements the yaml.Unmarshaler interface // 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 { func (version *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
var versionString string var versionString string
err := unmarshal(&versionString) err := unmarshal(&versionString)
@ -374,7 +391,7 @@ func (loglevel *Loglevel) UnmarshalYAML(unmarshal func(interface{}) error) error
switch loglevelString { switch loglevelString {
case "error", "warn", "info", "debug": case "error", "warn", "info", "debug":
default: default:
return fmt.Errorf("Invalid loglevel %s Must be one of [error, warn, info, debug]", loglevelString) return fmt.Errorf("invalid loglevel %s Must be one of [error, warn, info, debug]", loglevelString)
} }
*loglevel = Loglevel(loglevelString) *loglevel = Loglevel(loglevelString)
@ -449,7 +466,7 @@ func (storage *Storage) UnmarshalYAML(unmarshal func(interface{}) error) error {
} }
if len(types) > 1 { if len(types) > 1 {
return fmt.Errorf("Must provide exactly one storage type. Provided: %v", types) return fmt.Errorf("must provide exactly one storage type. Provided: %v", types)
} }
} }
*storage = storageMap *storage = storageMap
@ -537,6 +554,8 @@ func (auth Auth) MarshalYAML() (interface{}, error) {
// Notifications configures multiple http endpoints. // Notifications configures multiple http endpoints.
type Notifications struct { type Notifications struct {
// EventConfig is the configuration for the event format that is sent to each Endpoint.
EventConfig Events `yaml:"events,omitempty"`
// Endpoints is a list of http configurations for endpoints that // Endpoints is a list of http configurations for endpoints that
// respond to webhook notifications. In the future, we may allow other // respond to webhook notifications. In the future, we may allow other
// kinds of endpoints, such as external queues. // kinds of endpoints, such as external queues.
@ -554,6 +573,18 @@ type Endpoint struct {
Threshold int `yaml:"threshold"` // circuit breaker threshold before backing off on failure Threshold int `yaml:"threshold"` // circuit breaker threshold before backing off on failure
Backoff time.Duration `yaml:"backoff"` // backoff duration Backoff time.Duration `yaml:"backoff"` // backoff duration
IgnoredMediaTypes []string `yaml:"ignoredmediatypes"` // target media types to ignore IgnoredMediaTypes []string `yaml:"ignoredmediatypes"` // target media types to ignore
Ignore Ignore `yaml:"ignore"` // ignore event types
}
// Events configures notification events.
type Events struct {
IncludeReferences bool `yaml:"includereferences"` // include reference data in manifest events
}
//Ignore configures mediaTypes and actions of the event, that it won't be propagated
type Ignore struct {
MediaTypes []string `yaml:"mediatypes"` // target media types to ignore
Actions []string `yaml:"actions"` // ignore action types
} }
// Reporting defines error reporting methods. // Reporting defines error reporting methods.
@ -626,15 +657,22 @@ func Parse(rd io.Reader) (*Configuration, error) {
ParseAs: reflect.TypeOf(v0_1Configuration{}), ParseAs: reflect.TypeOf(v0_1Configuration{}),
ConversionFunc: func(c interface{}) (interface{}, error) { ConversionFunc: func(c interface{}) (interface{}, error) {
if v0_1, ok := c.(*v0_1Configuration); ok { if v0_1, ok := c.(*v0_1Configuration); ok {
if v0_1.Loglevel == Loglevel("") { if v0_1.Log.Level == Loglevel("") {
v0_1.Loglevel = Loglevel("info") if v0_1.Loglevel != Loglevel("") {
v0_1.Log.Level = v0_1.Loglevel
} else {
v0_1.Log.Level = Loglevel("info")
}
}
if v0_1.Loglevel != Loglevel("") {
v0_1.Loglevel = Loglevel("")
} }
if v0_1.Storage.Type() == "" { 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 return (*Configuration)(v0_1), nil
} }
return nil, fmt.Errorf("Expected *v0_1Configuration, received %#v", c) return nil, fmt.Errorf("expected *v0_1Configuration, received %#v", c)
}, },
}, },
}) })

View file

@ -7,6 +7,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"time"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -22,14 +23,14 @@ var configStruct = Configuration{
AccessLog struct { AccessLog struct {
Disabled bool `yaml:"disabled,omitempty"` Disabled bool `yaml:"disabled,omitempty"`
} `yaml:"accesslog,omitempty"` } `yaml:"accesslog,omitempty"`
Level Loglevel `yaml:"level"` Level Loglevel `yaml:"level,omitempty"`
Formatter string `yaml:"formatter,omitempty"` Formatter string `yaml:"formatter,omitempty"`
Fields map[string]interface{} `yaml:"fields,omitempty"` Fields map[string]interface{} `yaml:"fields,omitempty"`
Hooks []LogHook `yaml:"hooks,omitempty"` Hooks []LogHook `yaml:"hooks,omitempty"`
}{ }{
Level: "info",
Fields: map[string]interface{}{"environment": "test"}, Fields: map[string]interface{}{"environment": "test"},
}, },
Loglevel: "info",
Storage: Storage{ Storage: Storage{
"s3": Parameters{ "s3": Parameters{
"region": "us-east-1", "region": "us-east-1",
@ -63,6 +64,10 @@ var configStruct = Configuration{
"Authorization": []string{"Bearer <example>"}, "Authorization": []string{"Bearer <example>"},
}, },
IgnoredMediaTypes: []string{"application/octet-stream"}, IgnoredMediaTypes: []string{"application/octet-stream"},
Ignore: Ignore{
MediaTypes: []string{"application/octet-stream"},
Actions: []string{"pull"},
},
}, },
}, },
}, },
@ -73,18 +78,25 @@ var configStruct = Configuration{
Prefix string `yaml:"prefix,omitempty"` Prefix string `yaml:"prefix,omitempty"`
Secret string `yaml:"secret,omitempty"` Secret string `yaml:"secret,omitempty"`
RelativeURLs bool `yaml:"relativeurls,omitempty"` RelativeURLs bool `yaml:"relativeurls,omitempty"`
DrainTimeout time.Duration `yaml:"draintimeout,omitempty"`
TLS struct { TLS struct {
Certificate string `yaml:"certificate,omitempty"` Certificate string `yaml:"certificate,omitempty"`
Key string `yaml:"key,omitempty"` Key string `yaml:"key,omitempty"`
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
MinimumTLS string `yaml:"minimumtls,omitempty"`
LetsEncrypt struct { LetsEncrypt struct {
CacheFile string `yaml:"cachefile,omitempty"` CacheFile string `yaml:"cachefile,omitempty"`
Email string `yaml:"email,omitempty"` Email string `yaml:"email,omitempty"`
Hosts []string `yaml:"hosts,omitempty"`
} `yaml:"letsencrypt,omitempty"` } `yaml:"letsencrypt,omitempty"`
} `yaml:"tls,omitempty"` } `yaml:"tls,omitempty"`
Headers http.Header `yaml:"headers,omitempty"` Headers http.Header `yaml:"headers,omitempty"`
Debug struct { Debug struct {
Addr string `yaml:"addr,omitempty"` Addr string `yaml:"addr,omitempty"`
Prometheus struct {
Enabled bool `yaml:"enabled,omitempty"`
Path string `yaml:"path,omitempty"`
} `yaml:"prometheus,omitempty"`
} `yaml:"debug,omitempty"` } `yaml:"debug,omitempty"`
HTTP2 struct { HTTP2 struct {
Disabled bool `yaml:"disabled,omitempty"` Disabled bool `yaml:"disabled,omitempty"`
@ -94,9 +106,11 @@ var configStruct = Configuration{
Certificate string `yaml:"certificate,omitempty"` Certificate string `yaml:"certificate,omitempty"`
Key string `yaml:"key,omitempty"` Key string `yaml:"key,omitempty"`
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
MinimumTLS string `yaml:"minimumtls,omitempty"`
LetsEncrypt struct { LetsEncrypt struct {
CacheFile string `yaml:"cachefile,omitempty"` CacheFile string `yaml:"cachefile,omitempty"`
Email string `yaml:"email,omitempty"` Email string `yaml:"email,omitempty"`
Hosts []string `yaml:"hosts,omitempty"`
} `yaml:"letsencrypt,omitempty"` } `yaml:"letsencrypt,omitempty"`
}{ }{
ClientCAs: []string{"/path/to/ca.pem"}, ClientCAs: []string{"/path/to/ca.pem"},
@ -116,9 +130,9 @@ var configStruct = Configuration{
var configYamlV0_1 = ` var configYamlV0_1 = `
version: 0.1 version: 0.1
log: log:
level: info
fields: fields:
environment: test environment: test
loglevel: info
storage: storage:
s3: s3:
region: us-east-1 region: us-east-1
@ -142,6 +156,11 @@ notifications:
Authorization: [Bearer <example>] Authorization: [Bearer <example>]
ignoredmediatypes: ignoredmediatypes:
- application/octet-stream - application/octet-stream
ignore:
mediatypes:
- application/octet-stream
actions:
- pull
reporting: reporting:
bugsnag: bugsnag:
apikey: BugsnagApiKey apikey: BugsnagApiKey
@ -156,7 +175,8 @@ http:
// storage driver with no parameters // storage driver with no parameters
var inmemoryConfigYamlV0_1 = ` var inmemoryConfigYamlV0_1 = `
version: 0.1 version: 0.1
loglevel: info log:
level: info
storage: inmemory storage: inmemory
auth: auth:
silly: silly:
@ -170,6 +190,11 @@ notifications:
Authorization: [Bearer <example>] Authorization: [Bearer <example>]
ignoredmediatypes: ignoredmediatypes:
- application/octet-stream - application/octet-stream
ignore:
mediatypes:
- application/octet-stream
actions:
- pull
http: http:
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
@ -192,6 +217,7 @@ func (suite *ConfigSuite) TestMarshalRoundtrip(c *C) {
configBytes, err := yaml.Marshal(suite.expectedConfig) configBytes, err := yaml.Marshal(suite.expectedConfig)
c.Assert(err, IsNil) c.Assert(err, IsNil)
config, err := Parse(bytes.NewReader(configBytes)) config, err := Parse(bytes.NewReader(configBytes))
c.Log(string(configBytes))
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(config, DeepEquals, suite.expectedConfig) c.Assert(config, DeepEquals, suite.expectedConfig)
} }
@ -314,9 +340,9 @@ func (suite *ConfigSuite) TestParseWithSameEnvLoglevel(c *C) {
// TestParseWithDifferentEnvLoglevel validates that providing an environment variable defining the // TestParseWithDifferentEnvLoglevel validates that providing an environment variable defining the
// log level will override the value provided in the yaml document // log level will override the value provided in the yaml document
func (suite *ConfigSuite) TestParseWithDifferentEnvLoglevel(c *C) { func (suite *ConfigSuite) TestParseWithDifferentEnvLoglevel(c *C) {
suite.expectedConfig.Loglevel = "error" suite.expectedConfig.Log.Level = "error"
os.Setenv("REGISTRY_LOGLEVEL", "error") os.Setenv("REGISTRY_LOG_LEVEL", "error")
config, err := Parse(bytes.NewReader([]byte(configYamlV0_1))) config, err := Parse(bytes.NewReader([]byte(configYamlV0_1)))
c.Assert(err, IsNil) c.Assert(err, IsNil)
@ -516,9 +542,7 @@ func copyConfig(config Configuration) *Configuration {
} }
configCopy.Notifications = Notifications{Endpoints: []Endpoint{}} configCopy.Notifications = Notifications{Endpoints: []Endpoint{}}
for _, v := range config.Notifications.Endpoints { configCopy.Notifications.Endpoints = append(configCopy.Notifications.Endpoints, config.Notifications.Endpoints...)
configCopy.Notifications.Endpoints = append(configCopy.Notifications.Endpoints, v)
}
configCopy.HTTP.Headers = make(http.Header) configCopy.HTTP.Headers = make(http.Header)
for k, v := range config.HTTP.Headers { for k, v := range config.HTTP.Headers {

View file

@ -8,7 +8,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -122,7 +122,7 @@ func (p *Parser) Parse(in []byte, v interface{}) error {
parseInfo, ok := p.mapping[versionedStruct.Version] parseInfo, ok := p.mapping[versionedStruct.Version]
if !ok { if !ok {
return fmt.Errorf("Unsupported version: %q", versionedStruct.Version) return fmt.Errorf("unsupported version: %q", versionedStruct.Version)
} }
parseAs := reflect.New(parseInfo.ParseAs) parseAs := reflect.New(parseInfo.ParseAs)
@ -220,7 +220,7 @@ func (p *Parser) overwriteStruct(v reflect.Value, fullpath string, path []string
} }
case reflect.Ptr: case reflect.Ptr:
if field.IsNil() { if field.IsNil() {
field.Set(reflect.New(sf.Type)) field.Set(reflect.New(field.Type().Elem()))
} }
} }

View file

@ -0,0 +1,70 @@
package configuration
import (
"os"
"reflect"
. "gopkg.in/check.v1"
)
type localConfiguration struct {
Version Version `yaml:"version"`
Log *Log `yaml:"log"`
}
type Log struct {
Formatter string `yaml:"formatter,omitempty"`
}
var expectedConfig = localConfiguration{
Version: "0.1",
Log: &Log{
Formatter: "json",
},
}
type ParserSuite struct{}
var _ = Suite(new(ParserSuite))
func (suite *ParserSuite) TestParserOverwriteIninitializedPoiner(c *C) {
config := localConfiguration{}
os.Setenv("REGISTRY_LOG_FORMATTER", "json")
defer os.Unsetenv("REGISTRY_LOG_FORMATTER")
p := NewParser("registry", []VersionedParseInfo{
{
Version: "0.1",
ParseAs: reflect.TypeOf(config),
ConversionFunc: func(c interface{}) (interface{}, error) {
return c, nil
},
},
})
err := p.Parse([]byte(`{version: "0.1", log: {formatter: "text"}}`), &config)
c.Assert(err, IsNil)
c.Assert(config, DeepEquals, expectedConfig)
}
func (suite *ParserSuite) TestParseOverwriteUnininitializedPoiner(c *C) {
config := localConfiguration{}
os.Setenv("REGISTRY_LOG_FORMATTER", "json")
defer os.Unsetenv("REGISTRY_LOG_FORMATTER")
p := NewParser("registry", []VersionedParseInfo{
{
Version: "0.1",
ParseAs: reflect.TypeOf(config),
ConversionFunc: func(c interface{}) (interface{}, error) {
return c, nil
},
},
})
err := p.Parse([]byte(`{version: "0.1"}`), &config)
c.Assert(err, IsNil)
c.Assert(config, DeepEquals, expectedConfig)
}

View file

@ -1,21 +1,16 @@
package context package context
import ( import (
"context"
"sync" "sync"
"github.com/docker/distribution/uuid" "github.com/docker/distribution/uuid"
"golang.org/x/net/context"
) )
// Context is a copy of Context from the golang.org/x/net/context package.
type Context interface {
context.Context
}
// instanceContext is a context that provides only an instance id. It is // instanceContext is a context that provides only an instance id. It is
// provided as the main background context. // provided as the main background context.
type instanceContext struct { type instanceContext struct {
Context context.Context
id string // id of context, logged as "instance.id" id string // id of context, logged as "instance.id"
once sync.Once // once protect generation of the id once sync.Once // once protect generation of the id
} }
@ -42,17 +37,10 @@ var background = &instanceContext{
// Background returns a non-nil, empty Context. The background context // Background returns a non-nil, empty Context. The background context
// provides a single key, "instance.id" that is globally unique to the // provides a single key, "instance.id" that is globally unique to the
// process. // process.
func Background() Context { func Background() context.Context {
return background return background
} }
// WithValue returns a copy of parent in which the value associated with key is
// val. Use context Values only for request-scoped data that transits processes
// and APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key, val interface{}) Context {
return context.WithValue(parent, key, val)
}
// stringMapContext is a simple context implementation that checks a map for a // stringMapContext is a simple context implementation that checks a map for a
// key, falling back to a parent if not present. // key, falling back to a parent if not present.
type stringMapContext struct { type stringMapContext struct {

View file

@ -1,7 +1,6 @@
// Package context provides several utilities for working with // Package context provides several utilities for working with
// golang.org/x/net/context in http requests. Primarily, the focus is on // Go's context in http requests. Primarily, the focus is on logging relevant
// logging relevant request information but this package is not limited to // request information but this package is not limited to that purpose.
// that purpose.
// //
// The easiest way to get started is to get the background context: // The easiest way to get started is to get the background context:
// //
@ -64,7 +63,7 @@
// Note that this only affects the new context, the previous context, with the // 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, // 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 // added to the request context, is unique to that context and can have
// request scoped varaibles. // request scoped variables.
// //
// HTTP Requests // HTTP Requests
// //

View file

@ -1,6 +1,7 @@
package context package context
import ( import (
"context"
"errors" "errors"
"net" "net"
"net/http" "net/http"
@ -8,9 +9,9 @@ import (
"sync" "sync"
"time" "time"
log "github.com/Sirupsen/logrus"
"github.com/docker/distribution/uuid" "github.com/docker/distribution/uuid"
"github.com/gorilla/mux" "github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
) )
// Common errors used with this package. // Common errors used with this package.
@ -68,7 +69,7 @@ func RemoteIP(r *http.Request) string {
// is available at "http.request". Other common attributes are available under // is available at "http.request". Other common attributes are available under
// the prefix "http.request.". If a request is already present on the context, // the prefix "http.request.". If a request is already present on the context,
// this method will panic. // this method will panic.
func WithRequest(ctx Context, r *http.Request) Context { func WithRequest(ctx context.Context, r *http.Request) context.Context {
if ctx.Value("http.request") != nil { if ctx.Value("http.request") != nil {
// NOTE(stevvooe): This needs to be considered a programming error. It // NOTE(stevvooe): This needs to be considered a programming error. It
// is unlikely that we'd want to have more than one request in // is unlikely that we'd want to have more than one request in
@ -87,7 +88,7 @@ func WithRequest(ctx Context, r *http.Request) Context {
// GetRequest returns the http request in the given context. Returns // GetRequest returns the http request in the given context. Returns
// ErrNoRequestContext if the context does not have an http request associated // ErrNoRequestContext if the context does not have an http request associated
// with it. // with it.
func GetRequest(ctx Context) (*http.Request, error) { func GetRequest(ctx context.Context) (*http.Request, error) {
if r, ok := ctx.Value("http.request").(*http.Request); r != nil && ok { if r, ok := ctx.Value("http.request").(*http.Request); r != nil && ok {
return r, nil return r, nil
} }
@ -96,25 +97,13 @@ func GetRequest(ctx Context) (*http.Request, error) {
// GetRequestID attempts to resolve the current request id, if possible. An // GetRequestID attempts to resolve the current request id, if possible. An
// error is return if it is not available on the context. // error is return if it is not available on the context.
func GetRequestID(ctx Context) string { func GetRequestID(ctx context.Context) string {
return GetStringValue(ctx, "http.request.id") return GetStringValue(ctx, "http.request.id")
} }
// WithResponseWriter returns a new context and response writer that makes // WithResponseWriter returns a new context and response writer that makes
// interesting response statistics available within the context. // interesting response statistics available within the context.
func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.ResponseWriter) { func WithResponseWriter(ctx context.Context, w http.ResponseWriter) (context.Context, http.ResponseWriter) {
if closeNotifier, ok := w.(http.CloseNotifier); ok {
irwCN := &instrumentedResponseWriterCN{
instrumentedResponseWriter: instrumentedResponseWriter{
ResponseWriter: w,
Context: ctx,
},
CloseNotifier: closeNotifier,
}
return irwCN, irwCN
}
irw := instrumentedResponseWriter{ irw := instrumentedResponseWriter{
ResponseWriter: w, ResponseWriter: w,
Context: ctx, Context: ctx,
@ -125,7 +114,7 @@ func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.Respo
// GetResponseWriter returns the http.ResponseWriter from the provided // GetResponseWriter returns the http.ResponseWriter from the provided
// context. If not present, ErrNoResponseWriterContext is returned. The // context. If not present, ErrNoResponseWriterContext is returned. The
// returned instance provides instrumentation in the context. // returned instance provides instrumentation in the context.
func GetResponseWriter(ctx Context) (http.ResponseWriter, error) { func GetResponseWriter(ctx context.Context) (http.ResponseWriter, error) {
v := ctx.Value("http.response") v := ctx.Value("http.response")
rw, ok := v.(http.ResponseWriter) rw, ok := v.(http.ResponseWriter)
@ -145,7 +134,7 @@ var getVarsFromRequest = mux.Vars
// example, if looking for the variable "name", it can be accessed as // example, if looking for the variable "name", it can be accessed as
// "vars.name". Implementations that are accessing values need not know that // "vars.name". Implementations that are accessing values need not know that
// the underlying context is implemented with gorilla/mux vars. // the underlying context is implemented with gorilla/mux vars.
func WithVars(ctx Context, r *http.Request) Context { func WithVars(ctx context.Context, r *http.Request) context.Context {
return &muxVarsContext{ return &muxVarsContext{
Context: ctx, Context: ctx,
vars: getVarsFromRequest(r), vars: getVarsFromRequest(r),
@ -155,7 +144,7 @@ func WithVars(ctx Context, r *http.Request) Context {
// GetRequestLogger returns a logger that contains fields from the request in // GetRequestLogger returns a logger that contains fields from the request in
// the current context. If the request is not available in the context, no // the current context. If the request is not available in the context, no
// fields will display. Request loggers can safely be pushed onto the context. // fields will display. Request loggers can safely be pushed onto the context.
func GetRequestLogger(ctx Context) Logger { func GetRequestLogger(ctx context.Context) Logger {
return GetLogger(ctx, return GetLogger(ctx,
"http.request.id", "http.request.id",
"http.request.method", "http.request.method",
@ -171,7 +160,7 @@ func GetRequestLogger(ctx Context) Logger {
// Because the values are read at call time, pushing a logger returned from // Because the values are read at call time, pushing a logger returned from
// this function on the context will lead to missing or invalid data. Only // this function on the context will lead to missing or invalid data. Only
// call this at the end of a request, after the response has been written. // call this at the end of a request, after the response has been written.
func GetResponseLogger(ctx Context) Logger { func GetResponseLogger(ctx context.Context) Logger {
l := getLogrusLogger(ctx, l := getLogrusLogger(ctx,
"http.response.written", "http.response.written",
"http.response.status", "http.response.status",
@ -188,7 +177,7 @@ func GetResponseLogger(ctx Context) Logger {
// httpRequestContext makes information about a request available to context. // httpRequestContext makes information about a request available to context.
type httpRequestContext struct { type httpRequestContext struct {
Context context.Context
startedAt time.Time startedAt time.Time
id string id string
@ -247,7 +236,7 @@ fallback:
} }
type muxVarsContext struct { type muxVarsContext struct {
Context context.Context
vars map[string]string vars map[string]string
} }
@ -269,20 +258,12 @@ func (ctx *muxVarsContext) Value(key interface{}) interface{} {
return ctx.Context.Value(key) return ctx.Context.Value(key)
} }
// instrumentedResponseWriterCN provides response writer information in a
// context. It implements http.CloseNotifier so that users can detect
// early disconnects.
type instrumentedResponseWriterCN struct {
instrumentedResponseWriter
http.CloseNotifier
}
// instrumentedResponseWriter provides response writer information in a // instrumentedResponseWriter provides response writer information in a
// context. This variant is only used in the case where CloseNotifier is not // context. This variant is only used in the case where CloseNotifier is not
// implemented by the parent ResponseWriter. // implemented by the parent ResponseWriter.
type instrumentedResponseWriter struct { type instrumentedResponseWriter struct {
http.ResponseWriter http.ResponseWriter
Context context.Context
mu sync.Mutex mu sync.Mutex
status int status int
@ -354,13 +335,3 @@ func (irw *instrumentedResponseWriter) Value(key interface{}) interface{} {
fallback: fallback:
return irw.Context.Value(key) return irw.Context.Value(key)
} }
func (irw *instrumentedResponseWriterCN) Value(key interface{}) interface{} {
if keyStr, ok := key.(string); ok {
if keyStr == "http.response" {
return irw
}
}
return irw.instrumentedResponseWriter.Value(key)
}

View file

@ -1,10 +1,11 @@
package context package context
import ( import (
"context"
"fmt" "fmt"
"github.com/Sirupsen/logrus"
"runtime" "runtime"
"github.com/sirupsen/logrus"
) )
// Logger provides a leveled-logging interface. // Logger provides a leveled-logging interface.
@ -38,24 +39,28 @@ type Logger interface {
Warn(args ...interface{}) Warn(args ...interface{})
Warnf(format string, args ...interface{}) Warnf(format string, args ...interface{})
Warnln(args ...interface{}) Warnln(args ...interface{})
WithError(err error) *logrus.Entry
} }
type loggerKey struct{}
// WithLogger creates a new context with provided logger. // WithLogger creates a new context with provided logger.
func WithLogger(ctx Context, logger Logger) Context { func WithLogger(ctx context.Context, logger Logger) context.Context {
return WithValue(ctx, "logger", logger) return context.WithValue(ctx, loggerKey{}, logger)
} }
// GetLoggerWithField returns a logger instance with the specified field key // GetLoggerWithField returns a logger instance with the specified field key
// and value without affecting the context. Extra specified keys will be // and value without affecting the context. Extra specified keys will be
// resolved from the context. // resolved from the context.
func GetLoggerWithField(ctx Context, key, value interface{}, keys ...interface{}) Logger { func GetLoggerWithField(ctx context.Context, key, value interface{}, keys ...interface{}) Logger {
return getLogrusLogger(ctx, keys...).WithField(fmt.Sprint(key), value) return getLogrusLogger(ctx, keys...).WithField(fmt.Sprint(key), value)
} }
// GetLoggerWithFields returns a logger instance with the specified fields // GetLoggerWithFields returns a logger instance with the specified fields
// without affecting the context. Extra specified keys will be resolved from // without affecting the context. Extra specified keys will be resolved from
// the context. // the context.
func GetLoggerWithFields(ctx Context, fields map[interface{}]interface{}, keys ...interface{}) Logger { func GetLoggerWithFields(ctx context.Context, fields map[interface{}]interface{}, keys ...interface{}) Logger {
// must convert from interface{} -> interface{} to string -> interface{} for logrus. // must convert from interface{} -> interface{} to string -> interface{} for logrus.
lfields := make(logrus.Fields, len(fields)) lfields := make(logrus.Fields, len(fields))
for key, value := range fields { for key, value := range fields {
@ -71,7 +76,7 @@ func GetLoggerWithFields(ctx Context, fields map[interface{}]interface{}, keys .
// argument passed to GetLogger will be passed to fmt.Sprint when expanded as // argument passed to GetLogger will be passed to fmt.Sprint when expanded as
// a logging key field. If context keys are integer constants, for example, // a logging key field. If context keys are integer constants, for example,
// its recommended that a String method is implemented. // its recommended that a String method is implemented.
func GetLogger(ctx Context, keys ...interface{}) Logger { func GetLogger(ctx context.Context, keys ...interface{}) Logger {
return getLogrusLogger(ctx, keys...) return getLogrusLogger(ctx, keys...)
} }
@ -79,11 +84,11 @@ func GetLogger(ctx Context, keys ...interface{}) Logger {
// are provided, they will be resolved on the context and included in the // are provided, they will be resolved on the context and included in the
// logger. Only use this function if specific logrus functionality is // logger. Only use this function if specific logrus functionality is
// required. // required.
func getLogrusLogger(ctx Context, keys ...interface{}) *logrus.Entry { func getLogrusLogger(ctx context.Context, keys ...interface{}) *logrus.Entry {
var logger *logrus.Entry var logger *logrus.Entry
// Get a logger, if it is present. // Get a logger, if it is present.
loggerInterface := ctx.Value("logger") loggerInterface := ctx.Value(loggerKey{})
if loggerInterface != nil { if loggerInterface != nil {
if lgr, ok := loggerInterface.(*logrus.Entry); ok { if lgr, ok := loggerInterface.(*logrus.Entry); ok {
logger = lgr logger = lgr

View file

@ -1,6 +1,7 @@
package context package context
import ( import (
"context"
"runtime" "runtime"
"time" "time"
@ -36,7 +37,7 @@ import (
// //
// Notice that the function name is automatically resolved, along with the // Notice that the function name is automatically resolved, along with the
// package and a trace id is emitted that can be linked with parent ids. // package and a trace id is emitted that can be linked with parent ids.
func WithTrace(ctx Context) (Context, func(format string, a ...interface{})) { func WithTrace(ctx context.Context) (context.Context, func(format string, a ...interface{})) {
if ctx == nil { if ctx == nil {
ctx = Background() ctx = Background()
} }
@ -69,7 +70,7 @@ func WithTrace(ctx Context) (Context, func(format string, a ...interface{})) {
// also provides fast lookup for the various attributes that are available on // also provides fast lookup for the various attributes that are available on
// the trace. // the trace.
type traced struct { type traced struct {
Context context.Context
id string id string
parent string parent string
start time.Time start time.Time

View file

@ -1,6 +1,7 @@
package context package context
import ( import (
"context"
"runtime" "runtime"
"testing" "testing"
"time" "time"
@ -35,7 +36,7 @@ func TestWithTrace(t *testing.T) {
ctx, done := WithTrace(Background()) ctx, done := WithTrace(Background())
defer done("this will be emitted at end of test") defer done("this will be emitted at end of test")
checkContextForValues(t, ctx, append(base, valueTestCase{ checkContextForValues(ctx, t, append(base, valueTestCase{
key: "trace.func", key: "trace.func",
expected: f.Name(), expected: f.Name(),
})) }))
@ -48,7 +49,7 @@ func TestWithTrace(t *testing.T) {
ctx, done := WithTrace(ctx) ctx, done := WithTrace(ctx)
defer done("this should be subordinate to the other trace") defer done("this should be subordinate to the other trace")
time.Sleep(time.Second) time.Sleep(time.Second)
checkContextForValues(t, ctx, append(base, valueTestCase{ checkContextForValues(ctx, t, append(base, valueTestCase{
key: "trace.func", key: "trace.func",
expected: f.Name(), expected: f.Name(),
}, valueTestCase{ }, valueTestCase{
@ -67,8 +68,7 @@ type valueTestCase struct {
notnilorempty bool // just check not empty/not nil notnilorempty bool // just check not empty/not nil
} }
func checkContextForValues(t *testing.T, ctx Context, values []valueTestCase) { func checkContextForValues(ctx context.Context, t *testing.T, values []valueTestCase) {
for _, testcase := range values { for _, testcase := range values {
v := ctx.Value(testcase.key) v := ctx.Value(testcase.key)
if testcase.notnilorempty { if testcase.notnilorempty {

View file

@ -1,13 +1,14 @@
package context package context
import ( import (
"context"
"time" "time"
) )
// Since looks up key, which should be a time.Time, and returns the duration // Since looks up key, which should be a time.Time, and returns the duration
// since that time. If the key is not found, the value returned will be zero. // since that time. If the key is not found, the value returned will be zero.
// This is helpful when inferring metrics related to context execution times. // This is helpful when inferring metrics related to context execution times.
func Since(ctx Context, key interface{}) time.Duration { func Since(ctx context.Context, key interface{}) time.Duration {
if startedAt, ok := ctx.Value(key).(time.Time); ok { if startedAt, ok := ctx.Value(key).(time.Time); ok {
return time.Since(startedAt) return time.Since(startedAt)
} }
@ -16,7 +17,7 @@ func Since(ctx Context, key interface{}) time.Duration {
// GetStringValue returns a string value from the context. The empty string // GetStringValue returns a string value from the context. The empty string
// will be returned if not found. // will be returned if not found.
func GetStringValue(ctx Context, key interface{}) (value string) { func GetStringValue(ctx context.Context, key interface{}) (value string) {
if valuev, ok := ctx.Value(key).(string); ok { if valuev, ok := ctx.Value(key).(string); ok {
value = valuev value = valuev
} }

View file

@ -1,16 +1,22 @@
package context package context
import "context"
type versionKey struct{}
func (versionKey) String() string { return "version" }
// WithVersion stores the application version in the context. The new context // WithVersion stores the application version in the context. The new context
// gets a logger to ensure log messages are marked with the application // gets a logger to ensure log messages are marked with the application
// version. // version.
func WithVersion(ctx Context, version string) Context { func WithVersion(ctx context.Context, version string) context.Context {
ctx = WithValue(ctx, "version", version) ctx = context.WithValue(ctx, versionKey{}, version)
// push a new logger onto the stack // push a new logger onto the stack
return WithLogger(ctx, GetLogger(ctx, "version")) return WithLogger(ctx, GetLogger(ctx, versionKey{}))
} }
// GetVersion returns the application version from the context. An empty // GetVersion returns the application version from the context. An empty
// string may returned if the version was not set on the context. // string may returned if the version was not set on the context.
func GetVersion(ctx Context) string { func GetVersion(ctx context.Context) string {
return GetStringValue(ctx, "version") return GetStringValue(ctx, versionKey{})
} }

View file

@ -70,7 +70,7 @@ to the 1.0 registry. Requests from newer clients will route to the 2.0 registry.
Removing intermediate container edb84c2b40cb Removing intermediate container edb84c2b40cb
Successfully built 74acc70fa106 Successfully built 74acc70fa106
The commmand outputs its progress until it completes. The command outputs its progress until it completes.
4. Start your configuration with compose. 4. Start your configuration with compose.
@ -123,22 +123,22 @@ 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. 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 * Hostname was NOT found in DNS cache
* Trying 127.0.0.1... * Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 32777 (#0) * Connected to localhost (127.0.0.1) port 32777 (#0)
> GET /v2/registry1/tags/list HTTP/1.1 > GET /v2/registry1/tags/list HTTP/1.1
> User-Agent: curl/7.36.0 > User-Agent: curl/7.36.0
> Host: localhost:32777 > Host: localhost:5000
> Accept: */* > Accept: */*
> >
< HTTP/1.1 200 OK < HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8 < Content-Type: application/json
< Docker-Distribution-Api-Version: registry/2.0 < Docker-Distribution-Api-Version: registry/2.0
< Date: Tue, 14 Apr 2015 22:34:13 GMT < Date: Tue, 14 Apr 2015 22:34:13 GMT
< Content-Length: 39 < Content-Length: 39
< <
{"name":"registry1","tags":["latest"]} {"name":"registry_one","tags":["latest"]}
* Connection #0 to host localhost left intact * Connection #0 to host localhost left intact
This example refers to the specific port assigned to the 2.0 registry. You saw This example refers to the specific port assigned to the 2.0 registry. You saw

View file

@ -4,3 +4,6 @@ proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900; proxy_read_timeout 900;
proxy_send_timeout 300;
proxy_request_buffering off; (see issue #2292 - https://github.com/moby/moby/issues/2292)
proxy_http_version 1.1;

View file

@ -35,7 +35,7 @@ the [release page](https://github.com/docker/golem/releases/tag/v0.1).
#### Running golem with docker #### Running golem with docker
Additionally golem can be run as a docker image requiring no additonal Additionally golem can be run as a docker image requiring no additional
installation. installation.
`docker run --privileged -v "$GOPATH/src/github.com/docker/distribution/contrib/docker-integration:/test" -w /test distribution/golem golem -rundaemon .` `docker run --privileged -v "$GOPATH/src/github.com/docker/distribution/contrib/docker-integration:/test" -w /test distribution/golem golem -rundaemon .`

View file

@ -1,18 +1,18 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIC9TCCAd+gAwIBAgIQKQTGjKpSVBW78ef0fOcxRTALBgkqhkiG9w0BAQswJjER MIIC+TCCAeGgAwIBAgIQJMzVQNYVNTbh36kZUytWiDANBgkqhkiG9w0BAQsFADAm
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE1MDgyMDIz MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
MjE0OVoXDTE4MDgwNDIzMjE0OVowJjERMA8GA1UEChMIUXVpY2tUTFMxETAPBgNV MjI1OTA2WhcNMjgwODI2MjI1OTA2WjAmMREwDwYDVQQKEwhRdWlja1RMUzERMA8G
BAMTCFF1aWNrVExTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwoPM A1UEAxMIUXVpY2tUTFMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCe
xiDZK6Fwy5r3waRkfJHhyZZH828Jyj+nz5UVkMyOM/xN6MgJ2w911hTj1wSXG2n3 8rEU8xHh6BMYVRz/KhFftKSxS4dxJi2LoNN4fxzY6EgHNfBACt2MhIWaUSHf2YkF
AohF3gTFNrDYh4j2qRZnixDrOM5GBm2/KJbyfBIYkrR45yLfjidO7MRnhaPZ5Fov NsS/T7qZWq23NEuIJYUUwbJRAh/iQsEhCI56eV+aJX+DGd2SQQNKdx1Pt528LNws
l+RKwNBXP4Q2mUe7q9FM457Rm8hAcqXP04AJT20m1QSYQivDgxsDxuAQte3VEy1E n8Ci8rEHTe6i2/U7n/DLqa32BWF3aShsVrchRgpizXezS7GLyFmhv0hi0zRKJgDG
0j0CwUKoFHT6MHOnDPEZbc4r1+ba34WBM1Sc5KXyV2JlbtU07J4hACYWVsD7vQCl JebLeqe/BUtEOsS/Oa65NQTEO/5EZBzM74+4eRo5zyp9Uvw4edmOrXRXK1fK9gP3
VFlZNE4E35ahMDZ+ODLal9PAT8ARLdAtjvRWrT+h8qZ4Yfwt/sGF1K4CAkTP3H5p Fq/jz9+8b5eUd9vl0e9z/xTqMdicYZOUHuUtxM3hXAkkxcaVJqqqDe6URbJHpbaN
uMkJG56zmqIEYeHMuwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/ 8Vt/p/csFXMWj3oSokvDAgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMB
BAUwAwEB/zALBgkqhkiG9w0BAQsDggEBALpieTckiPEeb3rTAWl7waDPLPOIhS5C Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCC3NiX+2Qk3WB+TRNDPCtQ7Pw+
XHVfOm7cPmRn3pT2VuR8y74U7a1uOkYMgJnCWb8lSXhbqC89FatLnAhKqo4I9oD8 o31SSqfF8m3fevT4mdrJqFAF4qUpDwgV9/9EkU4UBoIq03S91Dk/No0jR3VAzzRA
2BXgYeIpP5/OWBcjzmsMnowrvokc0chAmAR0Ux6AP0eX9amC0lGMuTHdw3+is0AR h3+ul/7u08JriS/ZgVediodi7H8xeCz3nvZfAwCP2ZmHzDGp39Uhc3L3WFZImZuV
lhoImOUPXvgMH7W2RimpSgnX0R5wKqfuGwMfbGa0xhWBZ+wekAKcU8b+pIHDyX0c fCDeSWF3c5CjJbdUuCYYFy6LwSFLPoBXZaNBL19XP9btJtjbNTm77PZJ4cELTQ+U
EQcir2y8/lVjECXSAIlV6iasPQ3hm1sd0xq1hx4yrwYFvQb7yEhOXbK24HLr/20D r5Ofw9D9mCCYrapmprw7Fw9wdE+iLL9EJCHAj7L8UYshF4+7O7Jv3ZatySMWPbjS
RRmEOuS8gg2XtUFv66z/VOw/nUleIg9GAuWDJaiu9frmIma4/tIY4qY= nIa2+eKl/sfvRvLZWV9dUSObVsm/bpv8bsHIKp4bYl+IDb2aoSWnw4eZQHDJ
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
SWDxLrvS33UCtsCcpPggjehnxKaC e38+Kzctl5iVbrB+JWY6roTQ26VLIdlS7A==
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,29 +1,18 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
KauB3KY1NiL+Ng5DCzNdkwDkWH78ZguI2w==
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,29 +1,18 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
SpS/cacZYUsSLgB4cWbxElcc/p7CW1PbOA==
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,29 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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 5O3gRtj/UQjegI0XV4YO2TQ=
X70TONscsBL/kx5MK4xoAmb+EN6Yy8i+z9NkNJd0B+2MjXPMFBpgGb0UiPv2wEmZ
5PAKyjwTxNIm6L/nFhkmVqfsQHfjHukXES4C0ff6fj6fuDpBfl5nTlVmc9LpP+hT
5RAwW10qumucGxAWGNBWW+K66cf8O7n/0nQykxJxYjBx16ZB80H2uvqFDKDVFqze
co5M4euXQq9KiXPRlcC9rab2a7FGLHd0TyPkq6TvfsqpxcryyKS4rIAz3sQh/tl/
/qm1tBcZW2bce3UlF2Wb2dW9HqvIu1O84f6ptLqwgKcIdTbwgQZ0kbFoWE2kWJSV
w+eAFb7tz1LDTpF3NRlz+1K27pBQWRQgcqoIRoQXpC0LfQY9Mp70QIfUQdUh6tnO
8hmq5y623tfxiDwCxb/EOpwCmwK1Cp9cloZTDefVE1r6NkEJWeeHG79VljUGF1KT
NKzXWrrsFtge/hU9Pj+frcZO9qExxPCcsrdZcoK7Ll8s+pjulRvbnCnJkNpeOI3P
iz6+sdGmzKSKg2daRM67Zmy5tmlBEX/eV7kFqt+b3HsdUiLo3Ng2lyPLNNDfwUtB
EukgYGjVJoyqLjLXgsCxLJlk7X/ogVwf8SlAnQ7p6KuxGWm02vlUpEmJp+Hq
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,30 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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 gqxjLkTNOdSva6Fkk/z8BD2XSZ4L+nM3Mw==
p3tFsnWUJCiOh9ywsc2NcmJdleKDc4/spElFMUarHqcE1ua6EH15O5GEnHWKj8EY
PVQFrPvf30UkRGNPl8eC7afZtCNk9MLllIATAzBr5Z1i+psV7MmgBKpbZ4B0TnhR
GXNT60QaCJ9RfUuc2z7RHJNo9XTn3Q44X7TFj+P3jHOWzTf8y6Mz6saTy2bugIUy
AfRgRgq/bB8hRjrazg55FIlrMv7dr3J0cIuqmaHfsw7Q2ECMCXW8oQXMBzfuIT0n
sG4u0oVxdNx4OdHsAubGjjwNDhxJvN5j8+YFqZMu03i8LbyamTwsrZg2C3QrRUq8
SujQEEB+AmO0lpuJ24FsOOYVSYCpLy2ugrKOr2NUqbiBKZs8uBh6RGACfunMZlEw
4BntohiO7oZ5gjvhGZNUEqzMChw7knvVjZ+DkhFk9yE4qIL7VsJSUNI2ZJym/Xeq
jr/oT8CpP8/mFZspa6DFciPfhGLQqKcaZZohL7461pOYWY5C2vsJNR2ucBZzTFvD
BiN/rMnIGFrxUscCCje6RLmrsZ3Lb7bfhB3W6kwzLRfr/XEygAzx6S2mlOM34kqF
HFpKrg9TtLIpYLAKAIfuNbrLaNP1UKh7iLarhDz/qDcvRka/qJTzLD3eLeGXefAP
KjJ1S7s=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAx0fwOrokPV/14eYr5nY0a+V1a9Q+/n1PULuqIQK6rQbibC6+ MIIEogIBAAKCAQEAoDx71xRLJqxG0QfDfIZbmUUKedkg35JK/KQA7Ke30ssrNTkb
rdkQU0vcOjyAH8Y0EjEhZa5vwmPoW3wTEoJvTXh9t6N5GAoKBD4T/+t+AOOVuccF mB7d6QG3OyUcTWd15iPL90rteQQJAFDRywX4pJpxTlCJl6TyDpu0f3gcPCW0KrUj
BZ6N/PFPPzRyu6sM0j9Xsyl31zb87qNZmYU9PGlXRjDq2VHGWWZfEd0T3CEcPVw0 x/UTwtAU/qTjzcwplQN402cfNu4r3GwyNg4KslYbKwsecqPMr/7J9U/BOb22ZRVG
n1ylZDJbh+noJPIi3TsXSHUUufA3kiNPRbJFnt3CGeZCZjKpyqCG2EiQlVXmDztE p3jGPDWhhjoLuIJ98hafv51AoOMeuf4rKF4jLbji/nLrcBrGA9+Meu28m3PW8+rG
RZSAYvs6XVciP6/SxtK9KZUXc/xyXr2zorVNsvd0tbPTVjDRJDhVNTxSZrBd2cza L4XLMMztF9kYiOSULopooebG9SwHSE7hY1v2S3wUG+fE7G4Mp/6tRgpODokrvY7d
iRQsko9NMvx3LIz1C2MCMWHanL9enEzZndz+hXoL7syyS4zbhmiyRnNWp7b/qetj NpRq6IS8TZdIpPS9ikuh6nmFz2ez/KHcG67OcQIDAQABAoIBABNXmb9ZtMSjUR0U
+2XRNw8qaxbsbDCYAy/fjYw2iM6GphX9FL+ytxe4ca6wB375tQjFDskC4PSelpeJ adWTRmVW/y+8NQqn1yNuDKqEiF0Kp1mSXjFbsH/a9CpQjX0Oex3fvlRImCfeg9Ok
i7DstmYQm3TRbE+naGwFBr8+DLo/VfFeaUfpxXoY5rDxDUrE3LOY9HvM01rbzBSE 7d4rB1ufRQQmFqXWhF2dEAm/DvF3v6rUGNCfVdZTVeVzNAh4l6BkPeaO8SapU2QV
nUvjWQJKYs9LOD1fAy4JOUadWRtleTp0TyzDk4CtJ54HORlWsX+zmAqxR2wSfLS/ L250/XePi1ID0pYWDbRE9k4FZZa5je3mTctn3s1PHp6xxQdyDHfxZmCZImwZcErj
dzFzUKbTRXgaVRYY1BqlRXM/up2xV9jbBS2Z4IUEbPZXo+E0xt9zUgGLrCqoVcKW joBoQldvUUfjqXCY9SgRJ/MQSNeJoJvPwXmYokpqxfv2sP+JlQgXEcO3Ihj9IkGx
BX/ArFwnL2LlOkZZAmI69zwfp19VA2tHlBptMzmm3/Ttw9Vcx0AaQ7s0h0MCAwEA avMFR3yGdWWLxmE3zzypXvFI+My0E035fEjcObspVOgqxJJUCWLSwWtVAo9shFgO
AQKCAgBd61qd4vKHdn1kzNztzdHg9BDGFA7oU9iYvQlua2HdgDwgLluxhXa7Oyp8 fPnfv70CgYEAxqVNQ4eEf8HRDN7Ygr9yruqN5NxXKJKBqOT+OlTAiCtrm6iRFkR/
y9y6nOgXls4dpPuJCxsMWsqGU7DvOxVNAh9lI/4ah8NXPv5wntIG73Q/dL2Ic5Yc WOFA3Ewjk5dxnVBvXHhTZoS2yfIVj8Pz7wbcoigfT+ia4JcAW8xQTs1CV/Xz8JsN
vLRCHFh7klzb1HRlmsXUFmp4/yGgIil+rDlS2MZ5hdTSj3X3ricoCBfI75oHQfB/ ChUH3ee2POue/AAxf25yDBGH3fKq34aqL9WNDmaUz+hDCo4r3/hfVZ8CgYEAzoAv
es7s8q1ZxKqxfHSbOUqHdlq7B0zmla8QE8RBdCkvlT5YGsMBjq1RimYfwOBNRgf4 tBxwE/VUwkmWzv40WI9J4GSh7lYo4d8Z2TR6FRSxgb0Uf3C3GiGKuLf9EMilL3ae
y8MZbt0Q1WtPeLPH9zdTzWYnDfmjmhqINEsq+PDoeCA4aciQGxjwOCrapgZnwF/q i/Dsb0CVn2sfLdSNFlxj1l8V4R8JfXST2Tn4g1pv6Hs3LEXJtlncg5/1DiMtfrqW
4q+r8HbgufXjnjGw5ERLt7BsRSYynoJiTWQ3p/wZ2VLpjFtxYxoJ5/qpQvbZMgGS quJtKuv8xO+5rbfqtmMYduf4ELkwg1uJJBc/we8CgYBZkUMrRbl6mXuXIAvjuEsP
Yu3FZNC6cnbOs+JWbdm7Kg93N24cBrGdk/KdEE6lz6uQq07FTSqLtPEQWePzBiuA j3b3UFqEUrrf2pC+4GQHgfx9LR5uOehpvPcv3azU6Z4y3oe33BFO0lxQ5jTOo/4j
1wfP78b2AH6vyJKq36EfMCJK2i7rpwtNz7d9NI5kiLRDB7gesqC94WJ+psEu+ErO Mqbc/tZPg4QB7FQfEBrNzUMywhWB0Yepmh338nh7M4p1+ehXmwcVZforGzXsn52w
w9DbTV3xdOPs4FGGrR41Hbo8emrk6smhb8+VK2odggi8i2CLAkYupMsuobBlX3CL /8sgSSSkMge4hK5HyIfD5QKBgHVr6rROH2UZ8dJwqfKWFgntoKKaVoICOEkH5dje
hyJPfWDv1aREJ1w7zWVQlJkvp5zR0oXZXpfFxjpj7Ypbp7BKxmh5+WYj8msFDfaD wDTQiYcuj0NQQq33OLyE0sACd/ufRdRpcOhqHyqBbT9QR9HZQ2QYuYZDcdAGxDOX
8VQ+pqgPpdl6zElEq9m5koHjsHH57fMeJQ59HiWpWFur+kQx4QKCAQEA0Jnvbm7R hTqb6FqYBe2E2Yh5XKzz/hLF6g7P5vDQxCbN/fO2JS0lEbAYdUbX7PUFeRKYsEj3
WypbPDInkIoPDIhyP9Pqv+wMzNfYEnVEG0GhEU/H5aE20a+Dm6u0bsmPm5lCSQsu d2e9AoGAMrejS2Ic64k2I8VyYapEJ1SUaCeNCj7yR67QVtXJWvmYeu9tsUy9bxGC
EvylTSL3yumQZMincNIUXcPYb2Qye/ZzJnMIibCqwMKQqi4HxCXprWhiEoGPum8A FmZuEIUnQV5KZUCKG26GKq/0NiT0Umc38zlUSJzDVM9LUHEt5K066RhVEBp3Fds5
fN0bTGgMYfM6JZ/Dh1eGsEvemeW+5tn5xZF4Lfp/vkT8v4FuHDydUF/lIx7F5MMi VIGgI1BkHeMKfhve0wwAbFECL+rzC9ihb6uNxZywlfeyfKN6ga8=
VteS0hHnR1DuvxHqtysf0wy2l61LFr7mQCMYTNEyFB3ZfXqpxJmFmCqPbr4PQsIm
2rqIDw+13eeoyDpJJkdi+yzHkAYDOdAsur0vOQvK/Zj1QKz9qmC1O6L4BN5yp265
vjSE4Orvo7btEQKCAQEA9I/afLw6lHUJ4FVL0p7dH15JSFjt7nmGHocE7Wf6Yp3G
vMp+PdGyoJ2KEQB2unnQZK1gZqUuRQLannjNl7fsIiIhHgHxMBCIiylwSUVnP868
u9/fpJV/cSGze2zF0WAttIgXKNtXG7xMntcY2k+SAe0qjqX494KT0NGnznySt2nU
A1YlkXm6u3KCOJrBKfbtiHXFoH39sA+ihuPiV7xcETS2ZrFdAX9M422p4yDHqe/0
dTe18wIxJNiEX4xp/HRE//cuQ5dw/Z/QmNrzgWxHbOmXVR5C90vIJRuYY9xz0tDP
LMnifSKfnG16l2gqg7zb8xsxYqSGndXWKPAeiq3/EwKCAQEAhCWQbWgcjmFFzNuE
/ubG48yoe9DW/OAft8Dg68iH7bBkxd/BpbG8VZeXiw16T1i29f5f5IAFnxeX7EbD
rTLLO1113V3ocwH3YZGa/bbBedETzo4xjc1z8asZVmQiJa1ju4+CKrvZFkDH415i
wcZgxqbwKhQDijl1+g52Ii5iMYuXE6GGPVXcu8DVrWOk0N7+/IGpIeOQJG2KYDPh
TOdzZ22FQKY8EeoS3gF0+SLUIDtbUIaR7/Z86iXD2HzdCemkVaZnaoYuMRBL0ybD
sqDn5nguEObWSII0pgN5Fa3QODhS6xOSc5brfx5X0BBVn0L9VbBJ99GIL3t71jRe
vVrL0QKCAQB+jUYZT+ncUqgWruy6g7yW89pmFqagxb/SYjn5g9m8WDq0DPDAmped
p4f/fkbx/gEJZ/I/i3BjA7QPVyHERcdqblDGz2h4X8XYhUv2jnR8P0XIznNTHo1B
BJh04PeIfgWIqveZC8+KqajYdSQGLDC40Ho6MMahha9p2mPEZRAi2x97zoNIQT6Q
qxOZqPMV/RIzkAYBI9E33w9ST/AbSHw35xgQEe23zaEC+wdzYc4QMPxF/9smcdbu
YyA0tVtO6PefoNAO5/nvNFjkEED7kwVu5X2K7Urn3w4lrZ7w5e4FhEoAukN6T4Va
lAhg+uUtIHiM12B50/tZB4N30bFsP9eDAoIBAHc7ppfpo1aDK3bDr6zTSOU4Mn1l
XrfhBJHDy2Wt9WkvWtcCtXr3sDpthaChueV+mGoKvfgWyzUoauO6HDDsRYriqaQB
cXclVjyy+3atY32Opz9rnWefQkbgTOQ+oQgOzEFhxNS+11Omc6ZZ9s31N6TZi/Yz
rgXzhGrr73DkV6uwiiwkvP8vJxg8AMWKorDIm1myr9wwlK5ogDKSku1DM/y1gvlt
4EA39fqURyqxN9o5Yq+8K1+a/smjGx95M+P8Nke4bMs1+lb7bBXbMaVpC6DLqj8B
eleOZ7adY2mS0CBuf0PNkJRNDwF1B5VDmGBJLubUtGLuUUoEyUbv66WfnUw=
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,29 +1,18 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
RfbdpOr8p/Ks34ZqQPukFwpM1s/6aicF
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,29 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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 6LPZM1wJIwuYHIP74eH0ctQP
wE560/AcVZcbKKAZOnZ/262a++8tparsQt+bXBJ2so6YUqsFDNdOLCI2aShjWDRe
TNhqmLIO3FNsLRKp96WHVz+jFoiECsoYfKn0jgqTqxx+7nWFqgBaNSlF5cbCgLCH
jQV1uQhzsw/Mh/32hXAidkv/nLeLf7FbKq08hgthtoP+XstlzZ5BxkPodjb8XWXG
DSS49SWX971GHa1apwMKfxVGSppxn18ZwEmW1BUfQBNxtMytqA9DK3+xuoUdXkB0
iJbm3Jc10JSRju8iyL121Xt6f8O33paVz/ndDJIWztUOjnItc89rxHsINPt5+cUt
jix8ohwmHGDrK7ZooXBvotvmGT/xhPr2eHUAG8JuSJ/Cr09UUOwUEigz4CfgJOHm
XukdzjOkb4r7lhNmVeGqrjRol1W0Wsc1NGH++J6xdkIeQ+i23kHwFHfQWV/J69tm
rOn2N+qijtmbIy9YfVcrFDtUtEAzXylZ2StCVQNofd0M7tXNdrUL8yAFwlrhWGJV
wsSP++1xH2Ie6Diupy8z6rbP383HmnmVPU/UecgLrlX2lEpt/UZkkX1Xm+6PhrrT
HDeeULvqtUP3PD8wS0C873Pl9GXOKISqf0HKEIDUAVZhQOsGFqiZH0388M4L
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
MIIJKgIBAAKCAgEAsF4L07p6z6ZK0OjBR3WSIzn1WSKfPN0eATbgu8qYbFDp8Oed MIIEpQIBAAKCAQEA2vfYJRcVQJbVzag+geOrvpPyNRMf9zE+JHk1psnXLiAwIGSj
PxL0vuLLOjFwlaW9Ie6l/Jla+KPRkjJFnbzxd6ZMQVirblErQgEYZ29jP06pPZHe ash75NuVb1RyXEf3XWCN+lIDEW01/6VfmTCYAweFTylwJz4yOncDH1pwVdJe/PNM
VuUFCtcONKL1YbXqwbHrQwaEzZ6AYyoVDkMF9PXogrDTT5GMWAJXMnxPrgvPDzYT OD7GPQ0aKDo4GTePI+473aUzwDiqzSYFn9PTiIuRrAuZ1FdWJGgYr9PsN/wc36Gb
R7t3qGXf1I/Jtj66+u1IgPrSFgaZeg51qIL2qq6K+SzrsFmmsY185Gu/Ik2sIUjq tSwbRU7cbEWBJJNiGEpO7okxMAOzNsgU868HEYJQ2F99eIs3K+I7gCIF1wC/a/RJ
gpQVYetDU+kZ3a07Ak3U/eCSRLylWUCJ/plCQB/7O4q76XiPm0rEaUkCQmxp9UkM Rp0Q+ZIabklvUMq18pjSNaLWTXM1KrOK39uEwv8QdtWRgnTRCYfnQwFO6enPrSAi
s7EEq61SPmayFrSDq4mAVdR7T4byGQ1wSN3xepRQLAg5jel2/hazJ0oGTe4f3Myd AeO3jyfMlqssMwuhEUymkb1cgFCVSfeWjSBXBwIDAQABAoIBAGQMCf4oZdV1FYs5
iiXDneTWrQ5u+hjU1d9t4zEdAC0OLud9AaVp71y645LKbL3la6/N+FkUp09ZR7yU 7BV86OPSxT/q1Rgkr7gKibEDWAYDPvoOAXywzarriYOsmfQADc3kZ/qPrkcwFxQP
o31BcUhZWgIWc6bxPc/4U0JQT6nwMhaRqXpSX1MeL8rPinu3DKtSnUvBPkS1Jone g3aC9XGs5gQdctj7WgfMiOiycdFEpZH9uD2asQkEC4eF0kvzTrukBkZnTRXuzlud
IYCYH0j7z/W+ZlPeU+Kdfw/6JUYznI5Sem2uwWbRtRwlZEPqJpMrUrGkf4iziHaS m8RDDMu+uXhadJbIsNtBlMYBllSdS+LFxXcAYm+IsvTYzmwg4+bnjvOwMHO9SMSb
JSJLPW0L/1spolg3aj2jLurv5lV8dKYjEujxkVixpkFxeL3pwq648xHdfghI/AoO 1dfgOLkg/A++/GTjD/kUyCV5dc4lv2I0i2pXJkD2V0Dr6Yra1U/MRKcOwTGC2q/8
o/mKvFT9Bsj5hAEyyGAbhvQE2gxnnSDfSvcdyyJ/DinM9AXREMw4F4KI6LcCAwEA hZuKm9DgvGXvZsG0+yT5fsexGRwTxmByvfj+QMF3LCTDCknD4d/mmEEX0EEGPlW2
AQKCAgEAnrHg/oD7ZMEC7PuifoRCHMRYCf5nPkLQbtNMYG2pvT0JY6VlDo4l/2Te I7OgKEECgYEA/LkdwnXy7ymis1Rgjumc3ydcLoCqV3ExaxXrvO50EkRpgRX/TLEk
7NvzrBPYHSI55RKwkq4FMwFdNtP+imTulJYOm1MaE2gc52WI7jv/eNE6OQIWCWz8 j98iVYyksiaJuMhqnxNttT6GwWJvwIXFPP9WpIGmzi4GKyqYGEX4WbyPoY9hjt/G
8Uv4dBVWyTcos8S31rTaXWBOVejlAUgMERy+5wfWOpLQlzLYF4m0pMFJk/AReUtB muR67cTXg6ssiSssUCoQnWIHyuGDJfzRWqnoei0dIA2GobOwFJtXeV0CgYEA3c6u
nmhLXlsPsB22cag/RWZmzzcXk6tT/LzVe+R5ptLkdTsUuAxjjaBKVCDiMuDAZL1m utbNtmbyp17Jffx01ee8Wprhnoz7Nh/dJMLngpIx3i8qQqpFB8TPNUTu+GLgGcol
dah3h8oKIMab8l0SABumxKqYAKkyvbSJQUhSUYAT5+3c0cfJ6q7WoMk8TqvnwfpQ n9BDzZszoVhsxybn7Lgm/OjS/jQL4hosFoqztThkg28L8UD7QB0TyCucwgk2lgOe
2Klbcaa4G6+79H8e/a41RWmcMVTTpLKmwzx/iMLPswLnTFbWYCsLSsml3OpmXPhG VxyX25kNSXzxdCYaKr1+6g2gtBAb0zPj2E+5t7MCgYEAimoA6J6dHWwaVkmiUOOW
CKdbIWMvNMBfahZmnCP2pNcZBVY1/k/lEw25ehtnWqA7HplawT6V3gk/Bzz+3e3R LYprLHT/1sCCJnptEJ8xJ0gc2LxphWGH+txk+6H6GjCNQY1TCCkl7xx9xbDaMAGU
XEpioZF70ipdW5Pb3OG/tKSNDvRRjqLPk9UWlQzmedzu7XN28V/blw/CBVcMAcc0 E2Jt28++wjHm4wGDJ9g6uztRF1VmQ1BAgFkfEta6irzXuZDRxl4jl283gWCd6dJb
njwAledTuqv/wQ67dtbXdcxSPZbV/Rq7y3OmpgK6RWLIFzzpOPW5gULqUZfrnxtv /2ILl87ZotKFqE6347Fo6WkCgYEAyDNyMMALIzTelkUO1wFUL3If5yPeuy4C3IJ8
StxVnlZXhFoymodFobTi7AYibsLaXLkunZWXEwFwdtLfFHznfHq/rHfBmna1lcKW J18oeQkdq66klVF8RxvT7v/ONjGAlqaHuSzQ1jbcrifS3xp1wYsh3asELl+pziXT
MgWRqsbaoCsqHC1nc0E4llFkn3zqGYgMQNBeqNfX6cIPI/eQzPECggEBAOk0TP8N X3FH7Sz+REep3tLJNMBKB6WdsuF//H09oOD1DEej342/nhd6DNPHRtiQEZZslwBC
edIFENOrzUtpH1fB3k15heeA84SeBhj8t/xrphR3o+IVO/GtMtq9hVLeYFVPwWCi Cg9D0NMCgYEArNksPSQJSxXqxZsw17OTqQJnf3kNBI0SP9q6Wc8gN69r5YQcIHcr
Mmy4KhwNUOtFeCSX4MbpiXvoPEjL3QF+Sv95HsEWsT1iBQIN4aoV0ZSv48YsRczs KgtfdiL4LawZFie6gcNu398ng7VYUzzkYR9j+G5qPetcqllQZeVc6cieUyR7Eul0
tLjr96hADLTMfpCwyRq9r8XVF/hnx7vqOoOC/J1kteRhjOWRnutFpdAMfkFgzUa9 WvtlUECCfweLFUsIhuHyEsGu1PrFYd98SlOzt24utguFss1539cEC3A=
1unmDHsDifcT+vpxief9Q9zK9xMYvYmwFkBUjOlhC7WchZC20nrwvM+A2mMBpeLB
WSRWsYeOqW8zcQNGdWuXXMKxsYHwv9tXbANVWxs1gz4x7BxcFoN5poIFrnT+eImY
EwhGrKR6jZsKF00CggEBAMGbdZU0+yvxL2tAul5RGAqv9xhdUV4eg8warTQ8/RWt
8Vef2wllBYnP48rXNDovb7ZNOjMBdjIWZ2zq2McMtHqpzP+zWQWaNT8/7Zi24JTL
y4G75kZdGgTPG2Y71seZoZGxfOu4gf7cLKOqxiHYrNDHEDl5Pi13tJD/8qf6hYm6
K3yALSv+QlM3mk+5oueKQ7Lj9rV81YomYSV5+K+WhszhvLmuxv0necOLKapeBWvL
GQ5038yAq3PFdu0HXzyA6L8YdusP1d3sqwQvLbi8KAMXJCeT6WZXGYgX2Rjfbuih
ZHUaE7Ac0EsJfMuOowSkS7oXuT81k64ngCoq5KZC5hMCggEBAKYkt9JiZG8HYuSb
GsjmHQllup5RvN+hVF0gRFHbAq2YeBtO3Xg+DpXxAjErIuhWPCWri6bwB6LDVmTj
68milaTke6TbTzLy0rg+Xbcppf766LlCFIYZ5l1/TE3j+4vGAC347sW/wkWY/7lj
4GmS43zsJmqhx6/XUJuOPJOZnZSCZr0vuhL6mOoZZDJUTXy62dx0PetvZsT/O9cM
P2fDWWTCLTEVlBqik4KMdsS4qjGsyzOeCzyZReNDDRO/nZTsRSqSSwARJhQom5Rr
RDVQXeyqbw93KAQhmshroBSB5Rc+4YiyCE3wPTo7NWL38XPi3lbF0VSd/rk/uNH5
6hcSCmUCggEAIPHjQFCTrRaNiyKolAQYozjuQyceAXYP11tyvcDjEB1ZRB/flemq
15iYmpukN4J67/qUPLmy8zL8xnvwB28SBw195MUQEPP8u5aVR7dW3/sN1jWzKaYO
F2Nmti7YjX6HD9Oz/iiXdlbhAbi9nmTQg3ZcPGt1OSd1gncLQ6pNrvIPFFB7X1EU
2DRN/eMI5X2Rp49DG/7yF2AQh+AJgVeL+LEw/CfRlKJzBeNYY7U8Fuuoh907eAEt
K7YeVpc6jYEiGeJ/2eAH9IuhTkT48saRyHTXoiR5QwDvR0lHmAPtS4irH4Igd4dv
qlUi90B+XPvYJwKCc08aojf2hzZlUiVwIQKCAQEAraCoWea8hLFchxmAiBt7joIg
nNK7a3LOHYxT1gB9H+PoVqTmzGVTeZpD8Jnis/UHmDhRYuUGqvFIefjAWbz0jJAN
t6RMAozENCG1PoeXHf1gt2wspv14kza+8jSdpzNrzZgPZdb7Wh1UEqUkiRYwn87f
C7DHknqCj9S2qq0DFXYz15JNPVrbvD+ZLBFJhTAjppS9TuYQVLf8JPYHpLRio/9A
dMsyOz1VA2RRYN0u/u4ccxiN45K3PbVMCeDPbWXNm8G75YKQ7LnIuehMB1qkZy6N
MOnNGp3l/ZkFK0JsW/pZqTQ2FqSkb0+ttTFApFI3qB04sc4s0uKPI9fa0OQtUw==
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -1,30 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIFETCCAvugAwIBAgIQCnqSQalw9ytL5bHLgHZe+jALBgkqhkiG9w0BAQswJjER MIIDFTCCAf2gAwIBAgIQTyBNJlm7fS0yutwdLbhG9zANBgkqhkiG9w0BAQsFADAm
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE1MDUyNjIw MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
NTQ1OFoXDTE4MDUxMDIwNTQ1OFowKzERMA8GA1UEChMIUXVpY2tUTFMxFjAUBgNV MjI1NzI4WhcNMjgwODI2MjI1NzI4WjArMREwDwYDVQQKEwhRdWlja1RMUzEWMBQG
BAMTDWxvY2FscmVnaXN0cnkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC A1UEAxMNbG9jYWxyZWdpc3RyeTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
AQC9gvT3cwz0Ih9+7Ilv5lc15HsEiSmEMh4nOMZrSaamKgf/ydCiGo3DQapr/XDK ggEBANSMT7auGdwF63fFdQM9O/EqrX++gnuBQgFa4cZzC7GqsvS90uKTOLuWIA2U
FHMLKq68AxwfOlzmEFQ4d9umpPMQ2+4GBr0VG23ppGtQApIPHgD06S0/CeHmDIXN ehgF548EDkZu1z6nRAvoFh5L6B5f1VjiVknzLEPlR+5uPD22kbcxgCrMCRZn+5mK
FXcKybPX/9KbgNkXBWbbJkJy0EcsdP8VJD50Q2WH89nvgEYJNFuKEELD3iGY6bBF vJhTUpx18yeBXMhxtPhkGnKaKwGcgeW8O69KM7Mo4HBQqg5656pa+4wkUo7GX2v0
jeDTle5jYA7CgBKvD2avn31g24Qhxn8n8/BdYO/U0kw0qmoy1veLOjCAW0os0jkM R4ZqmrS1tlwOgpld8KZKVJ1FNyGEeKQkIYGJKHqgC2/JrXsbzuSZ/4pqf8BHc6Mb
NlKrFpyHEWNj5B3X6UgSn8EGQaVbDq17PrQwlHJYU4nih0TnD1OwvBnFnd27pXjr AHU85RlBFVDHFPMtQ7Rg1vrhYzgInKeqXtc2kEAe63nqyYyHxPOUd3vIQX/N4tdB
68eGA6Zc2BbUnhNGhppWHZ46LpPxpIbafSOH3ES3N/MZAfcUKIUntLlWE2xCQgFV aH41ffs68Pdtp9GeocTiYyj7KuUCAwEAAaM6MDgwDgYDVR0PAQH/BAQDAgWgMAwG
TW95WeVtP/r1aWgIHu0E2Jb2eHCE+qXYqJxSU7S4DcknmmcTS69hzyHs+92Ec+7Q A1UdEwEB/wQCMAAwGAYDVR0RBBEwD4INbG9jYWxyZWdpc3RyeTANBgkqhkiG9w0B
m0aQFZ0dyPoYPwXMgZpTAIuXEGg/FKC1fiS/deTW37DyvB2jppehKW3RJY3uso7R AQsFAAOCAQEAkjfZvcd5WysbfqGfhPErG7ADWAFJ1bsIDlHVUaEn2/Asr68iJpfF
o9vs6DJx1OdU5XEq9R3n7op61N7PK8Wxmn7TVYHEZHkITVvtucZZd1FNTOrOJaNJ fqb0fhBkBExPhiLDS+jmL1L86QRNIgyM+7zGCCagKJkl9uNBGXPdS6KxZtY8W8rV
UnE+FuPK1Mrff+jz666Ru4zQL0CondOamX3QR5tuNK6MTqFs87wKY25qsqz7cS27 bF/GIYnYUL5pnyrhX4pH2ZnDJpKIAJl8CAZ1VHwErQ5VqnJAX/gGO/eKgiyCciZv
kHW+r7UNWbJY3/UQhaPZM78zCZa2IL1nBFUjsFvEA4rtYwIDAQABozowODAOBgNV WmmQkhcOo60FwLW+Wi9sLOYD+YAT+VnFrGfak/SDfT78wrmmfg5v05tvFXgJaZLh
HQ8BAf8EBAMCAKAwDAYDVR0TAQH/BAIwADAYBgNVHREEETAPgg1sb2NhbHJlZ2lz JSxRET9D5iT3DIxb+m5GyQAqIH1djh02ybrPJ9j6/+qRQDojIe5qJUL90qIvhwO+
dHJ5MAsGCSqGSIb3DQEBCwOCAgEAHVGMyoyX4lRzWCDkUjrXkrDZzuv03M2ojW2Q aSbIL/p+I6//AUMWJvcR7GbXy3xywgmaYw==
UL61ejMkTWQW8R4gKrcPHAOJAPKVfGEVOrQH3ZMyxV2HnWrJ7egrn65zOzmLbWSh
O7gdpL6YYjBr218fqJn/8HadXZa4k70JyympYOLojeWSLy3KP03U+y7AMcdE1uG6
6HJI54ZjBoW/nEyWmMh/mfMz8EN+Mgek48Z9AVaOswbtHtDIXN7XO0jbB3DbY5Yh
prVqVLYAz4sCchGTadj+aEChF5sJkKREDvAew/njC0WGS2TmMJ+V1uVhXV6354mr
edk79YvdwzwDgeYArkprahMtn9eu1aSTfUXsmM5OP5tR4gyFV1kUmTPY1yUd/yO+
638wV0mWtGbbf6j8dUKeUBCyt2qGg8J80OUeFdvdHMswtaUq951NApX44BinPkbK
moBVQByZ5OEcmMidFC9SqYSUwTQ7uNyWeguhCXav+l3x900YlKnUQgRUZntPwXjs
yc7MXv0j0E86Gme6G1O02zamwkRgr3qOTHu2oQOow/a24fM4HASayLR0Kegt0sh3
rzk0HRF1mGonf1Ecyyj/3LpHVsgYSckwtJoZLOqtDMn+CKtOCEByssQfD+E9Qe07
qMyvcwpXUpfqe3ZERbJ10m98Z88VeK/XGt9ptq7HY47n1KL6lx3oyXwZIw8pq928
89dcqL0=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,51 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View file

@ -7,6 +7,9 @@ storage:
rootdirectory: /tmp/registry-dev rootdirectory: /tmp/registry-dev
http: http:
addr: 0.0.0.0:5000 addr: 0.0.0.0:5000
compatibility:
schema1:
enabled: true
auth: auth:
token: token:
realm: "https://auth.localregistry:5559/token/" realm: "https://auth.localregistry:5559/token/"

View file

@ -10,6 +10,9 @@ http:
tls: tls:
certificate: "/etc/docker/registry/localregistry.cert" certificate: "/etc/docker/registry/localregistry.cert"
key: "/etc/docker/registry/localregistry.key" key: "/etc/docker/registry/localregistry.key"
compatibility:
schema1:
enabled: true
auth: auth:
token: token:
realm: "https://auth.localregistry:5559/token/" realm: "https://auth.localregistry:5559/token/"

View file

@ -10,6 +10,9 @@ http:
tls: tls:
certificate: "/etc/docker/registry/localregistry.cert" certificate: "/etc/docker/registry/localregistry.cert"
key: "/etc/docker/registry/localregistry.key" key: "/etc/docker/registry/localregistry.key"
compatibility:
schema1:
enabled: true
auth: auth:
token: token:
realm: "https://auth.localregistry:5556/token/" realm: "https://auth.localregistry:5556/token/"

View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"flag" "flag"
"math/rand" "math/rand"
@ -9,13 +10,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/Sirupsen/logrus" dcontext "github.com/docker/distribution/context"
"github.com/docker/distribution/context"
"github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/auth" "github.com/docker/distribution/registry/auth"
_ "github.com/docker/distribution/registry/auth/htpasswd" _ "github.com/docker/distribution/registry/auth/htpasswd"
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/sirupsen/logrus"
) )
var ( var (
@ -85,7 +86,7 @@ func main() {
// TODO: Make configurable // TODO: Make configurable
issuer.Expiration = 15 * time.Minute issuer.Expiration = 15 * time.Minute
ctx := context.Background() ctx := dcontext.Background()
ts := &tokenServer{ ts := &tokenServer{
issuer: issuer, issuer: issuer,
@ -115,23 +116,23 @@ func main() {
// request context from a base context. // request context from a base context.
func handlerWithContext(ctx context.Context, handler func(context.Context, http.ResponseWriter, *http.Request)) http.Handler { func handlerWithContext(ctx context.Context, handler func(context.Context, http.ResponseWriter, *http.Request)) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithRequest(ctx, r) ctx := dcontext.WithRequest(ctx, r)
logger := context.GetRequestLogger(ctx) logger := dcontext.GetRequestLogger(ctx)
ctx = context.WithLogger(ctx, logger) ctx = dcontext.WithLogger(ctx, logger)
handler(ctx, w, r) handler(ctx, w, r)
}) })
} }
func handleError(ctx context.Context, err error, w http.ResponseWriter) { func handleError(ctx context.Context, err error, w http.ResponseWriter) {
ctx, w = context.WithResponseWriter(ctx, w) ctx, w = dcontext.WithResponseWriter(ctx, w)
if serveErr := errcode.ServeJSON(w, err); serveErr != nil { if serveErr := errcode.ServeJSON(w, err); serveErr != nil {
context.GetResponseLogger(ctx).Errorf("error sending error response: %v", serveErr) dcontext.GetResponseLogger(ctx).Errorf("error sending error response: %v", serveErr)
return return
} }
context.GetResponseLogger(ctx).Info("application error") dcontext.GetResponseLogger(ctx).Info("application error")
} }
var refreshCharacters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") var refreshCharacters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
@ -173,13 +174,13 @@ func filterAccessList(ctx context.Context, scope string, requestedAccessList []a
for _, access := range requestedAccessList { for _, access := range requestedAccessList {
if access.Type == "repository" { if access.Type == "repository" {
if !strings.HasPrefix(access.Name, scope) { if !strings.HasPrefix(access.Name, scope) {
context.GetLogger(ctx).Debugf("Resource scope not allowed: %s", access.Name) dcontext.GetLogger(ctx).Debugf("Resource scope not allowed: %s", access.Name)
continue continue
} }
if enforceRepoClass { if enforceRepoClass {
if class, ok := repositoryClassCache[access.Name]; ok { if class, ok := repositoryClassCache[access.Name]; ok {
if class != access.Class { if class != access.Class {
context.GetLogger(ctx).Debugf("Different repository class: %q, previously %q", access.Class, class) dcontext.GetLogger(ctx).Debugf("Different repository class: %q, previously %q", access.Class, class)
continue continue
} }
} else if strings.EqualFold(access.Action, "push") { } else if strings.EqualFold(access.Action, "push") {
@ -188,12 +189,12 @@ func filterAccessList(ctx context.Context, scope string, requestedAccessList []a
} }
} else if access.Type == "registry" { } else if access.Type == "registry" {
if access.Name != "catalog" { if access.Name != "catalog" {
context.GetLogger(ctx).Debugf("Unknown registry resource: %s", access.Name) dcontext.GetLogger(ctx).Debugf("Unknown registry resource: %s", access.Name)
continue continue
} }
// TODO: Limit some actions to "admin" users // TODO: Limit some actions to "admin" users
} else { } else {
context.GetLogger(ctx).Debugf("Skipping unsupported resource type: %s", access.Type) dcontext.GetLogger(ctx).Debugf("Skipping unsupported resource type: %s", access.Type)
continue continue
} }
grantedAccessList = append(grantedAccessList, access) grantedAccessList = append(grantedAccessList, access)
@ -216,7 +217,7 @@ func (grantedAccess) String() string { return "grantedAccess" }
// getToken handles authenticating the request and authorizing access to the // getToken handles authenticating the request and authorizing access to the
// requested scopes. // requested scopes.
func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *http.Request) { func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *http.Request) {
context.GetLogger(ctx).Info("getToken") dcontext.GetLogger(ctx).Info("getToken")
params := r.URL.Query() params := r.URL.Query()
service := params.Get("service") service := params.Get("service")
@ -242,30 +243,30 @@ func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *h
} }
// Get response context. // Get response context.
ctx, w = context.WithResponseWriter(ctx, w) ctx, w = dcontext.WithResponseWriter(ctx, w)
challenge.SetHeaders(w) challenge.SetHeaders(r, w)
handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail(challenge.Error()), w) handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail(challenge.Error()), w)
context.GetResponseLogger(ctx).Info("get token authentication challenge") dcontext.GetResponseLogger(ctx).Info("get token authentication challenge")
return return
} }
ctx = authorizedCtx ctx = authorizedCtx
username := context.GetStringValue(ctx, "auth.user.name") username := dcontext.GetStringValue(ctx, "auth.user.name")
ctx = context.WithValue(ctx, acctSubject{}, username) ctx = context.WithValue(ctx, acctSubject{}, username)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, acctSubject{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, acctSubject{}))
context.GetLogger(ctx).Info("authenticated client") dcontext.GetLogger(ctx).Info("authenticated client")
ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList) ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, requestedAccess{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, requestedAccess{}))
grantedAccessList := filterAccessList(ctx, username, requestedAccessList) grantedAccessList := filterAccessList(ctx, username, requestedAccessList)
ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList) ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, grantedAccess{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, grantedAccess{}))
token, err := ts.issuer.CreateJWT(username, service, grantedAccessList) token, err := ts.issuer.CreateJWT(username, service, grantedAccessList)
if err != nil { if err != nil {
@ -273,7 +274,7 @@ func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *h
return return
} }
context.GetLogger(ctx).Info("authorized client") dcontext.GetLogger(ctx).Info("authorized client")
response := tokenResponse{ response := tokenResponse{
Token: token, Token: token,
@ -288,12 +289,12 @@ func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *h
} }
} }
ctx, w = context.WithResponseWriter(ctx, w) ctx, w = dcontext.WithResponseWriter(ctx, w)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) json.NewEncoder(w).Encode(response)
context.GetResponseLogger(ctx).Info("get token complete") dcontext.GetResponseLogger(ctx).Info("get token complete")
} }
type postTokenResponse struct { type postTokenResponse struct {
@ -378,16 +379,16 @@ func (ts *tokenServer) postToken(ctx context.Context, w http.ResponseWriter, r *
} }
ctx = context.WithValue(ctx, acctSubject{}, subject) ctx = context.WithValue(ctx, acctSubject{}, subject)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, acctSubject{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, acctSubject{}))
context.GetLogger(ctx).Info("authenticated client") dcontext.GetLogger(ctx).Info("authenticated client")
ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList) ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, requestedAccess{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, requestedAccess{}))
grantedAccessList := filterAccessList(ctx, subject, requestedAccessList) grantedAccessList := filterAccessList(ctx, subject, requestedAccessList)
ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList) ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList)
ctx = context.WithLogger(ctx, context.GetLogger(ctx, grantedAccess{})) ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, grantedAccess{}))
token, err := ts.issuer.CreateJWT(subject, service, grantedAccessList) token, err := ts.issuer.CreateJWT(subject, service, grantedAccessList)
if err != nil { if err != nil {
@ -395,7 +396,7 @@ func (ts *tokenServer) postToken(ctx context.Context, w http.ResponseWriter, r *
return return
} }
context.GetLogger(ctx).Info("authorized client") dcontext.GetLogger(ctx).Info("authorized client")
response := postTokenResponse{ response := postTokenResponse{
Token: token, Token: token,
@ -416,10 +417,10 @@ func (ts *tokenServer) postToken(ctx context.Context, w http.ResponseWriter, r *
response.RefreshToken = rToken response.RefreshToken = rToken
} }
ctx, w = context.WithResponseWriter(ctx, w) ctx, w = dcontext.WithResponseWriter(ctx, w)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response) json.NewEncoder(w).Encode(response)
context.GetResponseLogger(ctx).Info("post token complete") dcontext.GetResponseLogger(ctx).Info("post token complete")
} }

View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"crypto" "crypto"
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
@ -11,7 +12,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/docker/distribution/context" dcontext "github.com/docker/distribution/context"
"github.com/docker/distribution/registry/auth" "github.com/docker/distribution/registry/auth"
"github.com/docker/distribution/registry/auth/token" "github.com/docker/distribution/registry/auth/token"
"github.com/docker/libtrust" "github.com/docker/libtrust"
@ -27,7 +28,7 @@ func ResolveScopeSpecifiers(ctx context.Context, scopeSpecs []string) []auth.Acc
parts := strings.SplitN(scopeSpecifier, ":", 3) parts := strings.SplitN(scopeSpecifier, ":", 3)
if len(parts) != 3 { if len(parts) != 3 {
context.GetLogger(ctx).Infof("ignoring unsupported scope format %s", scopeSpecifier) dcontext.GetLogger(ctx).Infof("ignoring unsupported scope format %s", scopeSpecifier)
continue continue
} }

View file

@ -0,0 +1,80 @@
package main
import (
"crypto/rand"
"crypto/rsa"
"encoding/base64"
"errors"
"testing"
"time"
"strings"
"github.com/docker/distribution/registry/auth"
"github.com/docker/libtrust"
)
func TestCreateJWTSuccessWithEmptyACL(t *testing.T) {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
t.Fatal(err)
}
pk, err := libtrust.FromCryptoPrivateKey(key)
if err != nil {
t.Fatal(err)
}
tokenIssuer := TokenIssuer{
Expiration: time.Duration(100),
Issuer: "localhost",
SigningKey: pk,
}
grantedAccessList := make([]auth.Access, 0)
token, err := tokenIssuer.CreateJWT("test", "test", grantedAccessList)
if err != nil {
t.Fatal(err)
}
tokens := strings.Split(token, ".")
if len(token) == 0 {
t.Fatal("token not generated.")
}
json, err := decodeJWT(tokens[1])
if err != nil {
t.Fatal(err)
}
if !strings.Contains(json, "test") {
t.Fatal("Valid token was not generated.")
}
}
func decodeJWT(rawToken string) (string, error) {
data, err := joseBase64Decode(rawToken)
if err != nil {
return "", errors.New("Error in Decoding base64 String")
}
return data, nil
}
func joseBase64Decode(s string) (string, error) {
switch len(s) % 4 {
case 0:
case 2:
s += "=="
case 3:
s += "="
default:
{
return "", errors.New("Invalid base64 String")
}
}
data, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return "", err //errors.New("Error in Decoding base64 String")
}
return string(data), nil
}

View file

@ -1,7 +0,0 @@
#!/usr/bin/env bash
# Given a subpackage and the containing package, figures out which packages
# need to be passed to `go test -coverpkg`: this includes all of the
# subpackage's dependencies within the containing package, as well as the
# subpackage itself.
DEPENDENCIES="$(go list -f $'{{range $f := .Deps}}{{$f}}\n{{end}}' ${1} | grep ${2} | grep -v github.com/docker/distribution/vendor)"
echo "${1} ${DEPENDENCIES}" | xargs echo -n | tr ' ' ','

View file

@ -41,7 +41,7 @@ func TestLookup(t *testing.T) {
} }
assertEqualDigests(t, dgst, digests[3]) assertEqualDigests(t, dgst, digests[3])
dgst, err = dset.Lookup("1234") _, err = dset.Lookup("1234")
if err == nil { if err == nil {
t.Fatal("Expected ambiguous error looking up: 1234") t.Fatal("Expected ambiguous error looking up: 1234")
} }
@ -49,15 +49,15 @@ func TestLookup(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
dgst, err = dset.Lookup("9876") _, err = dset.Lookup("9876")
if err == nil { if err == nil {
t.Fatal("Expected ambiguous error looking up: 9876") t.Fatal("Expected not found error looking up: 9876")
} }
if err != ErrDigestNotFound { if err != ErrDigestNotFound {
t.Fatal(err) t.Fatal(err)
} }
dgst, err = dset.Lookup("sha256:1234") _, err = dset.Lookup("sha256:1234")
if err == nil { if err == nil {
t.Fatal("Expected ambiguous error looking up: sha256:1234") t.Fatal("Expected ambiguous error looking up: sha256:1234")
} }
@ -118,7 +118,7 @@ func TestAddDuplication(t *testing.T) {
} }
if len(dset.entries) != 8 { if len(dset.entries) != 8 {
t.Fatal("Duplicate digest insert allowed") t.Fatal("Duplicate digest insert should not increase entries size")
} }
if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil {
@ -126,7 +126,7 @@ func TestAddDuplication(t *testing.T) {
} }
if len(dset.entries) != 9 { if len(dset.entries) != 9 {
t.Fatal("Insert with different algorithm not allowed") t.Fatal("Insert with different algorithm should be allowed")
} }
} }

52
docs/architecture.md Normal file
View file

@ -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.

View file

@ -89,10 +89,6 @@ log:
to: to:
- errors@example.com - errors@example.com
loglevel: debug # deprecated: use "log" loglevel: debug # deprecated: use "log"
plugins:
- /plugins/
- /plugin/driver1.so
- /plugin/auth1.so
storage: storage:
filesystem: filesystem:
rootdirectory: /var/lib/registry rootdirectory: /var/lib/registry
@ -104,6 +100,17 @@ storage:
gcs: gcs:
bucket: bucketname bucket: bucketname
keyfile: /path/to/keyfile keyfile: /path/to/keyfile
credentials:
type: service_account
project_id: project_id_string
private_key_id: private_key_id_string
private_key: private_key_string
client_email: client@example.com
client_id: client_id_string
auth_uri: http://example.com/auth_uri
token_uri: http://example.com/token_uri
auth_provider_x509_cert_url: http://example.com/provider_cert_url
client_x509_cert_url: http://example.com/client_cert_url
rootdirectory: /gcs/object/name/prefix rootdirectory: /gcs/object/name/prefix
chunksize: 5242880 chunksize: 5242880
s3: s3:
@ -140,7 +147,8 @@ storage:
endpoint: optional endpoints endpoint: optional endpoints
internal: optional internal endpoint internal: optional internal endpoint
bucket: OSS bucket bucket: OSS bucket
encrypt: optional data encryption setting encrypt: optional enable server-side encryption
encryptionkeyid: optional KMS key id for encryption
secure: optional ssl setting secure: optional ssl setting
chunksize: optional size valye chunksize: optional size valye
rootdirectory: optional root directory rootdirectory: optional root directory
@ -164,6 +172,7 @@ auth:
realm: silly-realm realm: silly-realm
service: silly-service service: silly-service
token: token:
autoredirect: true
realm: token-realm realm: token-realm
service: token-service service: token-service
issuer: registry-token-issuer issuer: registry-token-issuer
@ -187,6 +196,10 @@ middleware:
privatekey: /path/to/pem privatekey: /path/to/pem
keypairid: cloudfrontkeypairid keypairid: cloudfrontkeypairid
duration: 3000s duration: 3000s
ipfilteredby: awsregion
awsregion: us-east-1, use-east-2
updatefrequency: 12h
iprangesurl: https://ip-ranges.amazonaws.com/ip-ranges.json
storage: storage:
- name: redirect - name: redirect
options: options:
@ -206,6 +219,7 @@ http:
host: https://myregistryaddress.org:5000 host: https://myregistryaddress.org:5000
secret: asecretforlocaldevelopment secret: asecretforlocaldevelopment
relativeurls: false relativeurls: false
draintimeout: 60s
tls: tls:
certificate: /path/to/x509/public certificate: /path/to/x509/public
key: /path/to/x509/private key: /path/to/x509/private
@ -215,23 +229,34 @@ http:
letsencrypt: letsencrypt:
cachefile: /path/to/cache-file cachefile: /path/to/cache-file
email: emailused@letsencrypt.com email: emailused@letsencrypt.com
hosts: [myregistryaddress.org]
debug: debug:
addr: localhost:5001 addr: localhost:5001
prometheus:
enabled: true
path: /metrics
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
http2: http2:
disabled: false disabled: false
notifications: notifications:
events:
includereferences: true
endpoints: endpoints:
- name: alistener - name: alistener
disabled: false disabled: false
url: https://my.listener.com/event url: https://my.listener.com/event
headers: <http.Header> headers: <http.Header>
timeout: 500 timeout: 1s
threshold: 5 threshold: 10
backoff: 1000 backoff: 1s
ignoredmediatypes: ignoredmediatypes:
- application/octet-stream - application/octet-stream
ignore:
mediatypes:
- application/octet-stream
actions:
- pull
redis: redis:
addr: localhost:6379 addr: localhost:6379
password: asecret password: asecret
@ -271,6 +296,7 @@ proxy:
compatibility: compatibility:
schema1: schema1:
signingkeyfile: /etc/registry/key.json signingkeyfile: /etc/registry/key.json
enabled: true
validation: validation:
manifests: manifests:
urls: urls:
@ -363,21 +389,6 @@ loglevel: debug
Permitted values are `error`, `warn`, `info` and `debug`. The default is Permitted values are `error`, `warn`, `info` and `debug`. The default is
`info`. `info`.
## `plugins`
```none
plugins:
- /plugins/
- /plugin/driver1.so
- /plugin/auth1.so
```
> Requires golang >= 1.8
Directory with plugins or paths point to plugins. Plugin are loaded before trying to initialize
any driver or authcontroller. If a path is a directory, it is scanned for plugins loading all files
with a is common shared library extension on the platform (`.so`, `.dylib`, `dll`).
## `storage` ## `storage`
```none ```none
@ -391,6 +402,17 @@ storage:
gcs: gcs:
bucket: bucketname bucket: bucketname
keyfile: /path/to/keyfile keyfile: /path/to/keyfile
credentials:
type: service_account
project_id: project_id_string
private_key_id: private_key_id_string
private_key: private_key_string
client_email: client@example.com
client_id: client_id_string
auth_uri: http://example.com/auth_uri
token_uri: http://example.com/token_uri
auth_provider_x509_cert_url: http://example.com/provider_cert_url
client_x509_cert_url: http://example.com/client_cert_url
rootdirectory: /gcs/object/name/prefix rootdirectory: /gcs/object/name/prefix
s3: s3:
accesskey: awsaccesskey accesskey: awsaccesskey
@ -426,7 +448,8 @@ storage:
endpoint: optional endpoints endpoint: optional endpoints
internal: optional internal endpoint internal: optional internal endpoint
bucket: OSS bucket bucket: OSS bucket
encrypt: optional data encryption setting encrypt: optional enable server-side encryption
encryptionkeyid: optional KMS key id for encryption
secure: optional ssl setting secure: optional ssl setting
chunksize: optional size valye chunksize: optional size valye
rootdirectory: optional root directory rootdirectory: optional root directory
@ -571,7 +594,8 @@ The `auth` option is **optional**. Possible auth providers include:
- [`silly`](#silly) - [`silly`](#silly)
- [`token`](#token) - [`token`](#token)
- [`htpasswd`](#token) - [`htpasswd`](#htpasswd)
- [`none`]
You can configure only one authentication provider. You can configure only one authentication provider.
@ -602,6 +626,7 @@ security.
| `service` | yes | The service being authenticated. | | `service` | yes | The service being authenticated. |
| `issuer` | yes | The name of the token issuer. The issuer inserts this into the token so it must match the value configured for the issuer. | | `issuer` | yes | The name of the token issuer. The issuer inserts this into the token so it must match the value configured for the issuer. |
| `rootcertbundle` | yes | The absolute path to the root certificate bundle. This bundle contains the public part of the certificates used to sign authentication tokens. | | `rootcertbundle` | yes | The absolute path to the root certificate bundle. This bundle contains the public part of the certificates used to sign authentication tokens. |
| `autoredirect` | no | When set to `true`, `realm` will automatically be set using the Host header of the request as the domain and a path of `/auth/token/`|
For more information about Token based authentication configuration, see the For more information about Token based authentication configuration, see the
@ -617,6 +642,9 @@ The only supported password format is
are ignored. The `htpasswd` file is loaded once, at startup. If the file is are ignored. The `htpasswd` file is loaded once, at startup. If the file is
invalid, the registry will display an error and will not start. invalid, the registry will display an error and will not start.
> **Warning**: If the `htpasswd` file is missing, the file will be created and provisioned with a default user and automatically generated password.
> The password will be printed to stdout.
> **Warning**: Only use the `htpasswd` authentication scheme with TLS > **Warning**: Only use the `htpasswd` authentication scheme with TLS
> configured, since basic authentication sends passwords as part of the HTTP > configured, since basic authentication sends passwords as part of the HTTP
> header. > header.
@ -655,6 +683,10 @@ middleware:
privatekey: /path/to/pem privatekey: /path/to/pem
keypairid: cloudfrontkeypairid keypairid: cloudfrontkeypairid
duration: 3000s duration: 3000s
ipfilteredby: awsregion
awsregion: us-east-1, use-east-2
updatefrequency: 12h
iprangesurl: https://ip-ranges.amazonaws.com/ip-ranges.json
``` ```
Each middleware entry has `name` and `options` entries. The `name` must Each middleware entry has `name` and `options` entries. The `name` must
@ -673,7 +705,31 @@ interpretation of the options.
| `baseurl` | yes | The `SCHEME://HOST[/PATH]` at which Cloudfront is served. | | `baseurl` | yes | The `SCHEME://HOST[/PATH]` at which Cloudfront is served. |
| `privatekey` | yes | The private key for Cloudfront, provided by AWS. | | `privatekey` | yes | The private key for Cloudfront, provided by AWS. |
| `keypairid` | yes | The key pair ID provided by AWS. | | `keypairid` | yes | The key pair ID provided by AWS. |
| `duration` | no | An integer and unit for the duration of the Cloudfront session. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `3000s` is valid, but `3000 s` is not. If you do not specify a `duration` or you specify an integer without a time unit, the duration defaults to `20m` (20 minutes).| | `duration` | no | An integer and unit for the duration of the Cloudfront session. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `3000s` is valid, but `3000 s` is not. If you do not specify a `duration` or you specify an integer without a time unit, the duration defaults to `20m` (20 minutes). |
| `ipfilteredby` | no | A string with the following value `none`, `aws` or `awsregion`. |
| `awsregion` | no | A comma separated string of AWS regions, only available when `ipfilteredby` is `awsregion`. For example, `us-east-1, us-west-2` |
| `updatefrequency` | no | The frequency to update AWS IP regions, default: `12h` |
| `iprangesurl` | no | The URL contains the AWS IP ranges information, default: `https://ip-ranges.amazonaws.com/ip-ranges.json` |
Value of `ipfilteredby` can be:
| Value | Description |
|-------------|------------------------------------|
| `none` | default, do not filter by IP |
| `aws` | IP from AWS goes to S3 directly |
| `awsregion` | IP from certain AWS regions goes to S3 directly, use together with `awsregion`. |
### `alicdn`
`alicdn` storage middleware allows the registry to serve layers via a content delivery network provided by Alibaba Cloud. Alicdn requires the OSS storage driver.
| Parameter | Required | Description |
|--------------|----------|-------------------------------------------------------------------------|
| `baseurl` | yes | The `SCHEME://HOST` at which Alicdn is served. |
| `authtype` | yes | The URL authentication type for Alicdn, which should be `a`, `b` or `c`. See the [Authentication configuration](https://www.alibabacloud.com/help/doc-detail/85117.htm).|
| `privatekey` | yes | The URL authentication key for Alicdn. |
| `duration` | no | An integer and unit for the duration of the Alicdn session. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`.|
### `redirect` ### `redirect`
@ -732,15 +788,18 @@ http:
host: https://myregistryaddress.org:5000 host: https://myregistryaddress.org:5000
secret: asecretforlocaldevelopment secret: asecretforlocaldevelopment
relativeurls: false relativeurls: false
draintimeout: 60s
tls: tls:
certificate: /path/to/x509/public certificate: /path/to/x509/public
key: /path/to/x509/private key: /path/to/x509/private
clientcas: clientcas:
- /path/to/ca.pem - /path/to/ca.pem
- /path/to/another/ca.pem - /path/to/another/ca.pem
minimumtls: tls1.0
letsencrypt: letsencrypt:
cachefile: /path/to/cache-file cachefile: /path/to/cache-file
email: emailused@letsencrypt.com email: emailused@letsencrypt.com
hosts: [myregistryaddress.org]
debug: debug:
addr: localhost:5001 addr: localhost:5001
headers: headers:
@ -760,6 +819,7 @@ registry.
| `host` | no | A fully-qualified URL for an externally-reachable address for the registry. If present, it is used when creating generated URLs. Otherwise, these URLs are derived from client requests. | | `host` | no | A fully-qualified URL for an externally-reachable address for the registry. If present, it is used when creating generated URLs. Otherwise, these URLs are derived from client requests. |
| `secret` | no | A random piece of data used to sign state that may be stored with the client to protect against tampering. For production environments you should generate a random piece of data using a cryptographically secure random generator. If you omit the secret, the registry will automatically generate a secret when it starts. **If you are building a cluster of registries behind a load balancer, you MUST ensure the secret is the same for all registries.**| | `secret` | no | A random piece of data used to sign state that may be stored with the client to protect against tampering. For production environments you should generate a random piece of data using a cryptographically secure random generator. If you omit the secret, the registry will automatically generate a secret when it starts. **If you are building a cluster of registries behind a load balancer, you MUST ensure the secret is the same for all registries.**|
| `relativeurls`| no | If `true`, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL. **This option is not compatible with Docker 1.7 and earlier.**| | `relativeurls`| no | If `true`, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL. **This option is not compatible with Docker 1.7 and earlier.**|
| `draintimeout`| no | Amount of time to wait for HTTP connections to drain before shutting down after registry receives SIGTERM signal|
### `tls` ### `tls`
@ -774,6 +834,7 @@ and proxy connections to the registry server.
| `certificate` | yes | Absolute path to the x509 certificate file. | | `certificate` | yes | Absolute path to the x509 certificate file. |
| `key` | yes | Absolute path to the x509 private key file. | | `key` | yes | Absolute path to the x509 private key file. |
| `clientcas` | no | An array of absolute paths to x509 CA files. | | `clientcas` | no | An array of absolute paths to x509 CA files. |
| `minimumtls` | no | Minimum TLS version allowed (tls1.0, tls1.1, tls1.2). Defaults to tls1.0 |
### `letsencrypt` ### `letsencrypt`
@ -785,12 +846,17 @@ TLS certificates provided by
> accessible on port `443`. The registry defaults to listening on port `5000`. > accessible on port `443`. The registry defaults to listening on port `5000`.
> If you run the registry as a container, consider adding the flag `-p 443:5000` > If you run the registry as a container, consider adding the flag `-p 443:5000`
> to the `docker run` command or using a similar setting in a cloud > to the `docker run` command or using a similar setting in a cloud
> configuration. > configuration. You should also set the `hosts` option to the list of hostnames
> that are valid for this registry to avoid trying to get certificates for random
> hostnames due to malicious clients connecting with bogus SNI hostnames. Please
> ensure that you have the `ca-certificates` package installed in order to verify
> letsencrypt certificates.
| Parameter | Required | Description | | Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------| |-----------|----------|-------------------------------------------------------|
| `cachefile` | yes | Absolute path to a file where the Let's Encrypt agent can cache data. | | `cachefile` | yes | Absolute path to a file where the Let's Encrypt agent can cache data. |
| `email` | yes | The email address used to register with Let's Encrypt. | | `email` | yes | The email address used to register with Let's Encrypt. |
| `hosts` | no | The hostnames allowed for Let's Encrypt certificates. |
### `debug` ### `debug`
@ -803,6 +869,19 @@ access to the debug endpoint is locked down in a production environment.
The `debug` section takes a single required `addr` parameter, which specifies The `debug` section takes a single required `addr` parameter, which specifies
the `HOST:PORT` on which the debug server should accept connections. the `HOST:PORT` on which the debug server should accept connections.
## `prometheus`
The `prometheus` option defines whether the prometheus metrics is enable, as well
as the path to access the metrics.
| Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------|
| `enabled` | no | Set `true` to enable the prometheus server |
| `path` | no | The path to access the metrics, `/metrics` by default |
The url to access the metrics is `HOST:PORT/path`, where `HOST:PORT` is defined
in `addr` under `debug`.
### `headers` ### `headers`
The `headers` option is **optional** . Use it to specify headers that the HTTP The `headers` option is **optional** . Use it to specify headers that the HTTP
@ -830,16 +909,23 @@ settings for the registry.
```none ```none
notifications: notifications:
events:
includereferences: true
endpoints: endpoints:
- name: alistener - name: alistener
disabled: false disabled: false
url: https://my.listener.com/event url: https://my.listener.com/event
headers: <http.Header> headers: <http.Header>
timeout: 500 timeout: 1s
threshold: 5 threshold: 10
backoff: 1000 backoff: 1s
ignoredmediatypes: ignoredmediatypes:
- application/octet-stream - application/octet-stream
ignore:
mediatypes:
- application/octet-stream
actions:
- pull
``` ```
The notifications option is **optional** and currently may contain a single The notifications option is **optional** and currently may contain a single
@ -860,6 +946,21 @@ accept event notifications.
| `threshold` | yes | An integer specifying how long to wait before backing off a failure. | | `threshold` | yes | An integer specifying how long to wait before backing off a failure. |
| `backoff` | yes | How long the system backs off before retrying after a failure. A positive integer and an optional suffix indicating the unit of time, which may be `ns`, `us`, `ms`, `s`, `m`, or `h`. If you omit the unit of time, `ns` is used. | | `backoff` | yes | How long the system backs off before retrying after a failure. A positive integer and an optional suffix indicating the unit of time, which may be `ns`, `us`, `ms`, `s`, `m`, or `h`. If you omit the unit of time, `ns` is used. |
| `ignoredmediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. | | `ignoredmediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. |
| `ignore` |no| Events with these mediatypes or actions are not published to the endpoint. |
#### `ignore`
| Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------|
| `mediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. |
| `actions` |no| A list of actions to ignore. Events with these actions are not published to the endpoint. |
### `events`
The `events` structure configures the information provided in event notifications.
| Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------|
| `includereferences` | no | If `true`, include reference information in manifest events. |
## `redis` ## `redis`
@ -966,7 +1067,7 @@ a file.
| Parameter | Required | Description | | Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------| |-----------|----------|-------------------------------------------------------|
| `file` | yes | The path to check for existence of a file. | | `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` ### `http`
@ -1031,6 +1132,7 @@ username (such as `batman`) and the password for that username.
compatibility: compatibility:
schema1: schema1:
signingkeyfile: /etc/registry/key.json signingkeyfile: /etc/registry/key.json
enabled: true
``` ```
Use the `compatibility` structure to configure handling of older and deprecated Use the `compatibility` structure to configure handling of older and deprecated
@ -1041,6 +1143,7 @@ features. Each subsection defines such a feature with configurable behavior.
| Parameter | Required | Description | | Parameter | Required | Description |
|-----------|----------|-------------------------------------------------------| |-----------|----------|-------------------------------------------------------|
| `signingkeyfile` | no | The signing private key used to add signatures to `schema1` manifests. If no signing key is provided, a new ECDSA key is generated when the registry starts. | | `signingkeyfile` | no | The signing private key used to add signatures to `schema1` manifests. If no signing key is provided, a new ECDSA key is generated when the registry starts. |
| `enabled` | no | If this is not set to true, `schema1` manifests cannot be pushed. |
## `validation` ## `validation`
@ -1128,7 +1231,7 @@ middleware:
baseurl: http://d111111abcdef8.cloudfront.net baseurl: http://d111111abcdef8.cloudfront.net
privatekey: /path/to/asecret.pem privatekey: /path/to/asecret.pem
keypairid: asecret keypairid: asecret
duration: 60 duration: 60s
``` ```
See the configuration reference for [Cloudfront](#cloudfront) for more See the configuration reference for [Cloudfront](#cloudfront) for more

View file

@ -1,7 +1,9 @@
--- ---
title: "HTTP API V2" title: "HTTP API V2"
description: "Specification for the Registry API." description: "Specification for the Registry API."
keywords: ["registry, on-prem, images, tags, repository, distribution, api, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, api, advanced
redirect_from:
- /reference/api/registry_api/
--- ---
# Docker Registry HTTP API V2 # Docker Registry HTTP API V2
@ -16,7 +18,7 @@ of this API, known as _Docker Registry HTTP API V2_.
While the V1 registry protocol is usable, there are several problems with the While the V1 registry protocol is usable, there are several problems with the
architecture that have led to this new version. The main driver of this architecture that have led to this new version. The main driver of this
specification is a set of changes to the docker the image format, covered in specification is a set of changes to the Docker image format, covered in
[docker/docker#8093](https://github.com/docker/docker/issues/8093). [docker/docker#8093](https://github.com/docker/docker/issues/8093).
The new, self-contained image manifest simplifies image definition and improves The new, self-contained image manifest simplifies image definition and improves
security. This specification will build on that work, leveraging new properties security. This specification will build on that work, leveraging new properties
@ -676,7 +678,7 @@ the upload will not be considered complete. The format for the final chunk
will be as follows: will be as follows:
``` ```
PUT /v2/<name>/blob/uploads/<uuid>?digest=<digest> PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>
Content-Length: <size of chunk> Content-Length: <size of chunk>
Content-Range: <start of range>-<end of range> Content-Range: <start of range>-<end of range>
Content-Type: application/octet-stream Content-Type: application/octet-stream
@ -685,7 +687,7 @@ Content-Type: application/octet-stream
``` ```
Optionally, if all chunks have already been uploaded, a `PUT` request with a Optionally, if all chunks have already been uploaded, a `PUT` request with a
`digest` parameter and zero-length body may be sent to complete and validated `digest` parameter and zero-length body may be sent to complete and validate
the upload. Multiple "digest" parameters may be provided with different the upload. Multiple "digest" parameters may be provided with different
digests. The server may verify none or all of them but _must_ notify the digests. The server may verify none or all of them but _must_ notify the
client if the content is rejected. client if the content is rejected.
@ -1206,7 +1208,7 @@ The registry does not implement the V2 API.
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1244,7 +1246,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1316,7 +1318,7 @@ The following parameters should be specified on the request:
``` ```
200 OK 200 OK
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"name": <name>, "name": <name>,
@ -1344,7 +1346,7 @@ The following headers will be returned with the response:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1382,7 +1384,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1419,7 +1421,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1456,7 +1458,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1514,7 +1516,7 @@ The following parameters should be specified on the request:
200 OK 200 OK
Content-Length: <length> Content-Length: <length>
Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next" Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next"
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"name": <name>, "name": <name>,
@ -1543,7 +1545,7 @@ The following headers will be returned with the response:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1581,7 +1583,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1618,7 +1620,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1655,7 +1657,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1759,7 +1761,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1792,7 +1794,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1830,7 +1832,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1867,7 +1869,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -1904,7 +1906,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2005,7 +2007,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2041,7 +2043,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2079,7 +2081,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2116,7 +2118,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2153,7 +2155,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2189,7 +2191,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [{ "errors:" [{
@ -2277,7 +2279,7 @@ The following parameters should be specified on the request:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2310,7 +2312,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2348,7 +2350,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2385,7 +2387,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2422,7 +2424,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2458,7 +2460,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2583,7 +2585,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2614,7 +2616,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2647,7 +2649,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2685,7 +2687,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2722,7 +2724,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2759,7 +2761,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2843,7 +2845,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2874,7 +2876,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2917,7 +2919,7 @@ The range specification cannot be satisfied for the requested content. This can
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2955,7 +2957,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -2992,7 +2994,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3029,7 +3031,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3132,7 +3134,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3163,7 +3165,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
405 Method Not Allowed 405 Method Not Allowed
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3195,7 +3197,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3233,7 +3235,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3270,7 +3272,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3307,7 +3309,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3445,7 +3447,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3483,7 +3485,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3520,7 +3522,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3557,7 +3559,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3662,7 +3664,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3700,7 +3702,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3737,7 +3739,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3774,7 +3776,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3897,7 +3899,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3935,7 +3937,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -3972,7 +3974,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4009,7 +4011,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4102,7 +4104,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4134,7 +4136,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4166,7 +4168,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4204,7 +4206,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4241,7 +4243,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4278,7 +4280,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4370,7 +4372,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4402,7 +4404,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4434,7 +4436,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4472,7 +4474,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4509,7 +4511,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4546,7 +4548,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4636,7 +4638,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4668,7 +4670,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4710,7 +4712,7 @@ The `Content-Range` specification cannot be accepted, either because it does not
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4748,7 +4750,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4785,7 +4787,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4822,7 +4824,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4916,7 +4918,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4949,7 +4951,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -4981,7 +4983,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5019,7 +5021,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5056,7 +5058,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5093,7 +5095,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5177,7 +5179,7 @@ The following headers will be returned with the response:
``` ```
400 Bad Request 400 Bad Request
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5208,7 +5210,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5240,7 +5242,7 @@ The error codes that may be included in the response body are enumerated below:
401 Unauthorized 401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..." WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5278,7 +5280,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
404 Not Found 404 Not Found
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5315,7 +5317,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
403 Forbidden 403 Forbidden
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5352,7 +5354,7 @@ The error codes that may be included in the response body are enumerated below:
``` ```
429 Too Many Requests 429 Too Many Requests
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"errors:" [ "errors:" [
@ -5414,7 +5416,7 @@ Request an unabridged list of repositories available. The implementation may im
``` ```
200 OK 200 OK
Content-Length: <length> Content-Length: <length>
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"repositories": [ "repositories": [
@ -5459,7 +5461,7 @@ The following parameters should be specified on the request:
200 OK 200 OK
Content-Length: <length> Content-Length: <length>
Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next" Link: <<url>?n=<last n value>&last=<last entry from response>>; rel="next"
Content-Type: application/json; charset=utf-8 Content-Type: application/json
{ {
"repositories": [ "repositories": [

View file

@ -1,7 +1,9 @@
--- ---
title: "HTTP API V2" title: "HTTP API V2"
description: "Specification for the Registry API." description: "Specification for the Registry API."
keywords: ["registry, on-prem, images, tags, repository, distribution, api, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, api, advanced
redirect_from:
- /reference/api/registry_api/
--- ---
# Docker Registry HTTP API V2 # Docker Registry HTTP API V2
@ -16,7 +18,7 @@ of this API, known as _Docker Registry HTTP API V2_.
While the V1 registry protocol is usable, there are several problems with the While the V1 registry protocol is usable, there are several problems with the
architecture that have led to this new version. The main driver of this architecture that have led to this new version. The main driver of this
specification is a set of changes to the docker the image format, covered in specification is a set of changes to the Docker image format, covered in
[docker/docker#8093](https://github.com/docker/docker/issues/8093). [docker/docker#8093](https://github.com/docker/docker/issues/8093).
The new, self-contained image manifest simplifies image definition and improves The new, self-contained image manifest simplifies image definition and improves
security. This specification will build on that work, leveraging new properties security. This specification will build on that work, leveraging new properties
@ -676,7 +678,7 @@ the upload will not be considered complete. The format for the final chunk
will be as follows: will be as follows:
``` ```
PUT /v2/<name>/blob/uploads/<uuid>?digest=<digest> PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>
Content-Length: <size of chunk> Content-Length: <size of chunk>
Content-Range: <start of range>-<end of range> Content-Range: <start of range>-<end of range>
Content-Type: application/octet-stream Content-Type: application/octet-stream
@ -685,7 +687,7 @@ Content-Type: application/octet-stream
``` ```
Optionally, if all chunks have already been uploaded, a `PUT` request with a Optionally, if all chunks have already been uploaded, a `PUT` request with a
`digest` parameter and zero-length body may be sent to complete and validated `digest` parameter and zero-length body may be sent to complete and validate
the upload. Multiple "digest" parameters may be provided with different the upload. Multiple "digest" parameters may be provided with different
digests. The server may verify none or all of them but _must_ notify the digests. The server may verify none or all of them but _must_ notify the
client if the content is rejected. client if the content is rejected.

View file

@ -1,7 +1,7 @@
--- ---
title: "Docker Registry Token Authentication" title: "Docker Registry Token Authentication"
description: "Docker Registry v2 authentication schema" description: "Docker Registry v2 authentication schema"
keywords: ["registry, on-prem, images, tags, repository, distribution, authentication, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, authentication, advanced
--- ---
# Docker Registry v2 authentication # Docker Registry v2 authentication

View file

@ -1,7 +1,7 @@
--- ---
title: "Token Authentication Implementation" title: "Token Authentication Implementation"
description: "Describe the reference implementation of the Docker Registry v2 authentication schema" description: "Describe the reference implementation of the Docker Registry v2 authentication schema"
keywords: ["registry, on-prem, images, tags, repository, distribution, JWT authentication, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, JWT authentication, advanced
--- ---
# Docker Registry v2 Bearer token specification # Docker Registry v2 Bearer token specification

View file

@ -1,7 +1,7 @@
--- ---
title: "Oauth2 Token Authentication" title: "Oauth2 Token Authentication"
description: "Specifies the Docker Registry v2 authentication" description: "Specifies the Docker Registry v2 authentication"
keywords: ["registry, on-prem, images, tags, repository, distribution, oauth2, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, oauth2, advanced
--- ---
# Docker Registry v2 authentication using OAuth2 # Docker Registry v2 authentication using OAuth2
@ -39,7 +39,7 @@ Content-Type: application/x-www-form-urlencoded
<dd> <dd>
(REQUIRED) Type of grant used to get token. When getting a refresh token (REQUIRED) Type of grant used to get token. When getting a refresh token
using credentials this type should be set to "password" and have the using credentials this type should be set to "password" and have the
accompanying username and password paramters. Type "authorization_code" accompanying username and password parameters. Type "authorization_code"
is reserved for future use for authenticating to an authorization server is reserved for future use for authenticating to an authorization server
without having to send credentials directly from the client. When without having to send credentials directly from the client. When
requesting an access token with a refresh token this should be set to requesting an access token with a refresh token this should be set to

View file

@ -1,7 +1,7 @@
--- ---
title: "Token Scope Documentation" title: "Token Scope Documentation"
description: "Describes the scope and access fields used for registry authorization tokens" description: "Describes the scope and access fields used for registry authorization tokens"
keywords: ["registry, on-prem, images, tags, repository, distribution, advanced, access, scope"] keywords: registry, on-prem, images, tags, repository, distribution, advanced, access, scope
--- ---
# Docker Registry Token Scope and Access # Docker Registry Token Scope and Access

View file

@ -1,14 +1,14 @@
--- ---
title: "Token Authentication Specification" title: "Token Authentication Specification"
description: "Specifies the Docker Registry v2 authentication" description: "Specifies the Docker Registry v2 authentication"
keywords: ["registry, on-prem, images, tags, repository, distribution, Bearer authentication, advanced"] keywords: registry, on-prem, images, tags, repository, distribution, Bearer authentication, advanced
--- ---
# Docker Registry v2 authentication via central service # Docker Registry v2 authentication via central service
This document outlines the v2 Docker registry authentication scheme: This document outlines the v2 Docker registry authentication scheme:
![v2 registry auth](../../images/v2-registry-auth.png) ![v2 registry auth](../images/v2-registry-auth.png)
1. Attempt to begin a push/pull operation with the registry. 1. Attempt to begin a push/pull operation with the registry.
2. If the registry requires authorization it will return a `401 Unauthorized` 2. If the registry requires authorization it will return a `401 Unauthorized`
@ -60,7 +60,7 @@ return this response:
``` ```
HTTP/1.1 401 Unauthorized HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8 Content-Type: application/json
Docker-Distribution-Api-Version: registry/2.0 Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push" Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
Date: Thu, 10 Sep 2015 19:32:31 GMT Date: Thu, 10 Sep 2015 19:32:31 GMT

View file

@ -0,0 +1,41 @@
---
title: Update deprecated schema image manifest version 2, v1 images
description: Update deprecated schema v1 iamges
keywords: registry, on-prem, images, tags, repository, distribution, api, advanced, manifest
---
## Image manifest version 2, schema 1
With the release of image manifest version 2, schema 2, image manifest version
2, schema 1 has been deprecated. This could lead to compatibility and
vulnerability issues in images that haven't been updated to image manifest
version 2, schema 2.
This page contains information on how to update from image manifest version 2,
schema 1. However, these instructions will not ensure your new image will run
successfully. There may be several other issues to troubleshoot that are
associated with the deprecated image manifest that will block your image from
running succesfully. A list of possible methods to help update your image is
also included below.
### Update to image manifest version 2, schema 2
One way to upgrade an image from image manifest version 2, schema 1 to
schema 2 is to `docker pull` the image and then `docker push` the image with a
current version of Docker. Doing so will automatically convert the image to use
the latest image manifest specification.
Converting an image to image manifest version 2, schema 2 converts the
manifest format, but does not update the contents within the image. Images
using manifest version 2, schema 1 may contain unpatched vulnerabilities. We
recommend looking for an alternative image or rebuilding it.
### Update FROM statement
You can rebuild the image by updating the `FROM` statement in your
`Dockerfile`. If your image manifest is out-of-date, there is a chance the
image pulled from your `FROM` statement in your `Dockerfile` is also
out-of-date. See the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/#from)
and the [Dockerfile best practices guide](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
for more information on how to update the `FROM` statement in your
`Dockerfile`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,12 +1,12 @@
--- ---
title: "Reference Overview" title: "Reference Overview"
description: "Explains registry JSON objects" description: "Explains registry JSON objects"
keywords: ["registry, service, images, repository, json"] keywords: registry, service, images, repository, json
--- ---
# Docker Registry Reference # Docker Registry Reference
* [HTTP API V2](api.md) * [HTTP API V2](api.md)
* [Storage Driver](../storage-drivers/index.md) * [Storage Driver](https://docs.docker.com/registry/storage-drivers/)
* [Token Authentication Specification](auth/token.md) * [Token Authentication Specification](auth/token.md)
* [Token Authentication Implementation](auth/jwt.md) * [Token Authentication Implementation](auth/jwt.md)

View file

@ -1,7 +1,7 @@
--- ---
title: "Image Manifest V 2, Schema 1 " title: "Image Manifest V 2, Schema 1 "
description: "image manifest for the Registry." description: "image manifest for the Registry."
keywords: ["registry, on-prem, images, tags, repository, distribution, api, advanced, manifest"] keywords: registry, on-prem, images, tags, repository, distribution, api, advanced, manifest
--- ---
# Image Manifest Version 2, Schema 1 # Image Manifest Version 2, Schema 1

View file

@ -1,7 +1,7 @@
--- ---
title: "Image Manifest V 2, Schema 2 " title: "Image Manifest V 2, Schema 2 "
description: "image manifest for the Registry." description: "image manifest for the Registry."
keywords: ["registry, on-prem, images, tags, repository, distribution, api, advanced, manifest"] keywords: registry, on-prem, images, tags, repository, distribution, api, advanced, manifest
--- ---
# Image Manifest Version 2, Schema 2 # Image Manifest Version 2, Schema 2
@ -60,8 +60,8 @@ image manifest based on the Content-Type returned in the HTTP response.
- **`mediaType`** *string* - **`mediaType`** *string*
The MIME type of the referenced object. This will generally be The MIME type of the referenced object. This will generally be
`application/vnd.docker.image.manifest.v2+json`, but it could also `application/vnd.docker.distribution.manifest.v2+json`, but it could also
be `application/vnd.docker.image.manifest.v1+json` if the manifest be `application/vnd.docker.distribution.manifest.v1+json` if the manifest
list references a legacy schema-1 manifest. list references a legacy schema-1 manifest.
- **`size`** *int* - **`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", "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [ "manifests": [
{ {
"mediaType": "application/vnd.docker.image.manifest.v2+json", "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 7143, "size": 7143,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f", "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
"platform": { "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, "size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270", "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"platform": { "platform": {

View file

@ -1,7 +1,7 @@
--- ---
title: "Reference" title: "Reference"
description: "Explains registry JSON objects" description: "Explains registry JSON objects"
keywords: ["registry, service, images, repository, json"] keywords: registry, service, images, repository, json
type: "menu" type: "menu"
identifier: "smn_registry_ref" identifier: "smn_registry_ref"
--- ---

View file

@ -20,6 +20,10 @@ var ErrManifestNotModified = errors.New("manifest not modified")
// performed // performed
var ErrUnsupported = errors.New("operation unsupported") var ErrUnsupported = errors.New("operation unsupported")
// ErrSchemaV1Unsupported is returned when a client tries to upload a schema v1
// manifest but the registry is configured to reject it
var ErrSchemaV1Unsupported = errors.New("manifest schema v1 unsupported")
// ErrTagUnknown is returned if the given tag is not known by the tag service // ErrTagUnknown is returned if the given tag is not known by the tag service
type ErrTagUnknown struct { type ErrTagUnknown struct {
Tag string Tag string
@ -77,7 +81,7 @@ func (err ErrManifestUnknownRevision) Error() string {
type ErrManifestUnverified struct{} type ErrManifestUnverified struct{}
func (ErrManifestUnverified) Error() string { func (ErrManifestUnverified) Error() string {
return fmt.Sprintf("unverified manifest") return "unverified manifest"
} }
// ErrManifestVerification provides a type to collect errors encountered // ErrManifestVerification provides a type to collect errors encountered

47
go.mod Normal file
View file

@ -0,0 +1,47 @@
module github.com/docker/distribution
go 1.12
require (
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible
github.com/Azure/go-autorest v10.8.1+incompatible // indirect
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d
github.com/aws/aws-sdk-go v1.34.9
github.com/bitly/go-simplejson v0.5.0 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/bshuster-repo/logrus-logstash-hook v0.4.1
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c // indirect
github.com/dnaeon/go-vcr v1.0.1 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c
github.com/docker/go-metrics v0.0.1
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
github.com/gorilla/mux v1.7.2
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/marstr/guid v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.1.2
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f // indirect
github.com/ncw/swift v1.0.47
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.1
github.com/satori/go.uuid v1.2.0 // indirect
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a // indirect
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789
gopkg.in/yaml.v2 v2.2.2
)

176
go.sum Normal file
View file

@ -0,0 +1,176 @@
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible h1:KnPIugL51v3N3WwvaSmZbxukD1WuWXOiE9fRdu32f2I=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v10.8.1+incompatible h1:u0jVQf+a6k6x8A+sT60l6EY9XZu+kHdnZVPAYqpVRo0=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aws/aws-sdk-go v1.34.9 h1:cUGBW9CVdi0mS7K1hDzxIqTpfeWhpoQiguq81M1tjK0=
github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba h1:p6poVbjHDkKa+wtC8frBMwQtT3BmqGYBjzMwJ63tuR4=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c h1:KJAnOBuY9cTKVqB5cfbynpvFgeHRTREkRk8C977oFu4=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I=
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/marstr/guid v1.1.0 h1:/M4H/1G4avsieL6BbUwCOBzulmoeKVP5ux/3mQNnbyI=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/ncw/swift v1.0.47 h1:4DQRPj35Y41WogBxyhOXlrI37nzGlyEcsforeudyYPQ=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff h1:mk5zS3XLqVUzdF/CQCZ5ERujSF/8JFo+Wpkp/5I93NA=
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8 h1:Cpp2P6TPjujNoC5M2KHY6g7wfyLYfIWRZaSdIKfDasA=
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a h1:zo0EaRwJM6T5UQ+QEt2dDSgEmbFJ4pZr/Rzsjpu7zgI=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789 h1:NMiUjDZiD6qDVeBOzpImftxXzQHCp2Y2QLdmaqU9MRk=
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -14,7 +14,7 @@ var (
// DownHandler registers a manual_http_status that always returns an Error // DownHandler registers a manual_http_status that always returns an Error
func DownHandler(w http.ResponseWriter, r *http.Request) { func DownHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" { if r.Method == "POST" {
updater.Update(errors.New("Manual Check")) updater.Update(errors.New("manual Check"))
} else { } else {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
} }

View file

@ -215,7 +215,7 @@ func RegisterFunc(name string, check func() error) {
// RegisterPeriodicFunc allows the convenience of registering a PeriodicChecker // RegisterPeriodicFunc allows the convenience of registering a PeriodicChecker
// from an arbitrary func() error. // from an arbitrary func() error.
func (registry *Registry) RegisterPeriodicFunc(name string, period time.Duration, check CheckFunc) { func (registry *Registry) RegisterPeriodicFunc(name string, period time.Duration, check CheckFunc) {
registry.Register(name, PeriodicChecker(CheckFunc(check), period)) registry.Register(name, PeriodicChecker(check, period))
} }
// RegisterPeriodicFunc allows the convenience of registering a PeriodicChecker // RegisterPeriodicFunc allows the convenience of registering a PeriodicChecker
@ -227,7 +227,7 @@ func RegisterPeriodicFunc(name string, period time.Duration, check CheckFunc) {
// RegisterPeriodicThresholdFunc allows the convenience of registering a // RegisterPeriodicThresholdFunc allows the convenience of registering a
// PeriodicChecker from an arbitrary func() error. // PeriodicChecker from an arbitrary func() error.
func (registry *Registry) RegisterPeriodicThresholdFunc(name string, period time.Duration, threshold int, check CheckFunc) { func (registry *Registry) RegisterPeriodicThresholdFunc(name string, period time.Duration, threshold int, check CheckFunc) {
registry.Register(name, PeriodicThresholdChecker(CheckFunc(check), period, threshold)) registry.Register(name, PeriodicThresholdChecker(check, period, threshold))
} }
// RegisterPeriodicThresholdFunc allows the convenience of registering a // RegisterPeriodicThresholdFunc allows the convenience of registering a
@ -291,7 +291,7 @@ func statusResponse(w http.ResponseWriter, r *http.Request, status int, checks m
} }
} }
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", fmt.Sprint(len(p))) w.Header().Set("Content-Length", fmt.Sprint(len(p)))
w.WriteHeader(status) w.WriteHeader(status)
if _, err := w.Write(p); err != nil { if _, err := w.Write(p); err != nil {

View file

@ -25,8 +25,8 @@ func TestReturns200IfThereAreNoChecks(t *testing.T) {
} }
} }
// TestReturns500IfThereAreErrorChecks ensures that the result code of the // TestReturns503IfThereAreErrorChecks ensures that the result code of the
// health endpoint is 500 if there are health checks with errors // health endpoint is 503 if there are health checks with errors.
func TestReturns503IfThereAreErrorChecks(t *testing.T) { func TestReturns503IfThereAreErrorChecks(t *testing.T) {
recorder := httptest.NewRecorder() recorder := httptest.NewRecorder()

View file

@ -8,10 +8,13 @@ import (
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
// MediaTypeManifestList specifies the mediaType for manifest lists. const (
const MediaTypeManifestList = "application/vnd.docker.distribution.manifest.list.v2+json" // MediaTypeManifestList specifies the mediaType for manifest lists.
MediaTypeManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
)
// SchemaVersion provides a pre-initialized version structure for this // SchemaVersion provides a pre-initialized version structure for this
// packages version of the manifest. // packages version of the manifest.
@ -20,6 +23,13 @@ var SchemaVersion = manifest.Versioned{
MediaType: MediaTypeManifestList, MediaType: MediaTypeManifestList,
} }
// OCISchemaVersion provides a pre-initialized version structure for this
// packages OCIschema version of the manifest.
var OCISchemaVersion = manifest.Versioned{
SchemaVersion: 2,
MediaType: v1.MediaTypeImageIndex,
}
func init() { func init() {
manifestListFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { manifestListFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
m := new(DeserializedManifestList) m := new(DeserializedManifestList)
@ -28,6 +38,13 @@ func init() {
return nil, distribution.Descriptor{}, err return nil, distribution.Descriptor{}, err
} }
if m.MediaType != MediaTypeManifestList {
err = fmt.Errorf("mediaType in manifest list should be '%s' not '%s'",
MediaTypeManifestList, m.MediaType)
return nil, distribution.Descriptor{}, err
}
dgst := digest.FromBytes(b) dgst := digest.FromBytes(b)
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifestList}, err return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifestList}, err
} }
@ -35,6 +52,28 @@ func init() {
if err != nil { if err != nil {
panic(fmt.Sprintf("Unable to register manifest: %s", err)) panic(fmt.Sprintf("Unable to register manifest: %s", err))
} }
imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
m := new(DeserializedManifestList)
err := m.UnmarshalJSON(b)
if err != nil {
return nil, distribution.Descriptor{}, err
}
if m.MediaType != "" && m.MediaType != v1.MediaTypeImageIndex {
err = fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'",
v1.MediaTypeImageIndex, m.MediaType)
return nil, distribution.Descriptor{}, err
}
dgst := digest.FromBytes(b)
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: v1.MediaTypeImageIndex}, err
}
err = distribution.RegisterManifestSchema(v1.MediaTypeImageIndex, imageIndexFunc)
if err != nil {
panic(fmt.Sprintf("Unable to register OCI Image Index: %s", err))
}
} }
// PlatformSpec specifies a platform where a particular image manifest is // PlatformSpec specifies a platform where a particular image manifest is
@ -81,7 +120,7 @@ type ManifestList struct {
Manifests []ManifestDescriptor `json:"manifests"` Manifests []ManifestDescriptor `json:"manifests"`
} }
// References returnes the distribution descriptors for the referenced image // References returns the distribution descriptors for the referenced image
// manifests. // manifests.
func (m ManifestList) References() []distribution.Descriptor { func (m ManifestList) References() []distribution.Descriptor {
dependencies := make([]distribution.Descriptor, len(m.Manifests)) dependencies := make([]distribution.Descriptor, len(m.Manifests))
@ -105,11 +144,26 @@ type DeserializedManifestList struct {
// DeserializedManifestList which contains the resulting manifest list // DeserializedManifestList which contains the resulting manifest list
// and its JSON representation. // and its JSON representation.
func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedManifestList, error) { func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedManifestList, error) {
m := ManifestList{ var mediaType string
Versioned: SchemaVersion, if len(descriptors) > 0 && descriptors[0].Descriptor.MediaType == v1.MediaTypeImageManifest {
mediaType = v1.MediaTypeImageIndex
} else {
mediaType = MediaTypeManifestList
} }
m.Manifests = make([]ManifestDescriptor, len(descriptors), len(descriptors)) return FromDescriptorsWithMediaType(descriptors, mediaType)
}
// FromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
func FromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType string) (*DeserializedManifestList, error) {
m := ManifestList{
Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: mediaType,
},
}
m.Manifests = make([]ManifestDescriptor, len(descriptors))
copy(m.Manifests, descriptors) copy(m.Manifests, descriptors)
deserialized := DeserializedManifestList{ deserialized := DeserializedManifestList{
@ -123,7 +177,7 @@ func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedManifestLis
// UnmarshalJSON populates a new ManifestList struct from JSON data. // UnmarshalJSON populates a new ManifestList struct from JSON data.
func (m *DeserializedManifestList) UnmarshalJSON(b []byte) error { func (m *DeserializedManifestList) UnmarshalJSON(b []byte) error {
m.canonical = make([]byte, len(b), len(b)) m.canonical = make([]byte, len(b))
// store manifest list in canonical // store manifest list in canonical
copy(m.canonical, b) copy(m.canonical, b)
@ -151,5 +205,12 @@ func (m *DeserializedManifestList) MarshalJSON() ([]byte, error) {
// Payload returns the raw content of the manifest list. The contents can be // Payload returns the raw content of the manifest list. The contents can be
// used to calculate the content identifier. // used to calculate the content identifier.
func (m DeserializedManifestList) Payload() (string, []byte, error) { func (m DeserializedManifestList) Payload() (string, []byte, error) {
return m.MediaType, m.canonical, nil var mediaType string
if m.MediaType == "" {
mediaType = v1.MediaTypeImageIndex
} else {
mediaType = m.MediaType
}
return mediaType, m.canonical, nil
} }

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/docker/distribution" "github.com/docker/distribution"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
var expectedManifestListSerialization = []byte(`{ var expectedManifestListSerialization = []byte(`{
@ -37,7 +38,7 @@ var expectedManifestListSerialization = []byte(`{
] ]
}`) }`)
func TestManifestList(t *testing.T) { func makeTestManifestList(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedManifestList) {
manifestDescriptors := []ManifestDescriptor{ manifestDescriptors := []ManifestDescriptor{
{ {
Descriptor: distribution.Descriptor{ Descriptor: distribution.Descriptor{
@ -64,12 +65,17 @@ func TestManifestList(t *testing.T) {
}, },
} }
deserialized, err := FromDescriptors(manifestDescriptors) deserialized, err := FromDescriptorsWithMediaType(manifestDescriptors, mediaType)
if err != nil { if err != nil {
t.Fatalf("error creating DeserializedManifestList: %v", err) t.Fatalf("error creating DeserializedManifestList: %v", err)
} }
mediaType, canonical, err := deserialized.Payload() return manifestDescriptors, deserialized
}
func TestManifestList(t *testing.T) {
manifestDescriptors, deserialized := makeTestManifestList(t, MediaTypeManifestList)
mediaType, canonical, _ := deserialized.Payload()
if mediaType != MediaTypeManifestList { if mediaType != MediaTypeManifestList {
t.Fatalf("unexpected media type: %s", mediaType) t.Fatalf("unexpected media type: %s", mediaType)
@ -109,3 +115,191 @@ func TestManifestList(t *testing.T) {
} }
} }
} }
// TODO (mikebrow): add annotations on the manifest list (index) and support for
// empty platform structs (move to Platform *Platform `json:"platform,omitempty"`
// from current Platform PlatformSpec `json:"platform"`) in the manifest descriptor.
// Requires changes to docker/distribution/manifest/manifestlist.ManifestList and .ManifestDescriptor
// and associated serialization APIs in manifestlist.go. Or split the OCI index and
// docker manifest list implementations, which would require a lot of refactoring.
var expectedOCIImageIndexSerialization = []byte(`{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 985,
"digest": "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
"platform": {
"architecture": "amd64",
"os": "linux",
"features": [
"sse4"
]
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 985,
"digest": "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
"annotations": {
"platform": "none"
},
"platform": {
"architecture": "",
"os": ""
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2392,
"digest": "sha256:6346340964309634683409684360934680934608934608934608934068934608",
"annotations": {
"what": "for"
},
"platform": {
"architecture": "sun4m",
"os": "sunos"
}
}
]
}`)
func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedManifestList) {
manifestDescriptors := []ManifestDescriptor{
{
Descriptor: distribution.Descriptor{
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
Size: 985,
MediaType: "application/vnd.oci.image.manifest.v1+json",
},
Platform: PlatformSpec{
Architecture: "amd64",
OS: "linux",
Features: []string{"sse4"},
},
},
{
Descriptor: distribution.Descriptor{
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
Size: 985,
MediaType: "application/vnd.oci.image.manifest.v1+json",
Annotations: map[string]string{"platform": "none"},
},
},
{
Descriptor: distribution.Descriptor{
Digest: "sha256:6346340964309634683409684360934680934608934608934608934068934608",
Size: 2392,
MediaType: "application/vnd.oci.image.manifest.v1+json",
Annotations: map[string]string{"what": "for"},
},
Platform: PlatformSpec{
Architecture: "sun4m",
OS: "sunos",
},
},
}
deserialized, err := FromDescriptorsWithMediaType(manifestDescriptors, mediaType)
if err != nil {
t.Fatalf("error creating DeserializedManifestList: %v", err)
}
return manifestDescriptors, deserialized
}
func TestOCIImageIndex(t *testing.T) {
manifestDescriptors, deserialized := makeTestOCIImageIndex(t, v1.MediaTypeImageIndex)
mediaType, canonical, _ := deserialized.Payload()
if mediaType != v1.MediaTypeImageIndex {
t.Fatalf("unexpected media type: %s", mediaType)
}
// Check that the canonical field is the same as json.MarshalIndent
// with these parameters.
p, err := json.MarshalIndent(&deserialized.ManifestList, "", " ")
if err != nil {
t.Fatalf("error marshaling manifest list: %v", err)
}
if !bytes.Equal(p, canonical) {
t.Fatalf("manifest bytes not equal: %q != %q", string(canonical), string(p))
}
// Check that the canonical field has the expected value.
if !bytes.Equal(expectedOCIImageIndexSerialization, canonical) {
t.Fatalf("manifest bytes not equal to expected: %q != %q", string(canonical), string(expectedOCIImageIndexSerialization))
}
var unmarshalled DeserializedManifestList
if err := json.Unmarshal(deserialized.canonical, &unmarshalled); err != nil {
t.Fatalf("error unmarshaling manifest: %v", err)
}
if !reflect.DeepEqual(&unmarshalled, deserialized) {
t.Fatalf("manifests are different after unmarshaling: %v != %v", unmarshalled, *deserialized)
}
references := deserialized.References()
if len(references) != 3 {
t.Fatalf("unexpected number of references: %d", len(references))
}
for i := range references {
if !reflect.DeepEqual(references[i], manifestDescriptors[i].Descriptor) {
t.Fatalf("unexpected value %d returned by References: %v", i, references[i])
}
}
}
func mediaTypeTest(t *testing.T, contentType string, mediaType string, shouldError bool) {
var m *DeserializedManifestList
if contentType == MediaTypeManifestList {
_, m = makeTestManifestList(t, mediaType)
} else {
_, m = makeTestOCIImageIndex(t, mediaType)
}
_, canonical, err := m.Payload()
if err != nil {
t.Fatalf("error getting payload, %v", err)
}
unmarshalled, descriptor, err := distribution.UnmarshalManifest(
contentType,
canonical)
if shouldError {
if err == nil {
t.Fatalf("bad content type should have produced error")
}
} else {
if err != nil {
t.Fatalf("error unmarshaling manifest, %v", err)
}
asManifest := unmarshalled.(*DeserializedManifestList)
if asManifest.MediaType != mediaType {
t.Fatalf("Bad media type '%v' as unmarshalled", asManifest.MediaType)
}
if descriptor.MediaType != contentType {
t.Fatalf("Bad media type '%v' for descriptor", descriptor.MediaType)
}
unmarshalledMediaType, _, _ := unmarshalled.Payload()
if unmarshalledMediaType != contentType {
t.Fatalf("Bad media type '%v' for payload", unmarshalledMediaType)
}
}
}
func TestMediaTypes(t *testing.T) {
mediaTypeTest(t, MediaTypeManifestList, "", true)
mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList, false)
mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList+"XXX", true)
mediaTypeTest(t, v1.MediaTypeImageIndex, "", false)
mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex, false)
mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex+"XXX", true)
}

View file

@ -0,0 +1,107 @@
package ocischema
import (
"context"
"errors"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
// Builder is a type for constructing manifests.
type Builder struct {
// bs is a BlobService used to publish the configuration blob.
bs distribution.BlobService
// configJSON references
configJSON []byte
// layers is a list of layer descriptors that gets built by successive
// calls to AppendReference.
layers []distribution.Descriptor
// Annotations contains arbitrary metadata relating to the targeted content.
annotations map[string]string
// For testing purposes
mediaType string
}
// 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, and annotations.
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder {
mb := &Builder{
bs: bs,
configJSON: make([]byte, len(configJSON)),
annotations: annotations,
mediaType: v1.MediaTypeImageManifest,
}
copy(mb.configJSON, configJSON)
return mb
}
// SetMediaType assigns the passed mediatype or error if the mediatype is not a
// valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json"
func (mb *Builder) SetMediaType(mediaType string) error {
if mediaType != "" && mediaType != v1.MediaTypeImageManifest {
return errors.New("invalid media type for OCI image manifest")
}
mb.mediaType = mediaType
return nil
}
// Build produces a final manifest from the given references.
func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
m := Manifest{
Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: mb.mediaType,
},
Layers: make([]distribution.Descriptor, len(mb.layers)),
Annotations: mb.annotations,
}
copy(m.Layers, mb.layers)
configDigest := digest.FromBytes(mb.configJSON)
var err error
m.Config, err = mb.bs.Stat(ctx, configDigest)
switch err {
case nil:
// Override MediaType, since Put always replaces the specified media
// type with application/octet-stream in the descriptor it returns.
m.Config.MediaType = v1.MediaTypeImageConfig
return FromStruct(m)
case distribution.ErrBlobUnknown:
// nop
default:
return nil, err
}
// Add config to the blob store
m.Config, err = mb.bs.Put(ctx, v1.MediaTypeImageConfig, mb.configJSON)
// Override MediaType, since Put always replaces the specified media
// type with application/octet-stream in the descriptor it returns.
m.Config.MediaType = v1.MediaTypeImageConfig
if err != nil {
return nil, err
}
return FromStruct(m)
}
// AppendReference adds a reference to the current ManifestBuilder.
func (mb *Builder) AppendReference(d distribution.Describable) error {
mb.layers = append(mb.layers, d.Descriptor())
return nil
}
// References returns the current references added to this builder.
func (mb *Builder) References() []distribution.Descriptor {
return mb.layers
}

View file

@ -0,0 +1,173 @@
package ocischema
import (
"context"
"reflect"
"testing"
"github.com/docker/distribution"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
type mockBlobService struct {
descriptors map[digest.Digest]distribution.Descriptor
}
func (bs *mockBlobService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
if descriptor, ok := bs.descriptors[dgst]; ok {
return descriptor, nil
}
return distribution.Descriptor{}, distribution.ErrBlobUnknown
}
func (bs *mockBlobService) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) {
panic("not implemented")
}
func (bs *mockBlobService) Open(ctx context.Context, dgst digest.Digest) (distribution.ReadSeekCloser, error) {
panic("not implemented")
}
func (bs *mockBlobService) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
d := distribution.Descriptor{
Digest: digest.FromBytes(p),
Size: int64(len(p)),
MediaType: "application/octet-stream",
}
bs.descriptors[d.Digest] = d
return d, nil
}
func (bs *mockBlobService) Create(ctx context.Context, options ...distribution.BlobCreateOption) (distribution.BlobWriter, error) {
panic("not implemented")
}
func (bs *mockBlobService) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) {
panic("not implemented")
}
func TestBuilder(t *testing.T) {
imgJSON := []byte(`{
"created": "2015-10-31T22:22:56.015925234Z",
"author": "Alyssa P. Hacker <alyspdev@example.com>",
"architecture": "amd64",
"os": "linux",
"config": {
"User": "alice",
"ExposedPorts": {
"8080/tcp": {}
},
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"FOO=oci_is_a",
"BAR=well_written_spec"
],
"Entrypoint": [
"/bin/my-app-binary"
],
"Cmd": [
"--foreground",
"--config",
"/etc/my-app.d/default.cfg"
],
"Volumes": {
"/var/job-result-data": {},
"/var/log/my-app-logs": {}
},
"WorkingDir": "/home/alice",
"Labels": {
"com.example.project.git.url": "https://example.com/project.git",
"com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b"
}
},
"rootfs": {
"diff_ids": [
"sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
],
"type": "layers"
},
"annotations": {
"hot": "potato"
}
"history": [
{
"created": "2015-10-31T22:22:54.690851953Z",
"created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
},
{
"created": "2015-10-31T22:22:55.613815829Z",
"created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
"empty_layer": true
}
]
}`)
configDigest := digest.FromBytes(imgJSON)
descriptors := []distribution.Descriptor{
{
Digest: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
Size: 5312,
MediaType: v1.MediaTypeImageLayerGzip,
Annotations: map[string]string{"apple": "orange", "lettuce": "wrap"},
},
{
Digest: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa"),
Size: 235231,
MediaType: v1.MediaTypeImageLayerGzip,
},
{
Digest: digest.Digest("sha256:b4ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
Size: 639152,
MediaType: v1.MediaTypeImageLayerGzip,
},
}
annotations := map[string]string{"hot": "potato"}
bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
builder := NewManifestBuilder(bs, imgJSON, annotations)
for _, d := range descriptors {
if err := builder.AppendReference(d); err != nil {
t.Fatalf("AppendReference returned error: %v", err)
}
}
built, err := builder.Build(context.Background())
if err != nil {
t.Fatalf("Build returned error: %v", err)
}
// Check that the config was put in the blob store
_, err = bs.Stat(context.Background(), configDigest)
if err != nil {
t.Fatal("config was not put in the blob store")
}
manifest := built.(*DeserializedManifest).Manifest
if manifest.Annotations["hot"] != "potato" {
t.Fatalf("unexpected annotation in manifest: %s", manifest.Annotations["hot"])
}
if manifest.Versioned.SchemaVersion != 2 {
t.Fatal("SchemaVersion != 2")
}
target := manifest.Target()
if target.Digest != configDigest {
t.Fatalf("unexpected digest in target: %s", target.Digest.String())
}
if target.MediaType != v1.MediaTypeImageConfig {
t.Fatalf("unexpected media type in target: %s", target.MediaType)
}
if target.Size != 1632 {
t.Fatalf("unexpected size in target: %d", target.Size)
}
references := manifest.References()
expected := append([]distribution.Descriptor{manifest.Target()}, descriptors...)
if !reflect.DeepEqual(references, expected) {
t.Fatal("References() does not match the descriptors added")
}
}

View file

@ -0,0 +1,124 @@
package ocischema
import (
"encoding/json"
"errors"
"fmt"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
var (
// SchemaVersion provides a pre-initialized version structure for this
// packages version of the manifest.
SchemaVersion = manifest.Versioned{
SchemaVersion: 2, // historical value here.. does not pertain to OCI or docker version
MediaType: v1.MediaTypeImageManifest,
}
)
func init() {
ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
m := new(DeserializedManifest)
err := m.UnmarshalJSON(b)
if err != nil {
return nil, distribution.Descriptor{}, err
}
dgst := digest.FromBytes(b)
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: v1.MediaTypeImageManifest}, err
}
err := distribution.RegisterManifestSchema(v1.MediaTypeImageManifest, ocischemaFunc)
if err != nil {
panic(fmt.Sprintf("Unable to register manifest: %s", err))
}
}
// Manifest defines a ocischema manifest.
type Manifest struct {
manifest.Versioned
// Config references the image configuration as a blob.
Config distribution.Descriptor `json:"config"`
// Layers lists descriptors for the layers referenced by the
// configuration.
Layers []distribution.Descriptor `json:"layers"`
// Annotations contains arbitrary metadata for the image manifest.
Annotations map[string]string `json:"annotations,omitempty"`
}
// References returns the descriptors of this manifests references.
func (m Manifest) References() []distribution.Descriptor {
references := make([]distribution.Descriptor, 0, 1+len(m.Layers))
references = append(references, m.Config)
references = append(references, m.Layers...)
return references
}
// Target returns the target of this manifest.
func (m Manifest) Target() distribution.Descriptor {
return m.Config
}
// DeserializedManifest wraps Manifest with a copy of the original JSON.
// It satisfies the distribution.Manifest interface.
type DeserializedManifest struct {
Manifest
// canonical is the canonical byte representation of the Manifest.
canonical []byte
}
// FromStruct takes a Manifest structure, marshals it to JSON, and returns a
// DeserializedManifest which contains the manifest and its JSON representation.
func FromStruct(m Manifest) (*DeserializedManifest, error) {
var deserialized DeserializedManifest
deserialized.Manifest = m
var err error
deserialized.canonical, err = json.MarshalIndent(&m, "", " ")
return &deserialized, err
}
// UnmarshalJSON populates a new Manifest struct from JSON data.
func (m *DeserializedManifest) UnmarshalJSON(b []byte) error {
m.canonical = make([]byte, len(b))
// store manifest in canonical
copy(m.canonical, b)
// Unmarshal canonical JSON into Manifest object
var manifest Manifest
if err := json.Unmarshal(m.canonical, &manifest); err != nil {
return err
}
if manifest.MediaType != "" && manifest.MediaType != v1.MediaTypeImageManifest {
return fmt.Errorf("if present, mediaType in manifest should be '%s' not '%s'",
v1.MediaTypeImageManifest, manifest.MediaType)
}
m.Manifest = manifest
return nil
}
// MarshalJSON returns the contents of canonical. If canonical is empty,
// marshals the inner contents.
func (m *DeserializedManifest) MarshalJSON() ([]byte, error) {
if len(m.canonical) > 0 {
return m.canonical, nil
}
return nil, errors.New("JSON representation not initialized in DeserializedManifest")
}
// Payload returns the raw content of the manifest. The contents can be used to
// calculate the content identifier.
func (m DeserializedManifest) Payload() (string, []byte, error) {
return v1.MediaTypeImageManifest, m.canonical, nil
}

View file

@ -0,0 +1,184 @@
package ocischema
import (
"bytes"
"encoding/json"
"reflect"
"testing"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
var expectedManifestSerialization = []byte(`{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 985,
"digest": "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
"annotations": {
"apple": "orange"
}
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 153263,
"digest": "sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b",
"annotations": {
"lettuce": "wrap"
}
}
],
"annotations": {
"hot": "potato"
}
}`)
func makeTestManifest(mediaType string) Manifest {
return Manifest{
Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: mediaType,
},
Config: distribution.Descriptor{
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
Size: 985,
MediaType: v1.MediaTypeImageConfig,
Annotations: map[string]string{"apple": "orange"},
},
Layers: []distribution.Descriptor{
{
Digest: "sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b",
Size: 153263,
MediaType: v1.MediaTypeImageLayerGzip,
Annotations: map[string]string{"lettuce": "wrap"},
},
},
Annotations: map[string]string{"hot": "potato"},
}
}
func TestManifest(t *testing.T) {
manifest := makeTestManifest(v1.MediaTypeImageManifest)
deserialized, err := FromStruct(manifest)
if err != nil {
t.Fatalf("error creating DeserializedManifest: %v", err)
}
mediaType, canonical, _ := deserialized.Payload()
if mediaType != v1.MediaTypeImageManifest {
t.Fatalf("unexpected media type: %s", mediaType)
}
// Check that the canonical field is the same as json.MarshalIndent
// with these parameters.
p, err := json.MarshalIndent(&manifest, "", " ")
if err != nil {
t.Fatalf("error marshaling manifest: %v", err)
}
if !bytes.Equal(p, canonical) {
t.Fatalf("manifest bytes not equal: %q != %q", string(canonical), string(p))
}
// Check that canonical field matches expected value.
if !bytes.Equal(expectedManifestSerialization, canonical) {
t.Fatalf("manifest bytes not equal: %q != %q", string(canonical), string(expectedManifestSerialization))
}
var unmarshalled DeserializedManifest
if err := json.Unmarshal(deserialized.canonical, &unmarshalled); err != nil {
t.Fatalf("error unmarshaling manifest: %v", err)
}
if !reflect.DeepEqual(&unmarshalled, deserialized) {
t.Fatalf("manifests are different after unmarshaling: %v != %v", unmarshalled, *deserialized)
}
if deserialized.Annotations["hot"] != "potato" {
t.Fatalf("unexpected annotation in manifest: %s", deserialized.Annotations["hot"])
}
target := deserialized.Target()
if target.Digest != "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b" {
t.Fatalf("unexpected digest in target: %s", target.Digest.String())
}
if target.MediaType != v1.MediaTypeImageConfig {
t.Fatalf("unexpected media type in target: %s", target.MediaType)
}
if target.Size != 985 {
t.Fatalf("unexpected size in target: %d", target.Size)
}
if target.Annotations["apple"] != "orange" {
t.Fatalf("unexpected annotation in target: %s", target.Annotations["apple"])
}
references := deserialized.References()
if len(references) != 2 {
t.Fatalf("unexpected number of references: %d", len(references))
}
if !reflect.DeepEqual(references[0], target) {
t.Fatalf("first reference should be target: %v != %v", references[0], target)
}
// Test the second reference
if references[1].Digest != "sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b" {
t.Fatalf("unexpected digest in reference: %s", references[0].Digest.String())
}
if references[1].MediaType != v1.MediaTypeImageLayerGzip {
t.Fatalf("unexpected media type in reference: %s", references[0].MediaType)
}
if references[1].Size != 153263 {
t.Fatalf("unexpected size in reference: %d", references[0].Size)
}
if references[1].Annotations["lettuce"] != "wrap" {
t.Fatalf("unexpected annotation in reference: %s", references[1].Annotations["lettuce"])
}
}
func mediaTypeTest(t *testing.T, mediaType string, shouldError bool) {
manifest := makeTestManifest(mediaType)
deserialized, err := FromStruct(manifest)
if err != nil {
t.Fatalf("error creating DeserializedManifest: %v", err)
}
unmarshalled, descriptor, err := distribution.UnmarshalManifest(
v1.MediaTypeImageManifest,
deserialized.canonical)
if shouldError {
if err == nil {
t.Fatalf("bad content type should have produced error")
}
} else {
if err != nil {
t.Fatalf("error unmarshaling manifest, %v", err)
}
asManifest := unmarshalled.(*DeserializedManifest)
if asManifest.MediaType != mediaType {
t.Fatalf("Bad media type '%v' as unmarshalled", asManifest.MediaType)
}
if descriptor.MediaType != v1.MediaTypeImageManifest {
t.Fatalf("Bad media type '%v' for descriptor", descriptor.MediaType)
}
unmarshalledMediaType, _, _ := unmarshalled.Payload()
if unmarshalledMediaType != v1.MediaTypeImageManifest {
t.Fatalf("Bad media type '%v' for payload", unmarshalledMediaType)
}
}
}
func TestMediaTypes(t *testing.T) {
mediaTypeTest(t, "", false)
mediaTypeTest(t, v1.MediaTypeImageManifest, false)
mediaTypeTest(t, v1.MediaTypeImageManifest+"XXX", true)
}

View file

@ -1,6 +1,7 @@
package schema1 package schema1
import ( import (
"context"
"crypto/sha512" "crypto/sha512"
"encoding/json" "encoding/json"
"errors" "errors"
@ -8,7 +9,6 @@ import (
"time" "time"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/context"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/libtrust" "github.com/docker/libtrust"

View file

@ -3,12 +3,13 @@ package schema1
import ( import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"context"
"io" "io"
"reflect" "reflect"
"testing" "testing"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/context" dcontext "github.com/docker/distribution/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
@ -58,7 +59,7 @@ func TestEmptyTar(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("NewReader returned error: %v", err) t.Fatalf("NewReader returned error: %v", err)
} }
n, err := gzipReader.Read(decompressed[:]) n, _ := gzipReader.Read(decompressed[:])
if n != 1024 { if n != 1024 {
t.Fatalf("read returned %d bytes; expected 1024", n) t.Fatalf("read returned %d bytes; expected 1024", n)
} }
@ -214,13 +215,13 @@ func TestConfigBuilder(t *testing.T) {
} }
} }
signed, err := builder.Build(context.Background()) signed, err := builder.Build(dcontext.Background())
if err != nil { if err != nil {
t.Fatalf("Build returned error: %v", err) t.Fatalf("Build returned error: %v", err)
} }
// Check that the gzipped empty layer tar was put in the blob store // Check that the gzipped empty layer tar was put in the blob store
_, err = bs.Stat(context.Background(), digestSHA256GzippedEmptyTar) _, err = bs.Stat(dcontext.Background(), digestSHA256GzippedEmptyTar)
if err != nil { if err != nil {
t.Fatal("gzipped empty tar was not put in the blob store") t.Fatal("gzipped empty tar was not put in the blob store")
} }

View file

@ -108,7 +108,7 @@ type SignedManifest struct {
// UnmarshalJSON populates a new SignedManifest struct from JSON data. // UnmarshalJSON populates a new SignedManifest struct from JSON data.
func (sm *SignedManifest) UnmarshalJSON(b []byte) error { func (sm *SignedManifest) UnmarshalJSON(b []byte) error {
sm.all = make([]byte, len(b), len(b)) sm.all = make([]byte, len(b))
// store manifest and signatures in all // store manifest and signatures in all
copy(sm.all, b) copy(sm.all, b)
@ -124,7 +124,7 @@ func (sm *SignedManifest) UnmarshalJSON(b []byte) error {
} }
// sm.Canonical stores the canonical manifest JSON // sm.Canonical stores the canonical manifest JSON
sm.Canonical = make([]byte, len(bytes), len(bytes)) sm.Canonical = make([]byte, len(bytes))
copy(sm.Canonical, bytes) copy(sm.Canonical, bytes)
// Unmarshal canonical JSON into Manifest object // Unmarshal canonical JSON into Manifest object
@ -138,7 +138,7 @@ func (sm *SignedManifest) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// References returnes the descriptors of this manifests references // References returns the descriptors of this manifests references
func (sm SignedManifest) References() []distribution.Descriptor { func (sm SignedManifest) References() []distribution.Descriptor {
dependencies := make([]distribution.Descriptor, len(sm.FSLayers)) dependencies := make([]distribution.Descriptor, len(sm.FSLayers))
for i, fsLayer := range sm.FSLayers { for i, fsLayer := range sm.FSLayers {

View file

@ -1,11 +1,11 @@
package schema1 package schema1
import ( import (
"context"
"errors"
"fmt" "fmt"
"errors"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/context"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/libtrust" "github.com/docker/libtrust"
@ -58,7 +58,7 @@ func (mb *referenceManifestBuilder) Build(ctx context.Context) (distribution.Man
func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error { func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error {
r, ok := d.(Reference) r, ok := d.(Reference)
if !ok { if !ok {
return fmt.Errorf("Unable to add non-reference type to v1 builder") return fmt.Errorf("unable to add non-reference type to v1 builder")
} }
// Entries need to be prepended // Entries need to be prepended

View file

@ -3,8 +3,8 @@ package schema1
import ( import (
"crypto/x509" "crypto/x509"
"github.com/Sirupsen/logrus"
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/sirupsen/logrus"
) )
// Verify verifies the signature of the signed manifest returning the public // Verify verifies the signature of the signed manifest returning the public

View file

@ -1,8 +1,9 @@
package schema2 package schema2
import ( import (
"context"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/context"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )

View file

@ -1,11 +1,11 @@
package schema2 package schema2
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/context"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )

View file

@ -71,7 +71,7 @@ type Manifest struct {
Layers []distribution.Descriptor `json:"layers"` Layers []distribution.Descriptor `json:"layers"`
} }
// References returnes the descriptors of this manifests references. // References returns the descriptors of this manifests references.
func (m Manifest) References() []distribution.Descriptor { func (m Manifest) References() []distribution.Descriptor {
references := make([]distribution.Descriptor, 0, 1+len(m.Layers)) references := make([]distribution.Descriptor, 0, 1+len(m.Layers))
references = append(references, m.Config) references = append(references, m.Config)
@ -79,7 +79,7 @@ func (m Manifest) References() []distribution.Descriptor {
return references return references
} }
// Target returns the target of this signed manifest. // Target returns the target of this manifest.
func (m Manifest) Target() distribution.Descriptor { func (m Manifest) Target() distribution.Descriptor {
return m.Config return m.Config
} }
@ -106,7 +106,7 @@ func FromStruct(m Manifest) (*DeserializedManifest, error) {
// UnmarshalJSON populates a new Manifest struct from JSON data. // UnmarshalJSON populates a new Manifest struct from JSON data.
func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { func (m *DeserializedManifest) UnmarshalJSON(b []byte) error {
m.canonical = make([]byte, len(b), len(b)) m.canonical = make([]byte, len(b))
// store manifest in canonical // store manifest in canonical
copy(m.canonical, b) copy(m.canonical, b)
@ -116,6 +116,12 @@ func (m *DeserializedManifest) UnmarshalJSON(b []byte) error {
return err return err
} }
if manifest.MediaType != MediaTypeManifest {
return fmt.Errorf("mediaType in manifest should be '%s' not '%s'",
MediaTypeManifest, manifest.MediaType)
}
m.Manifest = manifest m.Manifest = manifest
return nil return nil

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/manifest"
) )
var expectedManifestSerialization = []byte(`{ var expectedManifestSerialization = []byte(`{
@ -26,9 +27,12 @@ var expectedManifestSerialization = []byte(`{
] ]
}`) }`)
func TestManifest(t *testing.T) { func makeTestManifest(mediaType string) Manifest {
manifest := Manifest{ return Manifest{
Versioned: SchemaVersion, Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: mediaType,
},
Config: distribution.Descriptor{ Config: distribution.Descriptor{
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b", Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
Size: 985, Size: 985,
@ -42,13 +46,17 @@ func TestManifest(t *testing.T) {
}, },
}, },
} }
}
func TestManifest(t *testing.T) {
manifest := makeTestManifest(MediaTypeManifest)
deserialized, err := FromStruct(manifest) deserialized, err := FromStruct(manifest)
if err != nil { if err != nil {
t.Fatalf("error creating DeserializedManifest: %v", err) t.Fatalf("error creating DeserializedManifest: %v", err)
} }
mediaType, canonical, err := deserialized.Payload() mediaType, canonical, _ := deserialized.Payload()
if mediaType != MediaTypeManifest { if mediaType != MediaTypeManifest {
t.Fatalf("unexpected media type: %s", mediaType) t.Fatalf("unexpected media type: %s", mediaType)
@ -109,3 +117,46 @@ func TestManifest(t *testing.T) {
t.Fatalf("unexpected size in reference: %d", references[0].Size) t.Fatalf("unexpected size in reference: %d", references[0].Size)
} }
} }
func mediaTypeTest(t *testing.T, mediaType string, shouldError bool) {
manifest := makeTestManifest(mediaType)
deserialized, err := FromStruct(manifest)
if err != nil {
t.Fatalf("error creating DeserializedManifest: %v", err)
}
unmarshalled, descriptor, err := distribution.UnmarshalManifest(
MediaTypeManifest,
deserialized.canonical)
if shouldError {
if err == nil {
t.Fatalf("bad content type should have produced error")
}
} else {
if err != nil {
t.Fatalf("error unmarshaling manifest, %v", err)
}
asManifest := unmarshalled.(*DeserializedManifest)
if asManifest.MediaType != mediaType {
t.Fatalf("Bad media type '%v' as unmarshalled", asManifest.MediaType)
}
if descriptor.MediaType != MediaTypeManifest {
t.Fatalf("Bad media type '%v' for descriptor", descriptor.MediaType)
}
unmarshalledMediaType, _, _ := unmarshalled.Payload()
if unmarshalledMediaType != MediaTypeManifest {
t.Fatalf("Bad media type '%v' for payload", unmarshalledMediaType)
}
}
}
func TestMediaTypes(t *testing.T) {
mediaTypeTest(t, "", true)
mediaTypeTest(t, MediaTypeManifest, false)
mediaTypeTest(t, MediaTypeManifest+"XXX", true)
}

View file

@ -1,10 +1,10 @@
package distribution package distribution
import ( import (
"context"
"fmt" "fmt"
"mime" "mime"
"github.com/docker/distribution/context"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
@ -87,7 +87,7 @@ func ManifestMediaTypes() (mediaTypes []string) {
// UnmarshalFunc implements manifest unmarshalling a given MediaType // UnmarshalFunc implements manifest unmarshalling a given MediaType
type UnmarshalFunc func([]byte) (Manifest, Descriptor, error) type UnmarshalFunc func([]byte) (Manifest, Descriptor, error)
var mappings = make(map[string]UnmarshalFunc, 0) var mappings = make(map[string]UnmarshalFunc)
// UnmarshalManifest looks up manifest unmarshal functions based on // UnmarshalManifest looks up manifest unmarshal functions based on
// MediaType // MediaType

16
metrics/prometheus.go Normal file
View file

@ -0,0 +1,16 @@
package metrics
import "github.com/docker/go-metrics"
const (
// NamespacePrefix is the namespace of prometheus metrics
NamespacePrefix = "registry"
)
var (
// StorageNamespace is the prometheus namespace of blob/cache related operations
StorageNamespace = metrics.NewNamespace(NamespacePrefix, "storage", nil)
// NotificationsNamespace is the prometheus namespace of notification related metrics
NotificationsNamespace = metrics.NewNamespace(NamespacePrefix, "notifications", nil)
)

View file

@ -8,15 +8,17 @@ import (
"github.com/docker/distribution/context" "github.com/docker/distribution/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/distribution/uuid" "github.com/docker/distribution/uuid"
events "github.com/docker/go-events"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
type bridge struct { type bridge struct {
ub URLBuilder ub URLBuilder
includeReferences bool
actor ActorRecord actor ActorRecord
source SourceRecord source SourceRecord
request RequestRecord request RequestRecord
sink Sink sink events.Sink
} }
var _ Listener = &bridge{} var _ Listener = &bridge{}
@ -31,9 +33,10 @@ type URLBuilder interface {
// using the actor and source. Any urls populated in the events created by // using the actor and source. Any urls populated in the events created by
// this bridge will be created using the URLBuilder. // this bridge will be created using the URLBuilder.
// TODO(stevvooe): Update this to simply take a context.Context object. // TODO(stevvooe): Update this to simply take a context.Context object.
func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request RequestRecord, sink Sink) Listener { func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request RequestRecord, sink events.Sink, includeReferences bool) Listener {
return &bridge{ return &bridge{
ub: ub, ub: ub,
includeReferences: includeReferences,
actor: actor, actor: actor,
source: source, source: source,
request: request, request: request,
@ -108,13 +111,19 @@ func (b *bridge) BlobDeleted(repo reference.Named, dgst digest.Digest) error {
return b.createBlobDeleteEventAndWrite(EventActionDelete, repo, dgst) return b.createBlobDeleteEventAndWrite(EventActionDelete, repo, dgst)
} }
func (b *bridge) createManifestEventAndWrite(action string, repo reference.Named, sm distribution.Manifest) error { func (b *bridge) TagDeleted(repo reference.Named, tag string) error {
manifestEvent, err := b.createManifestEvent(action, repo, sm) event := b.createEvent(EventActionDelete)
if err != nil { event.Target.Repository = repo.Name()
return err event.Target.Tag = tag
}
return b.sink.Write(*manifestEvent) return b.sink.Write(*event)
}
func (b *bridge) RepoDeleted(repo reference.Named) error {
event := b.createEvent(EventActionDelete)
event.Target.Repository = repo.Name()
return b.sink.Write(*event)
} }
func (b *bridge) createManifestDeleteEventAndWrite(action string, repo reference.Named, dgst digest.Digest) error { func (b *bridge) createManifestDeleteEventAndWrite(action string, repo reference.Named, dgst digest.Digest) error {
@ -135,7 +144,7 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis
} }
// Ensure we have the canonical manifest descriptor here // Ensure we have the canonical manifest descriptor here
_, desc, err := distribution.UnmarshalManifest(mt, p) manifest, desc, err := distribution.UnmarshalManifest(mt, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -144,6 +153,9 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis
event.Target.Length = desc.Size event.Target.Length = desc.Size
event.Target.Size = desc.Size event.Target.Size = desc.Size
event.Target.Digest = desc.Digest event.Target.Digest = desc.Digest
if b.includeReferences {
event.Target.References = append(event.Target.References, manifest.References()...)
}
ref, err := reference.WithDigest(repo, event.Target.Digest) ref, err := reference.WithDigest(repo, event.Target.Digest)
if err != nil { if err != nil {

Some files were not shown because too many files have changed in this diff Show more