Merge pull request #239 from jlhawn/event_target_update

notifications: update notification event Target fields
This commit is contained in:
Stephen Day 2015-03-06 16:45:06 -08:00
commit f0ccdd448f
6 changed files with 89 additions and 55 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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