commit
						0d3efadf01
					
				|  | @ -391,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) | ||||||
|  | @ -466,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 | ||||||
|  | @ -668,11 +668,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) | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|  | @ -542,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 { | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -163,7 +163,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 +177,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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -87,7 +87,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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -125,15 +125,6 @@ func (b *bridge) RepoDeleted(repo reference.Named) error { | ||||||
| 	return b.sink.Write(*event) | 	return b.sink.Write(*event) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (b *bridge) createManifestEventAndWrite(action string, repo reference.Named, sm distribution.Manifest) error { |  | ||||||
| 	manifestEvent, err := b.createManifestEvent(action, repo, sm) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return b.sink.Write(*manifestEvent) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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 { | ||||||
| 	event := b.createEvent(action) | 	event := b.createEvent(action) | ||||||
| 	event.Target.Repository = repo.Name() | 	event.Target.Repository = repo.Name() | ||||||
|  |  | ||||||
|  | @ -114,8 +114,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | ||||||
| 	prototype.Request.UserAgent = "test/0.1" | 	prototype.Request.UserAgent = "test/0.1" | ||||||
| 	prototype.Source.Addr = "hostname.local:port" | 	prototype.Source.Addr = "hostname.local:port" | ||||||
| 
 | 
 | ||||||
| 	var manifestPush Event | 	var manifestPush = prototype | ||||||
| 	manifestPush = prototype |  | ||||||
| 	manifestPush.ID = "asdf-asdf-asdf-asdf-0" | 	manifestPush.ID = "asdf-asdf-asdf-asdf-0" | ||||||
| 	manifestPush.Target.Digest = "sha256:0123456789abcdef0" | 	manifestPush.Target.Digest = "sha256:0123456789abcdef0" | ||||||
| 	manifestPush.Target.Length = 1 | 	manifestPush.Target.Length = 1 | ||||||
|  | @ -124,8 +123,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | ||||||
| 	manifestPush.Target.Repository = "library/test" | 	manifestPush.Target.Repository = "library/test" | ||||||
| 	manifestPush.Target.URL = "http://example.com/v2/library/test/manifests/latest" | 	manifestPush.Target.URL = "http://example.com/v2/library/test/manifests/latest" | ||||||
| 
 | 
 | ||||||
| 	var layerPush0 Event | 	var layerPush0 = prototype | ||||||
| 	layerPush0 = prototype |  | ||||||
| 	layerPush0.ID = "asdf-asdf-asdf-asdf-1" | 	layerPush0.ID = "asdf-asdf-asdf-asdf-1" | ||||||
| 	layerPush0.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5" | 	layerPush0.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5" | ||||||
| 	layerPush0.Target.Length = 2 | 	layerPush0.Target.Length = 2 | ||||||
|  | @ -134,8 +132,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | ||||||
| 	layerPush0.Target.Repository = "library/test" | 	layerPush0.Target.Repository = "library/test" | ||||||
| 	layerPush0.Target.URL = "http://example.com/v2/library/test/manifests/latest" | 	layerPush0.Target.URL = "http://example.com/v2/library/test/manifests/latest" | ||||||
| 
 | 
 | ||||||
| 	var layerPush1 Event | 	var layerPush1 = prototype | ||||||
| 	layerPush1 = prototype |  | ||||||
| 	layerPush1.ID = "asdf-asdf-asdf-asdf-2" | 	layerPush1.ID = "asdf-asdf-asdf-asdf-2" | ||||||
| 	layerPush1.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d6" | 	layerPush1.Target.Digest = "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d6" | ||||||
| 	layerPush1.Target.Length = 3 | 	layerPush1.Target.Length = 3 | ||||||
|  |  | ||||||
|  | @ -133,8 +133,7 @@ type headerRoundTripper struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (hrt *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | func (hrt *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | ||||||
| 	var nreq http.Request | 	var nreq = *req | ||||||
| 	nreq = *req |  | ||||||
| 	nreq.Header = make(http.Header) | 	nreq.Header = make(http.Header) | ||||||
| 
 | 
 | ||||||
| 	merge := func(headers http.Header) { | 	merge := func(headers http.Header) { | ||||||
|  |  | ||||||
|  | @ -136,11 +136,10 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository, r | ||||||
| 	var blobDigests []digest.Digest | 	var blobDigests []digest.Digest | ||||||
| 	blobs := repository.Blobs(ctx) | 	blobs := repository.Blobs(ctx) | ||||||
| 	for i := 0; i < 2; i++ { | 	for i := 0; i < 2; i++ { | ||||||
| 		rs, ds, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("error creating test layer: %v", err) | 			t.Fatalf("error creating test layer: %v", err) | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(ds) |  | ||||||
| 		blobDigests = append(blobDigests, dgst) | 		blobDigests = append(blobDigests, dgst) | ||||||
| 
 | 
 | ||||||
| 		wr, err := blobs.Create(ctx) | 		wr, err := blobs.Create(ctx) | ||||||
|  |  | ||||||
|  | @ -284,11 +284,6 @@ type retryingSink struct { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type retryingSinkListener interface { |  | ||||||
| 	active(events ...Event) |  | ||||||
| 	retry(events ...Event) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // TODO(stevvooe): We are using circuit break here, which actually doesn't
 | // TODO(stevvooe): We are using circuit break here, which actually doesn't
 | ||||||
| // make a whole lot of sense for this use case, since we always retry. Move
 | // make a whole lot of sense for this use case, since we always retry. Move
 | ||||||
| // this to use bounded exponential backoff.
 | // this to use bounded exponential backoff.
 | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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() |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -182,11 +182,6 @@ func TestURLBuilderWithPrefix(t *testing.T) { | ||||||
| 	doTest(false) | 	doTest(false) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type builderFromRequestTestCase struct { |  | ||||||
| 	request *http.Request |  | ||||||
| 	base    string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestBuilderFromRequest(t *testing.T) { | func TestBuilderFromRequest(t *testing.T) { | ||||||
| 	u, err := url.Parse("http://example.com") | 	u, err := url.Parse("http://example.com") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -152,7 +152,7 @@ func TestBlobFetch(t *testing.T) { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	if bytes.Compare(b, b1) != 0 { | 	if !bytes.Equal(b, b1) { | ||||||
| 		t.Fatalf("Wrong bytes values fetched: [%d]byte != [%d]byte", len(b), len(b1)) | 		t.Fatalf("Wrong bytes values fetched: [%d]byte != [%d]byte", len(b), len(b1)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -959,7 +959,6 @@ func testManifestWithStorageError(t *testing.T, env *testEnv, imageName referenc | ||||||
| 	defer resp.Body.Close() | 	defer resp.Body.Close() | ||||||
| 	checkResponse(t, "getting non-existent manifest", resp, expectedStatusCode) | 	checkResponse(t, "getting non-existent manifest", resp, expectedStatusCode) | ||||||
| 	checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode) | 	checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode) | ||||||
| 	return |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs { | func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs { | ||||||
|  | @ -1066,12 +1065,11 @@ func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Name | ||||||
| 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | ||||||
| 
 | 
 | ||||||
| 	for i := range unsignedManifest.FSLayers { | 	for i := range unsignedManifest.FSLayers { | ||||||
| 		rs, dgstStr, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("error creating random layer %d: %v", i, err) | 			t.Fatalf("error creating random layer %d: %v", i, err) | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(dgstStr) |  | ||||||
| 
 | 
 | ||||||
| 		expectedLayers[dgst] = rs | 		expectedLayers[dgst] = rs | ||||||
| 		unsignedManifest.FSLayers[i].BlobSum = dgst | 		unsignedManifest.FSLayers[i].BlobSum = dgst | ||||||
|  | @ -1405,12 +1403,11 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name | ||||||
| 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | ||||||
| 
 | 
 | ||||||
| 	for i := range manifest.Layers { | 	for i := range manifest.Layers { | ||||||
| 		rs, dgstStr, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("error creating random layer %d: %v", i, err) | 			t.Fatalf("error creating random layer %d: %v", i, err) | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(dgstStr) |  | ||||||
| 
 | 
 | ||||||
| 		expectedLayers[dgst] = rs | 		expectedLayers[dgst] = rs | ||||||
| 		manifest.Layers[i].Digest = dgst | 		manifest.Layers[i].Digest = dgst | ||||||
|  | @ -2432,11 +2429,10 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string) | ||||||
| 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | 	expectedLayers := make(map[digest.Digest]io.ReadSeeker) | ||||||
| 
 | 
 | ||||||
| 	for i := range unsignedManifest.FSLayers { | 	for i := range unsignedManifest.FSLayers { | ||||||
| 		rs, dgstStr, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("error creating random layer %d: %v", i, err) | 			t.Fatalf("error creating random layer %d: %v", i, err) | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(dgstStr) |  | ||||||
| 
 | 
 | ||||||
| 		expectedLayers[dgst] = rs | 		expectedLayers[dgst] = rs | ||||||
| 		unsignedManifest.FSLayers[i].BlobSum = dgst | 		unsignedManifest.FSLayers[i].BlobSum = dgst | ||||||
|  |  | ||||||
|  | @ -753,20 +753,18 @@ func (app *App) logError(ctx context.Context, errors errcode.Errors) { | ||||||
| 	for _, e1 := range errors { | 	for _, e1 := range errors { | ||||||
| 		var c context.Context | 		var c context.Context | ||||||
| 
 | 
 | ||||||
| 		switch e1.(type) { | 		switch e := e1.(type) { | ||||||
| 		case errcode.Error: | 		case errcode.Error: | ||||||
| 			e, _ := e1.(errcode.Error) |  | ||||||
| 			c = context.WithValue(ctx, errCodeKey{}, e.Code) | 			c = context.WithValue(ctx, errCodeKey{}, e.Code) | ||||||
| 			c = context.WithValue(c, errMessageKey{}, e.Message) | 			c = context.WithValue(c, errMessageKey{}, e.Message) | ||||||
| 			c = context.WithValue(c, errDetailKey{}, e.Detail) | 			c = context.WithValue(c, errDetailKey{}, e.Detail) | ||||||
| 		case errcode.ErrorCode: | 		case errcode.ErrorCode: | ||||||
| 			e, _ := e1.(errcode.ErrorCode) |  | ||||||
| 			c = context.WithValue(ctx, errCodeKey{}, e) | 			c = context.WithValue(ctx, errCodeKey{}, e) | ||||||
| 			c = context.WithValue(c, errMessageKey{}, e.Message()) | 			c = context.WithValue(c, errMessageKey{}, e.Message()) | ||||||
| 		default: | 		default: | ||||||
| 			// just normal go 'error'
 | 			// just normal go 'error'
 | ||||||
| 			c = context.WithValue(ctx, errCodeKey{}, errcode.ErrorCodeUnknown) | 			c = context.WithValue(ctx, errCodeKey{}, errcode.ErrorCodeUnknown) | ||||||
| 			c = context.WithValue(c, errMessageKey{}, e1.Error()) | 			c = context.WithValue(c, errMessageKey{}, e.Error()) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		c = dcontext.WithLogger(c, dcontext.GetLogger(c, | 		c = dcontext.WithLogger(c, dcontext.GetLogger(c, | ||||||
|  |  | ||||||
|  | @ -172,7 +172,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque | ||||||
| 
 | 
 | ||||||
| 	ct := r.Header.Get("Content-Type") | 	ct := r.Header.Get("Content-Type") | ||||||
| 	if ct != "" && ct != "application/octet-stream" { | 	if ct != "" && ct != "application/octet-stream" { | ||||||
| 		buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(fmt.Errorf("Bad Content-Type"))) | 		buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(fmt.Errorf("bad Content-Type"))) | ||||||
| 		// TODO(dmcgowan): encode error
 | 		// TODO(dmcgowan): encode error
 | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ type logHook struct { | ||||||
| func (hook *logHook) Fire(entry *logrus.Entry) error { | func (hook *logHook) Fire(entry *logrus.Entry) error { | ||||||
| 	addr := strings.Split(hook.Mail.Addr, ":") | 	addr := strings.Split(hook.Mail.Addr, ":") | ||||||
| 	if len(addr) != 2 { | 	if len(addr) != 2 { | ||||||
| 		return errors.New("Invalid Mail Address") | 		return errors.New("invalid Mail Address") | ||||||
| 	} | 	} | ||||||
| 	host := addr[0] | 	host := addr[0] | ||||||
| 	subject := fmt.Sprintf("[%s] %s: %s", entry.Level, host, entry.Message) | 	subject := fmt.Sprintf("[%s] %s: %s", entry.Level, host, entry.Message) | ||||||
|  | @ -37,7 +37,7 @@ func (hook *logHook) Fire(entry *logrus.Entry) error { | ||||||
| 	if err := t.Execute(b, entry); err != nil { | 	if err := t.Execute(b, entry); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	body := fmt.Sprintf("%s", b) | 	body := b.String() | ||||||
| 
 | 
 | ||||||
| 	return hook.Mail.sendMail(subject, body) | 	return hook.Mail.sendMail(subject, body) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ type mailer struct { | ||||||
| func (mail *mailer) sendMail(subject, message string) error { | func (mail *mailer) sendMail(subject, message string) error { | ||||||
| 	addr := strings.Split(mail.Addr, ":") | 	addr := strings.Split(mail.Addr, ":") | ||||||
| 	if len(addr) != 2 { | 	if len(addr) != 2 { | ||||||
| 		return errors.New("Invalid Mail Address") | 		return errors.New("invalid Mail Address") | ||||||
| 	} | 	} | ||||||
| 	host := addr[0] | 	host := addr[0] | ||||||
| 	msg := []byte("To:" + strings.Join(mail.To, ";") + | 	msg := []byte("To:" + strings.Join(mail.To, ";") + | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ import ( | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/docker/distribution" | 	"github.com/docker/distribution" | ||||||
| 	dcontext "github.com/docker/distribution/context" | 	dcontext "github.com/docker/distribution/context" | ||||||
|  | @ -15,9 +14,6 @@ import ( | ||||||
| 	"github.com/opencontainers/go-digest" | 	"github.com/opencontainers/go-digest" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // todo(richardscothern): from cache control header or config file
 |  | ||||||
| const blobTTL = 24 * 7 * time.Hour |  | ||||||
| 
 |  | ||||||
| type proxyBlobStore struct { | type proxyBlobStore struct { | ||||||
| 	localStore     distribution.BlobStore | 	localStore     distribution.BlobStore | ||||||
| 	remoteStore    distribution.BlobService | 	remoteStore    distribution.BlobService | ||||||
|  |  | ||||||
|  | @ -193,7 +193,7 @@ func makeTestEnv(t *testing.T, name string) *testEnv { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func makeBlob(size int) []byte { | func makeBlob(size int) []byte { | ||||||
| 	blob := make([]byte, size, size) | 	blob := make([]byte, size) | ||||||
| 	for i := 0; i < size; i++ { | 	for i := 0; i < size; i++ { | ||||||
| 		blob[i] = byte('A' + rand.Int()%48) | 		blob[i] = byte('A' + rand.Int()%48) | ||||||
| 	} | 	} | ||||||
|  | @ -204,16 +204,6 @@ func init() { | ||||||
| 	rand.Seed(42) | 	rand.Seed(42) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func perm(m []distribution.Descriptor) []distribution.Descriptor { |  | ||||||
| 	for i := 0; i < len(m); i++ { |  | ||||||
| 		j := rand.Intn(i + 1) |  | ||||||
| 		tmp := m[i] |  | ||||||
| 		m[i] = m[j] |  | ||||||
| 		m[j] = tmp |  | ||||||
| 	} |  | ||||||
| 	return m |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func populate(t *testing.T, te *testEnv, blobCount, size, numUnique int) { | func populate(t *testing.T, te *testEnv, blobCount, size, numUnique int) { | ||||||
| 	var inRemote []distribution.Descriptor | 	var inRemote []distribution.Descriptor | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -165,11 +165,10 @@ func populateRepo(ctx context.Context, t *testing.T, repository distribution.Rep | ||||||
| 			t.Fatalf("unexpected error creating test upload: %v", err) | 			t.Fatalf("unexpected error creating test upload: %v", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		rs, ts, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("unexpected error generating test layer file") | 			t.Fatalf("unexpected error generating test layer file") | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(ts) |  | ||||||
| 		if _, err := io.Copy(wr, rs); err != nil { | 		if _, err := io.Copy(wr, rs); err != nil { | ||||||
| 			t.Fatalf("unexpected error copying to upload: %v", err) | 			t.Fatalf("unexpected error copying to upload: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ func (ttles *TTLExpirationScheduler) Start() error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !ttles.stopped { | 	if !ttles.stopped { | ||||||
| 		return fmt.Errorf("Scheduler already started") | 		return fmt.Errorf("scheduler already started") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dcontext.GetLogger(ttles.ctx).Infof("Starting cached object TTL expiration scheduler...") | 	dcontext.GetLogger(ttles.ctx).Infof("Starting cached object TTL expiration scheduler...") | ||||||
|  | @ -126,7 +126,7 @@ func (ttles *TTLExpirationScheduler) Start() error { | ||||||
| 
 | 
 | ||||||
| 	// Start timer for each deserialized entry
 | 	// Start timer for each deserialized entry
 | ||||||
| 	for _, entry := range ttles.entries { | 	for _, entry := range ttles.entries { | ||||||
| 		entry.timer = ttles.startTimer(entry, entry.Expiry.Sub(time.Now())) | 		entry.timer = ttles.startTimer(entry, time.Until(entry.Expiry)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Start a ticker to periodically save the entries index
 | 	// Start a ticker to periodically save the entries index
 | ||||||
|  | @ -164,7 +164,7 @@ func (ttles *TTLExpirationScheduler) add(r reference.Reference, ttl time.Duratio | ||||||
| 		Expiry:    time.Now().Add(ttl), | 		Expiry:    time.Now().Add(ttl), | ||||||
| 		EntryType: eType, | 		EntryType: eType, | ||||||
| 	} | 	} | ||||||
| 	dcontext.GetLogger(ttles.ctx).Infof("Adding new scheduler entry for %s with ttl=%s", entry.Key, entry.Expiry.Sub(time.Now())) | 	dcontext.GetLogger(ttles.ctx).Infof("Adding new scheduler entry for %s with ttl=%s", entry.Key, time.Until(entry.Expiry)) | ||||||
| 	if oldEntry, present := ttles.entries[entry.Key]; present && oldEntry.timer != nil { | 	if oldEntry, present := ttles.entries[entry.Key]; present && oldEntry.timer != nil { | ||||||
| 		oldEntry.timer.Stop() | 		oldEntry.timer.Stop() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -201,7 +201,7 @@ func (registry *Registry) ListenAndServe() error { | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if ok := pool.AppendCertsFromPEM(caPem); !ok { | 				if ok := pool.AppendCertsFromPEM(caPem); !ok { | ||||||
| 					return fmt.Errorf("Could not add CA to pool") | 					return fmt.Errorf("could not add CA to pool") | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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] | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| 	} | 	} | ||||||
|  | @ -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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -27,13 +27,12 @@ func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) { | ||||||
| 	// readseekers for upload later.
 | 	// readseekers for upload later.
 | ||||||
| 	testLayers := map[digest.Digest]io.ReadSeeker{} | 	testLayers := map[digest.Digest]io.ReadSeeker{} | ||||||
| 	for i := 0; i < 2; i++ { | 	for i := 0; i < 2; i++ { | ||||||
| 		rs, ds, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("unexpected error generating test layer file") | 			t.Fatalf("unexpected error generating test layer file") | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(ds) |  | ||||||
| 
 | 
 | ||||||
| 		testLayers[digest.Digest(dgst)] = rs | 		testLayers[dgst] = rs | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// upload the layers to foo/bar
 | 	// upload the layers to foo/bar
 | ||||||
|  |  | ||||||
|  | @ -91,13 +91,12 @@ func testManifestStorage(t *testing.T, schema1Enabled bool, options ...RegistryO | ||||||
| 	// readseekers for upload later.
 | 	// readseekers for upload later.
 | ||||||
| 	testLayers := map[digest.Digest]io.ReadSeeker{} | 	testLayers := map[digest.Digest]io.ReadSeeker{} | ||||||
| 	for i := 0; i < 2; i++ { | 	for i := 0; i < 2; i++ { | ||||||
| 		rs, ds, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("unexpected error generating test layer file") | 			t.Fatalf("unexpected error generating test layer file") | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(ds) |  | ||||||
| 
 | 
 | ||||||
| 		testLayers[digest.Digest(dgst)] = rs | 		testLayers[dgst] = rs | ||||||
| 		m.FSLayers = append(m.FSLayers, schema1.FSLayer{ | 		m.FSLayers = append(m.FSLayers, schema1.FSLayer{ | ||||||
| 			BlobSum: dgst, | 			BlobSum: dgst, | ||||||
| 		}) | 		}) | ||||||
|  | @ -414,11 +413,10 @@ func testOCIManifestStorage(t *testing.T, testname string, includeMediaTypes boo | ||||||
| 
 | 
 | ||||||
| 	// Add some layers
 | 	// Add some layers
 | ||||||
| 	for i := 0; i < 2; i++ { | 	for i := 0; i < 2; i++ { | ||||||
| 		rs, ds, err := testutil.CreateRandomTarFile() | 		rs, dgst, err := testutil.CreateRandomTarFile() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("%s: unexpected error generating test layer file", testname) | 			t.Fatalf("%s: unexpected error generating test layer file", testname) | ||||||
| 		} | 		} | ||||||
| 		dgst := digest.Digest(ds) |  | ||||||
| 
 | 
 | ||||||
| 		wr, err := env.repository.Blobs(env.ctx).Create(env.ctx) | 		wr, err := env.repository.Blobs(env.ctx).Create(env.ctx) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ func TestPathMapper(t *testing.T) { | ||||||
| 	for _, testcase := range []struct { | 	for _, testcase := range []struct { | ||||||
| 		spec     pathSpec | 		spec     pathSpec | ||||||
| 		expected string | 		expected string | ||||||
| 		err      error |  | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			spec: manifestRevisionPathSpec{ | 			spec: manifestRevisionPathSpec{ | ||||||
|  |  | ||||||
|  | @ -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{}) | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ func TestPurgeOnlyUploads(t *testing.T) { | ||||||
| 		t.Fatalf(err.Error()) | 		t.Fatalf(err.Error()) | ||||||
| 	} | 	} | ||||||
| 	nonUploadPath := strings.Replace(dataPath, "_upload", "_important", -1) | 	nonUploadPath := strings.Replace(dataPath, "_upload", "_important", -1) | ||||||
| 	if strings.Index(nonUploadPath, "_upload") != -1 { | 	if strings.Contains(nonUploadPath, "_upload") { | ||||||
| 		t.Fatalf("Non-upload path not created correctly") | 		t.Fatalf("Non-upload path not created correctly") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -132,7 +132,7 @@ func TestPurgeOnlyUploads(t *testing.T) { | ||||||
| 		t.Error("Unexpected errors", errs) | 		t.Error("Unexpected errors", errs) | ||||||
| 	} | 	} | ||||||
| 	for _, file := range deleted { | 	for _, file := range deleted { | ||||||
| 		if strings.Index(file, "_upload") == -1 { | 		if !strings.Contains(file, "_upload") { | ||||||
| 			t.Errorf("Non-upload file deleted") | 			t.Errorf("Non-upload file deleted") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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.
 | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -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 |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue