Merge pull request #239 from jlhawn/event_target_update
notifications: update notification event Target fieldsmaster
						commit
						f0ccdd448f
					
				|  | @ -65,37 +65,38 @@ func (b *bridge) ManifestDeleted(repo distribution.Repository, sm *manifest.Sign | |||
| } | ||||
| 
 | ||||
| func (b *bridge) LayerPushed(repo distribution.Repository, layer distribution.Layer) error { | ||||
| 	return b.createLayerEventAndWrite(EventActionPush, repo, layer.Digest()) | ||||
| 	return b.createLayerEventAndWrite(EventActionPush, repo, layer) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) LayerPulled(repo distribution.Repository, layer distribution.Layer) error { | ||||
| 	return b.createLayerEventAndWrite(EventActionPull, repo, layer.Digest()) | ||||
| 	return b.createLayerEventAndWrite(EventActionPull, repo, layer) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) LayerDeleted(repo distribution.Repository, layer distribution.Layer) error { | ||||
| 	return b.createLayerEventAndWrite(EventActionDelete, repo, layer.Digest()) | ||||
| 	return b.createLayerEventAndWrite(EventActionDelete, repo, layer) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) createManifestEventAndWrite(action string, repo distribution.Repository, sm *manifest.SignedManifest) error { | ||||
| 	event, err := b.createManifestEvent(action, repo, sm) | ||||
| 	manifestEvent, err := b.createManifestEvent(action, repo, sm) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return b.sink.Write(*event) | ||||
| 	return b.sink.Write(*manifestEvent) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) createManifestEvent(action string, repo distribution.Repository, sm *manifest.SignedManifest) (*Event, error) { | ||||
| 	event := b.createEvent(action) | ||||
| 	event.Target.Type = EventTargetTypeManifest | ||||
| 	event.Target.Name = repo.Name() | ||||
| 	event.Target.Tag = sm.Tag | ||||
| 	event.Target.MediaType = manifest.ManifestMediaType | ||||
| 	event.Target.Repository = repo.Name() | ||||
| 
 | ||||
| 	p, err := sm.Payload() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	event.Target.Length = int64(len(p)) | ||||
| 
 | ||||
| 	event.Target.Digest, err = digest.FromBytes(p) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
|  | @ -111,8 +112,8 @@ func (b *bridge) createManifestEvent(action string, repo distribution.Repository | |||
| 	return event, nil | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) createLayerEventAndWrite(action string, repo distribution.Repository, dgst digest.Digest) error { | ||||
| 	event, err := b.createLayerEvent(action, repo, dgst) | ||||
| func (b *bridge) createLayerEventAndWrite(action string, repo distribution.Repository, layer distribution.Layer) error { | ||||
| 	event, err := b.createLayerEvent(action, repo, layer) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -120,10 +121,14 @@ func (b *bridge) createLayerEventAndWrite(action string, repo distribution.Repos | |||
| 	return b.sink.Write(*event) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) createLayerEvent(action string, repo distribution.Repository, dgst digest.Digest) (*Event, error) { | ||||
| func (b *bridge) createLayerEvent(action string, repo distribution.Repository, layer distribution.Layer) (*Event, error) { | ||||
| 	event := b.createEvent(action) | ||||
| 	event.Target.Type = EventTargetTypeBlob | ||||
| 	event.Target.Name = repo.Name() | ||||
| 	event.Target.MediaType = layerMediaType | ||||
| 	event.Target.Repository = repo.Name() | ||||
| 
 | ||||
| 	event.Target.Length = layer.Length() | ||||
| 
 | ||||
| 	dgst := layer.Digest() | ||||
| 	event.Target.Digest = dgst | ||||
| 
 | ||||
| 	var err error | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/docker/distribution/digest" | ||||
| 	"github.com/docker/distribution" | ||||
| ) | ||||
| 
 | ||||
| // EventAction constants used in action field of Event.
 | ||||
|  | @ -14,17 +14,16 @@ const ( | |||
| 	EventActionDelete = "delete" | ||||
| ) | ||||
| 
 | ||||
| // EventTargetType constants used in Target section of Event.
 | ||||
| const ( | ||||
| 	EventTargetTypeManifest = "manifest" | ||||
| 	EventTargetTypeBlob     = "blob" | ||||
| 	// EventsMediaType is the mediatype for the json event envelope. If the
 | ||||
| 	// Event, ActorRecord, SourceRecord or Envelope structs change, the version
 | ||||
| 	// number should be incremented.
 | ||||
| 	EventsMediaType = "application/vnd.docker.distribution.events.v1+json" | ||||
| 	// LayerMediaType is the media type for image rootfs diffs (aka "layers")
 | ||||
| 	// used by Docker. We don't expect this to change for quite a while.
 | ||||
| 	layerMediaType = "application/vnd.docker.container.image.rootfs.diff+x-gtar" | ||||
| ) | ||||
| 
 | ||||
| // EventsMediaType is the mediatype for the json event envelope. If the Event,
 | ||||
| // ActorRecord, SourceRecord or Envelope structs change, the version number
 | ||||
| // should be incremented.
 | ||||
| const EventsMediaType = "application/vnd.docker.distribution.events.v1+json" | ||||
| 
 | ||||
| // Envelope defines the fields of a json event envelope message that can hold
 | ||||
| // one or more events.
 | ||||
| type Envelope struct { | ||||
|  | @ -51,19 +50,14 @@ type Event struct { | |||
| 
 | ||||
| 	// Target uniquely describes the target of the event.
 | ||||
| 	Target struct { | ||||
| 		// Type should be "manifest" or "blob"
 | ||||
| 		Type string `json:"type,omitempty"` | ||||
| 		// TODO(stevvooe): Use http.DetectContentType for layers, maybe.
 | ||||
| 
 | ||||
| 		// Name identifies the named repository.
 | ||||
| 		Name string `json:"name,omitempty"` | ||||
| 		distribution.Descriptor | ||||
| 
 | ||||
| 		// Digest should identify the object in the repository.
 | ||||
| 		Digest digest.Digest `json:"digest,omitempty"` | ||||
| 		// Repository identifies the named repository.
 | ||||
| 		Repository string `json:"repository,omitempty"` | ||||
| 
 | ||||
| 		// Tag is present if the operation involved a tagged manifest.
 | ||||
| 		Tag string `json:"tag,omitempty"` | ||||
| 
 | ||||
| 		// URL provides a link to the content on the relevant repository instance.
 | ||||
| 		// URL provides a direct link to the content.
 | ||||
| 		URL string `json:"url,omitempty"` | ||||
| 	} `json:"target,omitempty"` | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ import ( | |||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/docker/distribution/manifest" | ||||
| ) | ||||
| 
 | ||||
| // TestEventJSONFormat provides silly test to detect if the event format or
 | ||||
|  | @ -19,10 +21,10 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | |||
|          "timestamp": "2006-01-02T15:04:05Z", | ||||
|          "action": "push", | ||||
|          "target": { | ||||
|             "type": "manifest", | ||||
|             "name": "library/test", | ||||
|             "mediaType": "application/vnd.docker.distribution.manifest.v1+json", | ||||
|             "length": 1, | ||||
|             "digest": "sha256:0123456789abcdef0", | ||||
|             "tag": "latest", | ||||
|             "repository": "library/test", | ||||
|             "url": "http://example.com/v2/library/test/manifests/latest" | ||||
|          }, | ||||
|          "request": { | ||||
|  | @ -44,9 +46,10 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | |||
|          "timestamp": "2006-01-02T15:04:05Z", | ||||
|          "action": "push", | ||||
|          "target": { | ||||
|             "type": "blob", | ||||
|             "name": "library/test", | ||||
|             "mediaType": "application/vnd.docker.container.image.rootfs.diff+x-gtar", | ||||
|             "length": 2, | ||||
|             "digest": "tarsum.v2+sha256:0123456789abcdef1", | ||||
|             "repository": "library/test", | ||||
|             "url": "http://example.com/v2/library/test/manifests/latest" | ||||
|          }, | ||||
|          "request": { | ||||
|  | @ -68,9 +71,10 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | |||
|          "timestamp": "2006-01-02T15:04:05Z", | ||||
|          "action": "push", | ||||
|          "target": { | ||||
|             "type": "blob", | ||||
|             "name": "library/test", | ||||
|             "mediaType": "application/vnd.docker.container.image.rootfs.diff+x-gtar", | ||||
|             "length": 3, | ||||
|             "digest": "tarsum.v2+sha256:0123456789abcdef2", | ||||
|             "repository": "library/test", | ||||
|             "url": "http://example.com/v2/library/test/manifests/latest" | ||||
|          }, | ||||
|          "request": { | ||||
|  | @ -97,7 +101,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	var prototype Event | ||||
| 	prototype.Action = "push" | ||||
| 	prototype.Action = EventActionPush | ||||
| 	prototype.Timestamp = tm | ||||
| 	prototype.Actor.Name = "test-actor" | ||||
| 	prototype.Request.ID = "asdfasdf" | ||||
|  | @ -111,25 +115,27 @@ func TestEventEnvelopeJSONFormat(t *testing.T) { | |||
| 	manifestPush = prototype | ||||
| 	manifestPush.ID = "asdf-asdf-asdf-asdf-0" | ||||
| 	manifestPush.Target.Digest = "sha256:0123456789abcdef0" | ||||
| 	manifestPush.Target.Type = EventTargetTypeManifest | ||||
| 	manifestPush.Target.Name = "library/test" | ||||
| 	manifestPush.Target.Tag = "latest" | ||||
| 	manifestPush.Target.Length = int64(1) | ||||
| 	manifestPush.Target.MediaType = manifest.ManifestMediaType | ||||
| 	manifestPush.Target.Repository = "library/test" | ||||
| 	manifestPush.Target.URL = "http://example.com/v2/library/test/manifests/latest" | ||||
| 
 | ||||
| 	var layerPush0 Event | ||||
| 	layerPush0 = prototype | ||||
| 	layerPush0.ID = "asdf-asdf-asdf-asdf-1" | ||||
| 	layerPush0.Target.Digest = "tarsum.v2+sha256:0123456789abcdef1" | ||||
| 	layerPush0.Target.Type = EventTargetTypeBlob | ||||
| 	layerPush0.Target.Name = "library/test" | ||||
| 	layerPush0.Target.Length = 2 | ||||
| 	layerPush0.Target.MediaType = layerMediaType | ||||
| 	layerPush0.Target.Repository = "library/test" | ||||
| 	layerPush0.Target.URL = "http://example.com/v2/library/test/manifests/latest" | ||||
| 
 | ||||
| 	var layerPush1 Event | ||||
| 	layerPush1 = prototype | ||||
| 	layerPush1.ID = "asdf-asdf-asdf-asdf-2" | ||||
| 	layerPush1.Target.Digest = "tarsum.v2+sha256:0123456789abcdef2" | ||||
| 	layerPush1.Target.Type = EventTargetTypeBlob | ||||
| 	layerPush1.Target.Name = "library/test" | ||||
| 	layerPush1.Target.Length = 3 | ||||
| 	layerPush1.Target.MediaType = layerMediaType | ||||
| 	layerPush1.Target.Repository = "library/test" | ||||
| 	layerPush1.Target.URL = "http://example.com/v2/library/test/manifests/latest" | ||||
| 
 | ||||
| 	var envelope Envelope | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ import ( | |||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/docker/distribution/manifest" | ||||
| ) | ||||
| 
 | ||||
| // TestHTTPSink mocks out an http endpoint and notifies it under a couple of
 | ||||
|  | @ -73,14 +75,14 @@ func TestHTTPSink(t *testing.T) { | |||
| 		{ | ||||
| 			statusCode: http.StatusOK, | ||||
| 			events: []Event{ | ||||
| 				createTestEvent("push", "library/test", "manifest")}, | ||||
| 				createTestEvent("push", "library/test", manifest.ManifestMediaType)}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			statusCode: http.StatusOK, | ||||
| 			events: []Event{ | ||||
| 				createTestEvent("push", "library/test", "manifest"), | ||||
| 				createTestEvent("push", "library/test", "layer"), | ||||
| 				createTestEvent("push", "library/test", "layer"), | ||||
| 				createTestEvent("push", "library/test", manifest.ManifestMediaType), | ||||
| 				createTestEvent("push", "library/test", layerMediaType), | ||||
| 				createTestEvent("push", "library/test", layerMediaType), | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
|  | @ -148,8 +150,8 @@ func TestHTTPSink(t *testing.T) { | |||
| func createTestEvent(action, repo, typ string) Event { | ||||
| 	event := createEvent(action) | ||||
| 
 | ||||
| 	event.Target.Type = typ | ||||
| 	event.Target.Name = repo | ||||
| 	event.Target.MediaType = typ | ||||
| 	event.Target.Repository = repo | ||||
| 
 | ||||
| 	return *event | ||||
| } | ||||
|  |  | |||
							
								
								
									
										27
									
								
								registry.go
								
								
								
								
							
							
						
						
									
										27
									
								
								registry.go
								
								
								
								
							|  | @ -98,10 +98,12 @@ type Layer interface { | |||
| 	io.ReadSeeker | ||||
| 	io.Closer | ||||
| 
 | ||||
| 	// Digest returns the unique digest of the blob, which is the tarsum for
 | ||||
| 	// layers.
 | ||||
| 	// Digest returns the unique digest of the blob.
 | ||||
| 	Digest() digest.Digest | ||||
| 
 | ||||
| 	// Length returns the length in bytes of the blob.
 | ||||
| 	Length() int64 | ||||
| 
 | ||||
| 	// CreatedAt returns the time this layer was created.
 | ||||
| 	CreatedAt() time.Time | ||||
| } | ||||
|  | @ -137,3 +139,24 @@ type SignatureService interface { | |||
| 	// Put stores the signature for the provided digest.
 | ||||
| 	Put(dgst digest.Digest, signatures ...[]byte) error | ||||
| } | ||||
| 
 | ||||
| // Descriptor describes targeted content. Used in conjunction with a blob
 | ||||
| // store, a descriptor can be used to fetch, store and target any kind of
 | ||||
| // blob. The struct also describes the wire protocol format. Fields should
 | ||||
| // only be added but never changed.
 | ||||
| type Descriptor struct { | ||||
| 	// MediaType describe the type of the content. All text based formats are
 | ||||
| 	// encoded as utf-8.
 | ||||
| 	MediaType string `json:"mediaType,omitempty"` | ||||
| 
 | ||||
| 	// Length in bytes of content.
 | ||||
| 	Length int64 `json:"length,omitempty"` | ||||
| 
 | ||||
| 	// Digest uniquely identifies the content. A byte stream can be verified
 | ||||
| 	// against against this digest.
 | ||||
| 	Digest digest.Digest `json:"digest,omitempty"` | ||||
| 
 | ||||
| 	// NOTE: Before adding a field here, please ensure that all
 | ||||
| 	// other options have been exhausted. Much of the type relationships
 | ||||
| 	// depend on the simplicity of this type.
 | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,10 @@ func (lrs *layerReader) Digest() digest.Digest { | |||
| 	return lrs.digest | ||||
| } | ||||
| 
 | ||||
| func (lrs *layerReader) Length() int64 { | ||||
| 	return lrs.size | ||||
| } | ||||
| 
 | ||||
| func (lrs *layerReader) CreatedAt() time.Time { | ||||
| 	return lrs.modtime | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue