bump up github.com/docker/distribution to v2.8.0+incompatible (#16435)

Signed-off-by: yminer <yminer@vmmware.com>

rgoo mod vendor

Signed-off-by: yminer <yminer@vmmware.com>

Co-authored-by: yminer <yminer@vmmware.com>
This commit is contained in:
MinerYang 2022-03-01 17:29:02 +08:00 committed by GitHub
parent 74d2670616
commit 848efd067d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 332 additions and 285 deletions

View File

@ -15,7 +15,7 @@ require (
github.com/cenkalti/backoff/v4 v4.1.1 github.com/cenkalti/backoff/v4 v4.1.1
github.com/coreos/go-oidc/v3 v3.0.0 github.com/coreos/go-oidc/v3 v3.0.0
github.com/dghubble/sling v1.1.0 github.com/dghubble/sling v1.1.0
github.com/docker/distribution v2.7.1+incompatible github.com/docker/distribution v2.8.0+incompatible
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/go-asn1-ber/asn1-ber v1.5.1 github.com/go-asn1-ber/asn1-ber v1.5.1

View File

@ -432,6 +432,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k=
github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=

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

@ -1,16 +0,0 @@
{
"Vendor": true,
"Deadline": "2m",
"Sort": ["linter", "severity", "path", "line"],
"EnableGC": true,
"Enable": [
"structcheck",
"staticcheck",
"unconvert",
"gofmt",
"goimports",
"golint",
"vet"
]
}

View File

@ -30,3 +30,17 @@ Helen Xie <xieyulin821@harmonycloud.cn> Helen-xie <xieyulin821@harmonycloud.cn>
Mike Brown <brownwm@us.ibm.com> Mike Brown <mikebrow@users.noreply.github.com> 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> Manish Tomar <manish.tomar@docker.com> Manish Tomar <manishtomar@users.noreply.github.com>
Sakeven Jiang <jc5930@sina.cn> sakeven <jc5930@sina.cn> Sakeven Jiang <jc5930@sina.cn> sakeven <jc5930@sina.cn>
Milos Gajdos <milosgajdos83@gmail.com> Milos Gajdos <milosgajdos@users.noreply.github.com>
Derek McGowan <derek@mcgstyle.net> Derek McGowa <dmcgowan@users.noreply.github.com>
Adrian Plata <adrian.plata@docker.com> Adrian Plata <@users.noreply.github.com>
Sebastiaan van Stijn <github@gone.nl> Sebastiaan van Stijn <thaJeztah@users.noreply.github.com>
Vishesh Jindal <vishesh92@gmail.com> Vishesh Jindal <vishesh92@users.noreply.github.com>
Wang Yan <wangyan@vmware.com> Wang Yan <wy65701436@users.noreply.github.com>
Chris Patterson <chrispat@github.com> Chris Patterson <chrispat@users.noreply.github.com>
Eohyung Lee <liquidnuker@gmail.com> Eohyung Lee <leoh0@users.noreply.github.com>
João Pereira <484633+joaodrp@users.noreply.github.com>
Smasherr <soundcracker@gmail.com> Smasherr <Smasherr@users.noreply.github.com>
Thomas Berger <loki@lokis-chaos.de> Thomas Berger <tbe@users.noreply.github.com>
Samuel Karp <skarp@amazon.com> Samuel Karp <samuelkarp@users.noreply.github.com>
Justin Cormack <justin.cormack@docker.com>
sayboras <sayboras@yahoo.com>

View File

@ -1,51 +0,0 @@
dist: trusty
sudo: required
# setup travis so that we can run containers for integration tests
services:
- docker
language: go
go:
- "1.11.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:
- 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 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

View File

@ -1,22 +1,45 @@
FROM golang:1.11-alpine AS build # syntax=docker/dockerfile:1.3
ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution ARG GO_VERSION=1.16
ENV BUILDTAGS include_oss include_gcs ARG GORELEASER_XX_VERSION=1.2.5
ARG GOOS=linux FROM --platform=$BUILDPLATFORM crazymax/goreleaser-xx:${GORELEASER_XX_VERSION} AS goreleaser-xx
ARG GOARCH=amd64 FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base
ARG GOARM=6 COPY --from=goreleaser-xx / /
RUN apk add --no-cache file git
WORKDIR /go/src/github.com/docker/distribution
RUN set -ex \ FROM base AS build
&& apk add --no-cache make git file ENV GO111MODULE=auto
ENV CGO_ENABLED=0
ARG TARGETPLATFORM
ARG PKG="github.com/distribution/distribution"
ARG BUILDTAGS="include_oss include_gcs"
RUN --mount=type=bind,rw \
--mount=type=cache,target=/root/.cache/go-build \
--mount=target=/go/pkg/mod,type=cache \
goreleaser-xx --debug \
--name="registry" \
--dist="/out" \
--main="./cmd/registry" \
--flags="-v" \
--ldflags="-s -w -X '$PKG/version.Version={{.Version}}' -X '$PKG/version.Revision={{.Commit}}' -X '$PKG/version.Package=$PKG'" \
--tags="$BUILDTAGS" \
--files="LICENSE" \
--files="README.md"
WORKDIR $DISTRIBUTION_DIR FROM scratch AS artifacts
COPY . $DISTRIBUTION_DIR COPY --from=build /out/*.tar.gz /
RUN CGO_ENABLED=0 make PREFIX=/go clean binaries && file ./bin/registry | grep "statically linked" COPY --from=build /out/*.zip /
COPY --from=build /out/*.sha256 /
FROM alpine FROM scratch AS binary
COPY --from=build /usr/local/bin/registry* /
FROM alpine:3.14
RUN apk add --no-cache ca-certificates
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 COPY --from=build /usr/local/bin/registry /bin/registry
VOLUME ["/var/lib/registry"] VOLUME ["/var/lib/registry"]
EXPOSE 5000 EXPOSE 5000
ENTRYPOINT ["registry"] ENTRYPOINT ["registry"]

View File

@ -50,7 +50,7 @@ version/version.go:
check: ## run all linters (TODO: enable "unused", "varcheck", "ineffassign", "unconvert", "staticheck", "goimports", "structcheck") check: ## run all linters (TODO: enable "unused", "varcheck", "ineffassign", "unconvert", "staticheck", "goimports", "structcheck")
@echo "$(WHALE) $@" @echo "$(WHALE) $@"
gometalinter --config .gometalinter.json ./... golangci-lint run
test: ## run tests, except integration test with test.short test: ## run tests, except integration test with test.short
@echo "$(WHALE) $@" @echo "$(WHALE) $@"

View File

@ -10,7 +10,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
var ( var (

View File

@ -108,6 +108,12 @@ 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"`
// Specifies a list of cipher suites allowed
CipherSuites []string `yaml:"ciphersuites,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
@ -388,7 +394,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)
@ -463,7 +469,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
@ -665,11 +671,11 @@ func Parse(rd io.Reader) (*Configuration, error) {
v0_1.Loglevel = Loglevel("") v0_1.Loglevel = Loglevel("")
} }
if v0_1.Storage.Type() == "" { if v0_1.Storage.Type() == "" {
return nil, errors.New("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

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

View File

@ -0,0 +1,51 @@
group "default" {
targets = ["image-local"]
}
// Special target: https://github.com/docker/metadata-action#bake-definition
target "docker-metadata-action" {
tags = ["registry:local"]
}
target "binary" {
target = "binary"
output = ["./bin"]
}
target "artifact" {
target = "artifacts"
output = ["./bin"]
}
target "artifact-all" {
inherits = ["artifact"]
platforms = [
"linux/amd64",
"linux/arm/v6",
"linux/arm/v7",
"linux/arm64",
"linux/ppc64le",
"linux/s390x"
]
}
target "image" {
inherits = ["docker-metadata-action"]
}
target "image-local" {
inherits = ["image"]
output = ["type=docker"]
}
target "image-all" {
inherits = ["image"]
platforms = [
"linux/amd64",
"linux/arm/v6",
"linux/arm/v7",
"linux/arm64",
"linux/ppc64le",
"linux/s390x"
]
}

View File

@ -8,7 +8,7 @@ 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"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
const ( const (
@ -54,6 +54,9 @@ func init() {
} }
imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
if err := validateIndex(b); err != nil {
return nil, distribution.Descriptor{}, err
}
m := new(DeserializedManifestList) m := new(DeserializedManifestList)
err := m.UnmarshalJSON(b) err := m.UnmarshalJSON(b)
if err != nil { if err != nil {
@ -163,7 +166,7 @@ func FromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType st
}, },
} }
m.Manifests = make([]ManifestDescriptor, len(descriptors), len(descriptors)) m.Manifests = make([]ManifestDescriptor, len(descriptors))
copy(m.Manifests, descriptors) copy(m.Manifests, descriptors)
deserialized := DeserializedManifestList{ deserialized := DeserializedManifestList{
@ -177,7 +180,7 @@ func FromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType st
// 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)
@ -214,3 +217,23 @@ func (m DeserializedManifestList) Payload() (string, []byte, error) {
return mediaType, m.canonical, nil return mediaType, m.canonical, nil
} }
// unknownDocument represents a manifest, manifest list, or index that has not
// yet been validated
type unknownDocument struct {
Config interface{} `json:"config,omitempty"`
Layers interface{} `json:"layers,omitempty"`
}
// validateIndex returns an error if the byte slice is invalid JSON or if it
// contains fields that belong to a manifest
func validateIndex(b []byte) error {
var doc unknownDocument
if err := json.Unmarshal(b, &doc); err != nil {
return err
}
if doc.Config != nil || doc.Layers != nil {
return errors.New("index: expected index but found manifest")
}
return nil
}

View File

@ -7,7 +7,7 @@ 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"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
// Builder is a type for constructing manifests. // Builder is a type for constructing manifests.
@ -48,7 +48,7 @@ func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotati
// valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json" // valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json"
func (mb *Builder) SetMediaType(mediaType string) error { func (mb *Builder) SetMediaType(mediaType string) error {
if mediaType != "" && mediaType != v1.MediaTypeImageManifest { if mediaType != "" && mediaType != v1.MediaTypeImageManifest {
return errors.New("Invalid media type for OCI image manifest") return errors.New("invalid media type for OCI image manifest")
} }
mb.mediaType = mediaType mb.mediaType = mediaType

View File

@ -8,7 +8,7 @@ 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"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
var ( var (
@ -22,6 +22,9 @@ var (
func init() { func init() {
ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
if err := validateManifest(b); err != nil {
return nil, distribution.Descriptor{}, err
}
m := new(DeserializedManifest) m := new(DeserializedManifest)
err := m.UnmarshalJSON(b) err := m.UnmarshalJSON(b)
if err != nil { if err != nil {
@ -87,7 +90,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)
@ -122,3 +125,22 @@ func (m *DeserializedManifest) MarshalJSON() ([]byte, error) {
func (m DeserializedManifest) Payload() (string, []byte, error) { func (m DeserializedManifest) Payload() (string, []byte, error) {
return v1.MediaTypeImageManifest, m.canonical, nil return v1.MediaTypeImageManifest, m.canonical, nil
} }
// unknownDocument represents a manifest, manifest list, or index that has not
// yet been validated
type unknownDocument struct {
Manifests interface{} `json:"manifests,omitempty"`
}
// validateManifest returns an error if the byte slice is invalid JSON or if it
// contains fields that belong to a index
func validateManifest(b []byte) error {
var doc unknownDocument
if err := json.Unmarshal(b, &doc); err != nil {
return err
}
if doc.Manifests != nil {
return errors.New("ocimanifest: expected manifest but found index")
}
return nil
}

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

View File

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

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

View File

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

View File

@ -56,6 +56,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
return named, nil 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. // splitDockerDomain splits a repository name to domain and remotename string.
// If no valid domain is found, the default domain is used. Repository name // If no valid domain is found, the default domain is used. Repository name
// needs to be already validated before. // needs to be already validated before.

View File

@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
var repo repository var repo repository
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1]) nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
if nameMatch != nil && len(nameMatch) == 3 { if len(nameMatch) == 3 {
repo.domain = nameMatch[1] repo.domain = nameMatch[1]
repo.path = nameMatch[2] repo.path = nameMatch[2]
} else { } else {

View File

@ -207,11 +207,11 @@ func (errs Errors) MarshalJSON() ([]byte, error) {
for _, daErr := range errs { for _, daErr := range errs {
var err Error var err Error
switch daErr.(type) { switch daErr := daErr.(type) {
case ErrorCode: case ErrorCode:
err = daErr.(ErrorCode).WithDetail(nil) err = daErr.WithDetail(nil)
case Error: case Error:
err = daErr.(Error) err = daErr
default: default:
err = ErrorCodeUnknown.WithDetail(daErr) err = ErrorCodeUnknown.WithDetail(daErr)

View File

@ -252,15 +252,3 @@ func appendValuesURL(u *url.URL, values ...url.Values) *url.URL {
u.RawQuery = merged.Encode() u.RawQuery = merged.Encode()
return u return u
} }
// appendValues appends the parameters to the url. Panics if the string is not
// a url.
func appendValues(u string, values ...url.Values) string {
up, err := url.Parse(u)
if err != nil {
panic(err) // should never happen
}
return appendValuesURL(up, values...).String()
}

View File

@ -117,8 +117,8 @@ func init() {
var t octetType var t octetType
isCtl := c <= 31 || c == 127 isCtl := c <= 31 || c == 127
isChar := 0 <= c && c <= 127 isChar := 0 <= c && c <= 127
isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { if strings.ContainsRune(" \t\r\n", rune(c)) {
t |= isSpace t |= isSpace
} }
if isChar && !isCtl && !isSeparator { if isChar && !isCtl && !isSeparator {

View File

@ -16,7 +16,7 @@ import (
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/v2" v2 "github.com/docker/distribution/registry/api/v2"
"github.com/docker/distribution/registry/client/transport" "github.com/docker/distribution/registry/client/transport"
"github.com/docker/distribution/registry/storage/cache" "github.com/docker/distribution/registry/storage/cache"
"github.com/docker/distribution/registry/storage/cache/memory" "github.com/docker/distribution/registry/storage/cache/memory"
@ -736,7 +736,12 @@ func (bs *blobs) Create(ctx context.Context, options ...distribution.BlobCreateO
return nil, err return nil, err
} }
resp, err := bs.client.Post(u, "", nil) req, err := http.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
resp, err := bs.client.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -152,16 +152,6 @@ func (bs *blobStore) readlink(ctx context.Context, path string) (digest.Digest,
return linked, nil return linked, nil
} }
// resolve reads the digest link at path and returns the blob store path.
func (bs *blobStore) resolve(ctx context.Context, path string) (string, error) {
dgst, err := bs.readlink(ctx, path)
if err != nil {
return "", err
}
return bs.path(dgst)
}
type blobStatter struct { type blobStatter struct {
driver driver.StorageDriver driver driver.StorageDriver
} }

View File

@ -55,17 +55,17 @@ func (factory *azureDriverFactory) Create(parameters map[string]interface{}) (st
func FromParameters(parameters map[string]interface{}) (*Driver, error) { func FromParameters(parameters map[string]interface{}) (*Driver, error) {
accountName, ok := parameters[paramAccountName] accountName, ok := parameters[paramAccountName]
if !ok || fmt.Sprint(accountName) == "" { if !ok || fmt.Sprint(accountName) == "" {
return nil, fmt.Errorf("No %s parameter provided", paramAccountName) return nil, fmt.Errorf("no %s parameter provided", paramAccountName)
} }
accountKey, ok := parameters[paramAccountKey] accountKey, ok := parameters[paramAccountKey]
if !ok || fmt.Sprint(accountKey) == "" { if !ok || fmt.Sprint(accountKey) == "" {
return nil, fmt.Errorf("No %s parameter provided", paramAccountKey) return nil, fmt.Errorf("no %s parameter provided", paramAccountKey)
} }
container, ok := parameters[paramContainer] container, ok := parameters[paramContainer]
if !ok || fmt.Sprint(container) == "" { if !ok || fmt.Sprint(container) == "" {
return nil, fmt.Errorf("No %s parameter provided", paramContainer) return nil, fmt.Errorf("no %s parameter provided", paramContainer)
} }
realm, ok := parameters[paramRealm] realm, ok := parameters[paramRealm]

View File

@ -252,20 +252,6 @@ func (d *dir) delete(p string) error {
return nil return nil
} }
// dump outputs a primitive directory structure to stdout.
func (d *dir) dump(indent string) {
fmt.Println(indent, d.name()+"/")
for _, child := range d.children {
if child.isdir() {
child.(*dir).dump(indent + "\t")
} else {
fmt.Println(indent, child.name())
}
}
}
func (d *dir) String() string { func (d *dir) String() string {
return fmt.Sprintf("&dir{path: %v, children: %v}", d.p, d.children) return fmt.Sprintf("&dir{path: %v, children: %v}", d.p, d.children)
} }

View File

@ -16,7 +16,7 @@ import (
"github.com/aws/aws-sdk-go/service/cloudfront/sign" "github.com/aws/aws-sdk-go/service/cloudfront/sign"
dcontext "github.com/docker/distribution/context" dcontext "github.com/docker/distribution/context"
storagedriver "github.com/docker/distribution/registry/storage/driver" storagedriver "github.com/docker/distribution/registry/storage/driver"
"github.com/docker/distribution/registry/storage/driver/middleware" storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware"
) )
// cloudFrontStorageMiddleware provides a simple implementation of layerHandler that // cloudFrontStorageMiddleware provides a simple implementation of layerHandler that
@ -138,27 +138,33 @@ func newCloudFrontStorageMiddleware(storageDriver storagedriver.StorageDriver, o
// parse ipfilteredby // parse ipfilteredby
var awsIPs *awsIPs var awsIPs *awsIPs
if ipFilteredBy := options["ipfilteredby"].(string); ok { if i, ok := options["ipfilteredby"]; ok {
switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) { if ipFilteredBy, ok := i.(string); ok {
case "", "none": switch strings.ToLower(strings.TrimSpace(ipFilteredBy)) {
awsIPs = nil case "", "none":
case "aws": awsIPs = nil
newAWSIPs(ipRangesURL, updateFrequency, nil) case "aws":
case "awsregion": awsIPs = newAWSIPs(ipRangesURL, updateFrequency, nil)
var awsRegion []string case "awsregion":
if regions, ok := options["awsregion"].(string); ok { var awsRegion []string
for _, awsRegions := range strings.Split(regions, ",") { if i, ok := options["awsregion"]; ok {
awsRegion = append(awsRegion, strings.ToLower(strings.TrimSpace(awsRegions))) 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) default:
} else { return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion")
return nil, fmt.Errorf("awsRegion must be a comma separated string of valid aws regions")
} }
default: } else {
return nil, fmt.Errorf("ipfilteredby only allows a string the following value: none|aws|awsregion") 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{ return &cloudFrontStorageMiddleware{

View File

@ -188,19 +188,19 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
regionName := parameters["region"] regionName := parameters["region"]
if regionName == nil || fmt.Sprint(regionName) == "" { if regionName == nil || fmt.Sprint(regionName) == "" {
return nil, fmt.Errorf("No region parameter provided") return nil, fmt.Errorf("no region parameter provided")
} }
region := fmt.Sprint(regionName) region := fmt.Sprint(regionName)
// Don't check the region value if a custom endpoint is provided. // Don't check the region value if a custom endpoint is provided.
if regionEndpoint == "" { if regionEndpoint == "" {
if _, ok := validRegions[region]; !ok { if _, ok := validRegions[region]; !ok {
return nil, fmt.Errorf("Invalid region provided: %v", region) return nil, fmt.Errorf("invalid region provided: %v", region)
} }
} }
bucket := parameters["bucket"] bucket := parameters["bucket"]
if bucket == nil || fmt.Sprint(bucket) == "" { if bucket == nil || fmt.Sprint(bucket) == "" {
return nil, fmt.Errorf("No bucket parameter provided") return nil, fmt.Errorf("no bucket parameter provided")
} }
encryptBool := false encryptBool := false
@ -209,7 +209,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case string: case string:
b, err := strconv.ParseBool(encrypt) b, err := strconv.ParseBool(encrypt)
if err != nil { if err != nil {
return nil, fmt.Errorf("The encrypt parameter should be a boolean") return nil, fmt.Errorf("the encrypt parameter should be a boolean")
} }
encryptBool = b encryptBool = b
case bool: case bool:
@ -217,7 +217,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case nil: case nil:
// do nothing // do nothing
default: default:
return nil, fmt.Errorf("The encrypt parameter should be a boolean") return nil, fmt.Errorf("the encrypt parameter should be a boolean")
} }
secureBool := true secureBool := true
@ -226,7 +226,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case string: case string:
b, err := strconv.ParseBool(secure) b, err := strconv.ParseBool(secure)
if err != nil { if err != nil {
return nil, fmt.Errorf("The secure parameter should be a boolean") return nil, fmt.Errorf("the secure parameter should be a boolean")
} }
secureBool = b secureBool = b
case bool: case bool:
@ -234,7 +234,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case nil: case nil:
// do nothing // do nothing
default: default:
return nil, fmt.Errorf("The secure parameter should be a boolean") return nil, fmt.Errorf("the secure parameter should be a boolean")
} }
skipVerifyBool := false skipVerifyBool := false
@ -243,7 +243,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case string: case string:
b, err := strconv.ParseBool(skipVerify) b, err := strconv.ParseBool(skipVerify)
if err != nil { if err != nil {
return nil, fmt.Errorf("The skipVerify parameter should be a boolean") return nil, fmt.Errorf("the skipVerify parameter should be a boolean")
} }
skipVerifyBool = b skipVerifyBool = b
case bool: case bool:
@ -251,7 +251,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case nil: case nil:
// do nothing // do nothing
default: default:
return nil, fmt.Errorf("The skipVerify parameter should be a boolean") return nil, fmt.Errorf("the skipVerify parameter should be a boolean")
} }
v4Bool := true v4Bool := true
@ -260,7 +260,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case string: case string:
b, err := strconv.ParseBool(v4auth) b, err := strconv.ParseBool(v4auth)
if err != nil { if err != nil {
return nil, fmt.Errorf("The v4auth parameter should be a boolean") return nil, fmt.Errorf("the v4auth parameter should be a boolean")
} }
v4Bool = b v4Bool = b
case bool: case bool:
@ -268,7 +268,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
case nil: case nil:
// do nothing // do nothing
default: default:
return nil, fmt.Errorf("The v4auth parameter should be a boolean") return nil, fmt.Errorf("the v4auth parameter should be a boolean")
} }
keyID := parameters["keyid"] keyID := parameters["keyid"]
@ -306,7 +306,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
if storageClassParam != nil { if storageClassParam != nil {
storageClassString, ok := storageClassParam.(string) storageClassString, ok := storageClassParam.(string)
if !ok { if !ok {
return nil, fmt.Errorf("The storageclass parameter must be one of %v, %v invalid", return nil, fmt.Errorf("the storageclass parameter must be one of %v, %v invalid",
[]string{s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam) []string{s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam)
} }
// All valid storage class parameters are UPPERCASE, so be a bit more flexible here // All valid storage class parameters are UPPERCASE, so be a bit more flexible here
@ -314,7 +314,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
if storageClassString != noStorageClass && if storageClassString != noStorageClass &&
storageClassString != s3.StorageClassStandard && storageClassString != s3.StorageClassStandard &&
storageClassString != s3.StorageClassReducedRedundancy { storageClassString != s3.StorageClassReducedRedundancy {
return nil, fmt.Errorf("The storageclass parameter must be one of %v, %v invalid", return nil, fmt.Errorf("the storageclass parameter must be one of %v, %v invalid",
[]string{noStorageClass, s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam) []string{noStorageClass, s3.StorageClassStandard, s3.StorageClassReducedRedundancy}, storageClassParam)
} }
storageClass = storageClassString storageClass = storageClassString
@ -330,11 +330,11 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
if objectACLParam != nil { if objectACLParam != nil {
objectACLString, ok := objectACLParam.(string) objectACLString, ok := objectACLParam.(string)
if !ok { if !ok {
return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectACLParam) return nil, fmt.Errorf("invalid value for objectacl parameter: %v", objectACLParam)
} }
if _, ok = validObjectACLs[objectACLString]; !ok { if _, ok = validObjectACLs[objectACLString]; !ok {
return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectACLParam) return nil, fmt.Errorf("invalid value for objectacl parameter: %v", objectACLParam)
} }
objectACL = objectACLString objectACL = objectACLString
} }
@ -366,7 +366,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
return New(params) return New(params)
} }
// getParameterAsInt64 converts paramaters[name] to an int64 value (using // getParameterAsInt64 converts parameters[name] to an int64 value (using
// defaultt if nil), verifies it is no smaller than min, and returns it. // defaultt if nil), verifies it is no smaller than min, and returns it.
func getParameterAsInt64(parameters map[string]interface{}, name string, defaultt int64, min int64, max int64) (int64, error) { func getParameterAsInt64(parameters map[string]interface{}, name string, defaultt int64, min int64, max int64) (int64, error) {
rv := defaultt rv := defaultt
@ -389,7 +389,7 @@ func getParameterAsInt64(parameters map[string]interface{}, name string, default
} }
if rv < min || rv > max { if rv < min || rv > max {
return 0, fmt.Errorf("The %s %#v parameter should be a number between %d and %d (inclusive)", name, rv, min, max) return 0, fmt.Errorf("the %s %#v parameter should be a number between %d and %d (inclusive)", name, rv, min, max)
} }
return rv, nil return rv, nil
@ -401,7 +401,7 @@ func New(params DriverParameters) (*Driver, error) {
if !params.V4Auth && if !params.V4Auth &&
(params.RegionEndpoint == "" || (params.RegionEndpoint == "" ||
strings.Contains(params.RegionEndpoint, "s3.amazonaws.com")) { strings.Contains(params.RegionEndpoint, "s3.amazonaws.com")) {
return nil, fmt.Errorf("On Amazon S3 this storage driver can only be used with v4 authentication") return nil, fmt.Errorf("on Amazon S3 this storage driver can only be used with v4 authentication")
} }
awsConfig := aws.NewConfig() awsConfig := aws.NewConfig()
@ -878,7 +878,7 @@ func (d *driver) URLFor(ctx context.Context, path string, options map[string]int
if ok { if ok {
et, ok := expires.(time.Time) et, ok := expires.(time.Time)
if ok { if ok {
expiresIn = et.Sub(time.Now()) expiresIn = time.Until(et)
} }
} }
@ -970,8 +970,19 @@ func (d *driver) doWalk(parentCtx context.Context, objectCount *int64, path, pre
defer done("s3aws.ListObjectsV2Pages(%s)", path) defer done("s3aws.ListObjectsV2Pages(%s)", path)
listObjectErr := d.S3.ListObjectsV2PagesWithContext(ctx, listObjectsInput, func(objects *s3.ListObjectsV2Output, lastPage bool) bool { listObjectErr := d.S3.ListObjectsV2PagesWithContext(ctx, listObjectsInput, func(objects *s3.ListObjectsV2Output, lastPage bool) bool {
*objectCount += *objects.KeyCount var count int64
walkInfos := make([]walkInfoContainer, 0, *objects.KeyCount) // 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 { for _, dir := range objects.CommonPrefixes {
commonPrefix := *dir.Prefix commonPrefix := *dir.Prefix

View File

@ -39,12 +39,6 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
const (
signatureVersion = "2"
signatureMethod = "HmacSHA1"
timeFormat = "2006-01-02T15:04:05Z"
)
type signer struct { type signer struct {
// Values that must be populated from the request // Values that must be populated from the request
Request *http.Request Request *http.Request

View File

@ -160,23 +160,23 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) {
} }
if params.Username == "" { if params.Username == "" {
return nil, fmt.Errorf("No username parameter provided") return nil, fmt.Errorf("no username parameter provided")
} }
if params.Password == "" { if params.Password == "" {
return nil, fmt.Errorf("No password parameter provided") return nil, fmt.Errorf("no password parameter provided")
} }
if params.AuthURL == "" { if params.AuthURL == "" {
return nil, fmt.Errorf("No authurl parameter provided") return nil, fmt.Errorf("no authurl parameter provided")
} }
if params.Container == "" { if params.Container == "" {
return nil, fmt.Errorf("No container parameter provided") return nil, fmt.Errorf("no container parameter provided")
} }
if params.ChunkSize < minChunkSize { if params.ChunkSize < minChunkSize {
return nil, fmt.Errorf("The chunksize %#v parameter should be a number that is larger than or equal to %d", params.ChunkSize, minChunkSize) return nil, fmt.Errorf("the chunksize %#v parameter should be a number that is larger than or equal to %d", params.ChunkSize, minChunkSize)
} }
return New(params) return New(params)
@ -211,15 +211,15 @@ func New(params Parameters) (*Driver, error) {
} }
err := ct.Authenticate() err := ct.Authenticate()
if err != nil { if err != nil {
return nil, fmt.Errorf("Swift authentication failed: %s", err) return nil, fmt.Errorf("swift authentication failed: %s", err)
} }
if _, _, err := ct.Container(params.Container); err == swift.ContainerNotFound { if _, _, err := ct.Container(params.Container); err == swift.ContainerNotFound {
if err := ct.ContainerCreate(params.Container, nil); err != nil { if err := ct.ContainerCreate(params.Container, nil); err != nil {
return nil, fmt.Errorf("Failed to create container %s (%s)", params.Container, err) return nil, fmt.Errorf("failed to create container %s (%s)", params.Container, err)
} }
} else if err != nil { } else if err != nil {
return nil, fmt.Errorf("Failed to retrieve info about container %s (%s)", params.Container, err) return nil, fmt.Errorf("failed to retrieve info about container %s (%s)", params.Container, err)
} }
d := &driver{ d := &driver{
@ -258,7 +258,7 @@ func New(params Parameters) (*Driver, error) {
if d.TempURLContainerKey { if d.TempURLContainerKey {
_, containerHeaders, err := d.Conn.Container(d.Container) _, containerHeaders, err := d.Conn.Container(d.Container)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to fetch container info %s (%s)", d.Container, err) return nil, fmt.Errorf("failed to fetch container info %s (%s)", d.Container, err)
} }
d.SecretKey = containerHeaders["X-Container-Meta-Temp-Url-Key"] d.SecretKey = containerHeaders["X-Container-Meta-Temp-Url-Key"]
@ -273,7 +273,7 @@ func New(params Parameters) (*Driver, error) {
// Use the account secret key // Use the account secret key
_, accountHeaders, err := d.Conn.Account() _, accountHeaders, err := d.Conn.Account()
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to fetch account info (%s)", err) return nil, fmt.Errorf("failed to fetch account info (%s)", err)
} }
d.SecretKey = accountHeaders["X-Account-Meta-Temp-Url-Key"] d.SecretKey = accountHeaders["X-Account-Meta-Temp-Url-Key"]
@ -350,7 +350,7 @@ func (d *driver) Reader(ctx context.Context, path string, offset int64) (io.Read
} }
if isDLO && size == 0 { if isDLO && size == 0 {
if time.Now().Add(waitingTime).After(endTime) { if time.Now().Add(waitingTime).After(endTime) {
return nil, fmt.Errorf("Timeout expired while waiting for segments of %s to show up", path) return nil, fmt.Errorf("timeout expired while waiting for segments of %s to show up", path)
} }
time.Sleep(waitingTime) time.Sleep(waitingTime)
waitingTime *= 2 waitingTime *= 2
@ -456,7 +456,7 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo,
_, isDLO := headers["X-Object-Manifest"] _, isDLO := headers["X-Object-Manifest"]
if isDLO && info.Bytes == 0 { if isDLO && info.Bytes == 0 {
if time.Now().Add(waitingTime).After(endTime) { if time.Now().Add(waitingTime).After(endTime) {
return nil, fmt.Errorf("Timeout expired while waiting for segments of %s to show up", path) return nil, fmt.Errorf("timeout expired while waiting for segments of %s to show up", path)
} }
time.Sleep(waitingTime) time.Sleep(waitingTime)
waitingTime *= 2 waitingTime *= 2
@ -755,7 +755,7 @@ func chunkFilenames(slice []string, maxSize int) (chunks [][]string, err error)
chunks = append(chunks, slice[offset:offset+chunkSize]) chunks = append(chunks, slice[offset:offset+chunkSize])
} }
} else { } else {
return nil, fmt.Errorf("Max chunk size must be > 0") return nil, fmt.Errorf("max chunk size must be > 0")
} }
return return
} }
@ -894,7 +894,7 @@ func (w *writer) waitForSegmentsToShowUp() error {
if info.Bytes == w.size { if info.Bytes == w.size {
break break
} }
err = fmt.Errorf("Timeout expired while waiting for segments of %s to show up", w.path) err = fmt.Errorf("timeout expired while waiting for segments of %s to show up", w.path)
} }
if time.Now().Add(waitingTime).After(endTime) { if time.Now().Add(waitingTime).After(endTime) {
break break

View File

@ -98,15 +98,13 @@ func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, regis
return nil return nil
}) })
if err != nil { // In certain situations such as unfinished uploads, deleting all
// In certain situations such as unfinished uploads, deleting all // tags in S3 or removing the _manifests folder manually, this
// tags in S3 or removing the _manifests folder manually, this // error may be of type PathNotFound.
// error may be of type PathNotFound. //
// // In these cases we can continue marking other manifests safely.
// In these cases we can continue marking other manifests safely. if _, ok := err.(driver.PathNotFoundError); ok {
if _, ok := err.(driver.PathNotFoundError); ok { return nil
return nil
}
} }
return err return err

View File

@ -18,6 +18,7 @@ func getContent(ctx context.Context, driver driver.StorageDriver, p string) ([]b
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer r.Close()
return readAllLimited(r, maxBlobGetSize) return readAllLimited(r, maxBlobGetSize)
} }

View File

@ -13,7 +13,7 @@ import (
"github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema1"
"github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/manifest/schema2"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
// A ManifestHandler gets and puts manifests of a particular type. // A ManifestHandler gets and puts manifests of a particular type.

View File

@ -9,7 +9,7 @@ import (
dcontext "github.com/docker/distribution/context" dcontext "github.com/docker/distribution/context"
"github.com/docker/distribution/manifest/ocischema" "github.com/docker/distribution/manifest/ocischema"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
//ocischemaManifestHandler is a ManifestHandler that covers ocischema manifests. //ocischemaManifestHandler is a ManifestHandler that covers ocischema manifests.

View File

@ -133,10 +133,7 @@ func pathFor(spec pathSpec) (string, error) {
return path.Join(append(append(repoPrefix, v.name, "_manifests", "revisions"), components...)...), nil return path.Join(append(append(repoPrefix, v.name, "_manifests", "revisions"), components...)...), nil
case manifestRevisionLinkPathSpec: case manifestRevisionLinkPathSpec:
root, err := pathFor(manifestRevisionPathSpec{ root, err := pathFor(manifestRevisionPathSpec(v))
name: v.name,
revision: v.revision,
})
if err != nil { if err != nil {
return "", err return "", err
@ -156,10 +153,7 @@ func pathFor(spec pathSpec) (string, error) {
return path.Join(root, v.tag), nil return path.Join(root, v.tag), nil
case manifestTagCurrentPathSpec: case manifestTagCurrentPathSpec:
root, err := pathFor(manifestTagPathSpec{ root, err := pathFor(manifestTagPathSpec(v))
name: v.name,
tag: v.tag,
})
if err != nil { if err != nil {
return "", err return "", err
@ -167,10 +161,7 @@ func pathFor(spec pathSpec) (string, error) {
return path.Join(root, "current", "link"), nil return path.Join(root, "current", "link"), nil
case manifestTagIndexPathSpec: case manifestTagIndexPathSpec:
root, err := pathFor(manifestTagPathSpec{ root, err := pathFor(manifestTagPathSpec(v))
name: v.name,
tag: v.tag,
})
if err != nil { if err != nil {
return "", err return "", err
@ -178,11 +169,7 @@ func pathFor(spec pathSpec) (string, error) {
return path.Join(root, "index"), nil return path.Join(root, "index"), nil
case manifestTagIndexEntryLinkPathSpec: case manifestTagIndexEntryLinkPathSpec:
root, err := pathFor(manifestTagIndexEntryPathSpec{ root, err := pathFor(manifestTagIndexEntryPathSpec(v))
name: v.name,
tag: v.tag,
revision: v.revision,
})
if err != nil { if err != nil {
return "", err return "", err

View File

@ -59,7 +59,7 @@ func PurgeUploads(ctx context.Context, driver storageDriver.StorageDriver, older
// file, so gather files by UUID with a date from startedAt. // file, so gather files by UUID with a date from startedAt.
func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriver) (map[string]uploadData, []error) { func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriver) (map[string]uploadData, []error) {
var errors []error var errors []error
uploads := make(map[string]uploadData, 0) uploads := make(map[string]uploadData)
inUploadDir := false inUploadDir := false
root, err := pathFor(repositoriesRootPathSpec{}) root, err := pathFor(repositoriesRootPathSpec{})

View File

@ -14,9 +14,8 @@ import (
) )
var ( var (
errUnexpectedURL = errors.New("unexpected URL on layer") errMissingURL = errors.New("missing URL on layer")
errMissingURL = errors.New("missing URL on layer") errInvalidURL = errors.New("invalid URL on layer")
errInvalidURL = errors.New("invalid URL on layer")
) )
//schema2ManifestHandler is a ManifestHandler that covers schema2 manifests. //schema2ManifestHandler is a ManifestHandler that covers schema2 manifests.
@ -93,7 +92,7 @@ func (ms *schema2ManifestHandler) verifyManifest(ctx context.Context, mnfst sche
switch descriptor.MediaType { switch descriptor.MediaType {
case schema2.MediaTypeForeignLayer: case schema2.MediaTypeForeignLayer:
// Clients download this layer from an external URL, so do not check for // Clients download this layer from an external URL, so do not check for
// its presense. // its presence.
if len(descriptor.URLs) == 0 { if len(descriptor.URLs) == 0 {
err = errMissingURL err = errMissingURL
} }

View File

@ -50,25 +50,6 @@ func (ts *tagStore) All(ctx context.Context) ([]string, error) {
return tags, nil return tags, nil
} }
// exists returns true if the specified manifest tag exists in the repository.
func (ts *tagStore) exists(ctx context.Context, tag string) (bool, error) {
tagPath, err := pathFor(manifestTagCurrentPathSpec{
name: ts.repository.Named().Name(),
tag: tag,
})
if err != nil {
return false, err
}
exists, err := exists(ctx, ts.blobStore.driver, tagPath)
if err != nil {
return false, err
}
return exists, nil
}
// Tag tags the digest with the given tag, updating the the store to point at // Tag tags the digest with the given tag, updating the the store to point at
// the current tag. The digest must point to a manifest. // the current tag. The digest must point to a manifest.
func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error { func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {

View File

@ -1,22 +0,0 @@
package storage
import (
"context"
"github.com/docker/distribution/registry/storage/driver"
)
// Exists provides a utility method to test whether or not a path exists in
// the given driver.
func exists(ctx context.Context, drv driver.StorageDriver, path string) (bool, error) {
if _, err := drv.Stat(ctx, path); err != nil {
switch err := err.(type) {
case driver.PathNotFoundError:
return false, nil
default:
return false, err
}
}
return true, nil
}

View File

@ -8,7 +8,7 @@ github.com/bugsnag/bugsnag-go b1d153021fcd90ca3f080db36bec96dc690fb274
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702 github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782 github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782
github.com/denverdino/aliyungo afedced274aa9a7fcdd47ac97018f0f8db4e5de2 github.com/denverdino/aliyungo afedced274aa9a7fcdd47ac97018f0f8db4e5de2
github.com/dgrijalva/jwt-go a601269ab70c205d26370c16f7c81e9017c14e04 github.com/dgrijalva/jwt-go 4bbdd8ac624fc7a9ef7aec841c43d99b5fe65a29 https://github.com/golang-jwt/jwt.git # v3.2.2
github.com/docker/go-metrics 399ea8c73916000c64c2c76e8da00ca82f8387ab github.com/docker/go-metrics 399ea8c73916000c64c2c76e8da00ca82f8387ab
github.com/docker/libtrust fa567046d9b14f6aa788882a950d69651d230b21 github.com/docker/libtrust fa567046d9b14f6aa788882a950d69651d230b21
github.com/garyburd/redigo 535138d7bcd717d6531c701ef5933d98b1866257 github.com/garyburd/redigo 535138d7bcd717d6531c701ef5933d98b1866257
@ -48,4 +48,4 @@ gopkg.in/square/go-jose.v1 40d457b439244b546f023d056628e5184136899b
gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 v2.2.1
rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git
github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
github.com/opencontainers/image-spec ab7389ef9f50030c9b245bc16b981c7ddf192882 github.com/opencontainers/image-spec 67d2d5658fe0476ab9bf414cec164077ebff3920 # v1.0.2

View File

@ -8,7 +8,7 @@ var Package = "github.com/docker/distribution"
// the latest release tag by hand, always suffixed by "+unknown". During // 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 // 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. // used if the registry is run after a go get based install.
var Version = "v2.7.1+unknown" var Version = "v2.8.0-beta.1+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build // Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time. // the program at linking time.

View File

@ -216,7 +216,7 @@ github.com/docker/cli/cli/config
github.com/docker/cli/cli/config/configfile github.com/docker/cli/cli/config/configfile
github.com/docker/cli/cli/config/credentials github.com/docker/cli/cli/config/credentials
github.com/docker/cli/cli/config/types github.com/docker/cli/cli/config/types
# github.com/docker/distribution v2.7.1+incompatible # github.com/docker/distribution v2.8.0+incompatible
## explicit ## explicit
github.com/docker/distribution github.com/docker/distribution
github.com/docker/distribution/configuration github.com/docker/distribution/configuration