forked from mirrors/docker-distribution
Compare commits
25 Commits
master
...
release/2.
Author | SHA1 | Date |
---|---|---|
Derek McGowan | 70e0022e42 | |
Sebastiaan van Stijn | 48eeac88e9 | |
Derek McGowan | a45a401e97 | |
Thomas Berger | e2f006ac2b | |
Eohyung Lee | 0a1e4a57e2 | |
Derek McGowan | bdf503a444 | |
Derek McGowan | be75da0ef2 | |
Vishesh Jindal | afa91463d6 | |
Sebastiaan van Stijn | fad36ed1a1 | |
Derek McGowan | cfd1309845 | |
Derek McGowan | a85caead04 | |
Adrian Plata | f999f540d3 | |
Vishesh Jindal | c636ed788a | |
Derek McGowan | 5883e2d935 | |
Derek McGowan | 269d18d9a8 | |
Adrian Plata | a3c027e626 | |
Derek McGowan | 2461543d98 | |
Derek McGowan | 5b98226afe | |
Derek McGowan | 2eab12df9b | |
Derek McGowan | 445ef068dd | |
Ryan Abrams | cbc30be414 | |
Ryan Abrams | bf74e4f91d | |
Ryan Abrams | 62994fdd12 | |
Derek McGowan | e702d95cfd | |
David Wu | caf43bbcc2 |
|
@ -5,7 +5,6 @@
|
|||
"EnableGC": true,
|
||||
"Enable": [
|
||||
"structcheck",
|
||||
"staticcheck",
|
||||
"unconvert",
|
||||
|
||||
"gofmt",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM golang:1.11-alpine AS build
|
||||
|
||||
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
|
||||
|
|
|
@ -703,15 +703,20 @@ interpretation of the options.
|
|||
| `baseurl` | yes | The `SCHEME://HOST[/PATH]` at which Cloudfront is served. |
|
||||
| `privatekey` | yes | The private key for Cloudfront, 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).|
|
||||
|`ipfilteredby`|no | A string with the following value `none|aws|awsregion`. |
|
||||
|`awsregion`|no | A comma separated string of AWS regions, only available when `ipfilteredby` is `awsregion`. For example, `us-east-1, us-west-2`|
|
||||
|`updatefrenquency`|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`|
|
||||
Then value of ipfilteredby:
|
||||
`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`
|
||||
| `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` |
|
||||
| `updatefrenquency` | 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`. |
|
||||
|
||||
### `redirect`
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
title: "HTTP API V2"
|
||||
description: "Specification for the Registry API."
|
||||
keywords: registry, on-prem, images, tags, repository, distribution, api, advanced
|
||||
redirect_from:
|
||||
- /reference/api/registry_api/
|
||||
---
|
||||
|
||||
# Docker Registry HTTP API V2
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
title: "HTTP API V2"
|
||||
description: "Specification for the Registry API."
|
||||
keywords: registry, on-prem, images, tags, repository, distribution, api, advanced
|
||||
redirect_from:
|
||||
- /reference/api/registry_api/
|
||||
---
|
||||
|
||||
# Docker Registry HTTP API V2
|
||||
|
|
|
@ -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`.
|
|
@ -56,6 +56,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
|
|||
return named, nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func ParseDockerRef(ref string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(NamedTagged); ok {
|
||||
if canonical, ok := named.(Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return TagNameOnly(named), nil
|
||||
}
|
||||
|
||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||
// If no valid domain is found, the default domain is used. Repository name
|
||||
// needs to be already validated before.
|
||||
|
|
|
@ -623,3 +623,83 @@ func TestMatch(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDockerRef(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "nothing",
|
||||
input: "busybox",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "tag only",
|
||||
input: "busybox:latest",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "digest only",
|
||||
input: "busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
expected: "docker.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
},
|
||||
{
|
||||
name: "path only",
|
||||
input: "library/busybox",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "hostname only",
|
||||
input: "docker.io/busybox",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "no tag",
|
||||
input: "docker.io/library/busybox",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "no path",
|
||||
input: "docker.io/busybox:latest",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "no hostname",
|
||||
input: "library/busybox:latest",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "full reference with tag",
|
||||
input: "docker.io/library/busybox:latest",
|
||||
expected: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "gcr reference without tag",
|
||||
input: "gcr.io/library/busybox",
|
||||
expected: "gcr.io/library/busybox:latest",
|
||||
},
|
||||
{
|
||||
name: "both tag and digest",
|
||||
input: "gcr.io/library/busybox:latest@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
expected: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
},
|
||||
}
|
||||
for _, test := range testcases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
normalized, err := ParseDockerRef(test.input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
output := normalized.String()
|
||||
if output != test.expected {
|
||||
t.Fatalf("expected %q to be parsed as %v, got %v", test.input, test.expected, output)
|
||||
}
|
||||
_, err = Parse(output)
|
||||
if err != nil {
|
||||
t.Fatalf("%q should be a valid reference, but got an error: %v", output, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,11 +162,14 @@ func checkOptions(options map[string]interface{}) (tokenAccessOptions, error) {
|
|||
|
||||
opts.realm, opts.issuer, opts.service, opts.rootCertBundle = vals[0], vals[1], vals[2], vals[3]
|
||||
|
||||
autoRedirect, ok := options["autoredirect"].(bool)
|
||||
if !ok {
|
||||
return opts, fmt.Errorf("token auth requires a valid option bool: autoredirect")
|
||||
autoRedirectVal, ok := options["autoredirect"]
|
||||
if ok {
|
||||
autoRedirect, ok := autoRedirectVal.(bool)
|
||||
if !ok {
|
||||
return opts, fmt.Errorf("token auth requires a valid option bool: autoredirect")
|
||||
}
|
||||
opts.autoRedirect = autoRedirect
|
||||
}
|
||||
opts.autoRedirect = autoRedirect
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
|
|
@ -138,27 +138,33 @@ func newCloudFrontStorageMiddleware(storageDriver storagedriver.StorageDriver, o
|
|||
|
||||
// parse ipfilteredby
|
||||
var awsIPs *awsIPs
|
||||
if ipFilteredBy := options["ipfilteredby"].(string); ok {
|
||||
switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) {
|
||||
case "", "none":
|
||||
awsIPs = nil
|
||||
case "aws":
|
||||
newAWSIPs(ipRangesURL, updateFrequency, nil)
|
||||
case "awsregion":
|
||||
var awsRegion []string
|
||||
if regions, ok := options["awsregion"].(string); ok {
|
||||
for _, awsRegions := range strings.Split(regions, ",") {
|
||||
awsRegion = append(awsRegion, strings.ToLower(strings.TrimSpace(awsRegions)))
|
||||
if i, ok := options["ipfilteredby"]; ok {
|
||||
if ipFilteredBy, ok := i.(string); ok {
|
||||
switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) {
|
||||
case "", "none":
|
||||
awsIPs = nil
|
||||
case "aws":
|
||||
awsIPs = newAWSIPs(ipRangesURL, updateFrequency, nil)
|
||||
case "awsregion":
|
||||
var awsRegion []string
|
||||
if i, ok := options["awsregion"]; ok {
|
||||
if regions, ok := i.(string); ok {
|
||||
for _, awsRegions := range strings.Split(regions, ",") {
|
||||
awsRegion = append(awsRegion, strings.ToLower(strings.TrimSpace(awsRegions)))
|
||||
}
|
||||
awsIPs = newAWSIPs(ipRangesURL, updateFrequency, awsRegion)
|
||||
} else {
|
||||
return nil, fmt.Errorf("awsRegion must be a comma separated string of valid aws regions")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("awsRegion is not defined")
|
||||
}
|
||||
awsIPs = newAWSIPs(ipRangesURL, updateFrequency, awsRegion)
|
||||
} else {
|
||||
return nil, fmt.Errorf("awsRegion must be a comma separated string of valid aws regions")
|
||||
default:
|
||||
return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion")
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion")
|
||||
} else {
|
||||
return nil, fmt.Errorf("ipfilteredby only allows a string with the following value: none|aws|awsregion")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("ipfilteredby only allows a string with the following value: none|aws|awsregion")
|
||||
}
|
||||
|
||||
return &cloudFrontStorageMiddleware{
|
||||
|
|
|
@ -970,8 +970,19 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, path, pre
|
|||
defer done("s3aws.ListObjectsV2Pages(%s)", path)
|
||||
listObjectErr := d.S3.ListObjectsV2PagesWithContext(ctx, listObjectsInput, func(objects *s3.ListObjectsV2Output, lastPage bool) bool {
|
||||
|
||||
*objectCount += *objects.KeyCount
|
||||
walkInfos := make([]walkInfoContainer, 0, *objects.KeyCount)
|
||||
var count int64
|
||||
// KeyCount was introduced with version 2 of the GET Bucket operation in S3.
|
||||
// Some S3 implementations don't support V2 now, so we fall back to manual
|
||||
// calculation of the key count if required
|
||||
if objects.KeyCount != nil {
|
||||
count = *objects.KeyCount
|
||||
*objectCount += *objects.KeyCount
|
||||
} else {
|
||||
count = int64(len(objects.Contents) + len(objects.CommonPrefixes))
|
||||
*objectCount += count
|
||||
}
|
||||
|
||||
walkInfos := make([]walkInfoContainer, 0, count)
|
||||
|
||||
for _, dir := range objects.CommonPrefixes {
|
||||
commonPrefix := *dir.Prefix
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# commit to be tagged for new release
|
||||
commit = "HEAD"
|
||||
|
||||
project_name = "registry"
|
||||
github_repo = "docker/distribution"
|
||||
|
||||
# previous release
|
||||
previous = "v2.7.0"
|
||||
|
||||
pre_release = false
|
||||
|
||||
preface = """\
|
||||
The first patch release of 2.7 addresses an upgrade issue when
|
||||
using configurations from pre-2.7 registries. When upgrading from
|
||||
2.6 or earlier use this patch release or newer to avoid a failure
|
||||
on startup from not updating the configuration file.
|
||||
|
||||
- Set default for new `autoredirect` option
|
||||
- GCS driver is now included in binary builds using Dockerfile"""
|
||||
|
||||
# notable prs to include in the release notes, 1234 is the pr number
|
||||
[notes]
|
||||
|
||||
[breaking]
|
||||
|
||||
[rename_deps]
|
|
@ -0,0 +1,6 @@
|
|||
module github.com/aws/aws-sdk-go
|
||||
|
||||
require (
|
||||
github.com/go-ini/ini v1.25.4
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
module "gopkg.in/yaml.v2"
|
||||
|
||||
require (
|
||||
"gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
|
||||
)
|
|
@ -8,7 +8,7 @@ var Package = "github.com/docker/distribution"
|
|||
// the latest release tag by hand, always suffixed by "+unknown". During
|
||||
// build, it will be replaced by the actual version. The value here will be
|
||||
// used if the registry is run after a go get based install.
|
||||
var Version = "v2.7.0+unknown"
|
||||
var Version = "v2.7.1+unknown"
|
||||
|
||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||
// the program at linking time.
|
||||
|
|
Loading…
Reference in New Issue