Merge pull request #2639 from andrew-leung/manifesteventlayers
Add configurable layers in manifest eventsmaster
						commit
						b12bd4004a
					
				|  | @ -29,6 +29,8 @@ redis: | ||||||
|   readtimeout: 10ms |   readtimeout: 10ms | ||||||
|   writetimeout: 10ms |   writetimeout: 10ms | ||||||
| notifications: | notifications: | ||||||
|  |     events: | ||||||
|  |         includereferences: true | ||||||
|     endpoints: |     endpoints: | ||||||
|         - name: local-8082 |         - name: local-8082 | ||||||
|           url: http://localhost:5003/callback |           url: http://localhost:5003/callback | ||||||
|  |  | ||||||
|  | @ -47,6 +47,8 @@ redis: | ||||||
|   readtimeout: 10ms |   readtimeout: 10ms | ||||||
|   writetimeout: 10ms |   writetimeout: 10ms | ||||||
| notifications: | notifications: | ||||||
|  |     events: | ||||||
|  |         includereferences: true | ||||||
|     endpoints: |     endpoints: | ||||||
|         - name: local-5003 |         - name: local-5003 | ||||||
|           url: http://localhost:5003/callback |           url: http://localhost:5003/callback | ||||||
|  |  | ||||||
|  | @ -551,6 +551,8 @@ func (auth Auth) MarshalYAML() (interface{}, error) { | ||||||
| 
 | 
 | ||||||
| // Notifications configures multiple http endpoints.
 | // Notifications configures multiple http endpoints.
 | ||||||
| type Notifications struct { | type Notifications struct { | ||||||
|  | 	// EventConfig is the configuration for the event format that is sent to each Endpoint.
 | ||||||
|  | 	EventConfig Events `yaml:"events,omitempty"` | ||||||
| 	// Endpoints is a list of http configurations for endpoints that
 | 	// Endpoints is a list of http configurations for endpoints that
 | ||||||
| 	// respond to webhook notifications. In the future, we may allow other
 | 	// respond to webhook notifications. In the future, we may allow other
 | ||||||
| 	// kinds of endpoints, such as external queues.
 | 	// kinds of endpoints, such as external queues.
 | ||||||
|  | @ -571,6 +573,11 @@ type Endpoint struct { | ||||||
| 	Ignore            Ignore        `yaml:"ignore"`            // ignore event types
 | 	Ignore            Ignore        `yaml:"ignore"`            // ignore event types
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Events configures notification events.
 | ||||||
|  | type Events struct { | ||||||
|  | 	IncludeReferences bool `yaml:"includereferences"` // include reference data in manifest events
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| //Ignore configures mediaTypes and actions of the event, that it won't be propagated
 | //Ignore configures mediaTypes and actions of the event, that it won't be propagated
 | ||||||
| type Ignore struct { | type Ignore struct { | ||||||
| 	MediaTypes []string `yaml:"mediatypes"` // target media types to ignore
 | 	MediaTypes []string `yaml:"mediatypes"` // target media types to ignore
 | ||||||
|  |  | ||||||
|  | @ -227,6 +227,8 @@ http: | ||||||
|   http2: |   http2: | ||||||
|     disabled: false |     disabled: false | ||||||
| notifications: | notifications: | ||||||
|  |   events: | ||||||
|  |     includereferences: true | ||||||
|   endpoints: |   endpoints: | ||||||
|     - name: alistener |     - name: alistener | ||||||
|       disabled: false |       disabled: false | ||||||
|  | @ -857,6 +859,8 @@ settings for the registry. | ||||||
| 
 | 
 | ||||||
| ```none | ```none | ||||||
| notifications: | notifications: | ||||||
|  |   events: | ||||||
|  |     includereferences: true | ||||||
|   endpoints: |   endpoints: | ||||||
|     - name: alistener |     - name: alistener | ||||||
|       disabled: false |       disabled: false | ||||||
|  | @ -900,6 +904,13 @@ accept event notifications. | ||||||
| | `mediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. | | | `mediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. | | ||||||
| | `actions`   |no| A list of actions to ignore. Events with these actions are not published to the endpoint. | | | `actions`   |no| A list of actions to ignore. Events with these actions are not published to the endpoint. | | ||||||
| 
 | 
 | ||||||
|  | ### `events` | ||||||
|  | 
 | ||||||
|  | The `events` structure configures the information provided in event notifications. | ||||||
|  | 
 | ||||||
|  | | Parameter | Required | Description                                           | | ||||||
|  | |-----------|----------|-------------------------------------------------------| | ||||||
|  | | `includereferences` | no | If `true`, include reference information in manifest events. | | ||||||
| 
 | 
 | ||||||
| ## `redis` | ## `redis` | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ type Manifest struct { | ||||||
| 	Layers []distribution.Descriptor `json:"layers"` | 	Layers []distribution.Descriptor `json:"layers"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // References returnes the descriptors of this manifests references.
 | // References returns the descriptors of this manifests references.
 | ||||||
| func (m Manifest) References() []distribution.Descriptor { | func (m Manifest) References() []distribution.Descriptor { | ||||||
| 	references := make([]distribution.Descriptor, 0, 1+len(m.Layers)) | 	references := make([]distribution.Descriptor, 0, 1+len(m.Layers)) | ||||||
| 	references = append(references, m.Config) | 	references = append(references, m.Config) | ||||||
|  |  | ||||||
|  | @ -12,11 +12,12 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type bridge struct { | type bridge struct { | ||||||
| 	ub      URLBuilder | 	ub                URLBuilder | ||||||
| 	actor   ActorRecord | 	includeReferences bool | ||||||
| 	source  SourceRecord | 	actor             ActorRecord | ||||||
| 	request RequestRecord | 	source            SourceRecord | ||||||
| 	sink    Sink | 	request           RequestRecord | ||||||
|  | 	sink              Sink | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var _ Listener = &bridge{} | var _ Listener = &bridge{} | ||||||
|  | @ -31,13 +32,14 @@ type URLBuilder interface { | ||||||
| // using the actor and source. Any urls populated in the events created by
 | // using the actor and source. Any urls populated in the events created by
 | ||||||
| // this bridge will be created using the URLBuilder.
 | // this bridge will be created using the URLBuilder.
 | ||||||
| // TODO(stevvooe): Update this to simply take a context.Context object.
 | // TODO(stevvooe): Update this to simply take a context.Context object.
 | ||||||
| func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request RequestRecord, sink Sink) Listener { | func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request RequestRecord, sink Sink, includeReferences bool) Listener { | ||||||
| 	return &bridge{ | 	return &bridge{ | ||||||
| 		ub:      ub, | 		ub:                ub, | ||||||
| 		actor:   actor, | 		includeReferences: includeReferences, | ||||||
| 		source:  source, | 		actor:             actor, | ||||||
| 		request: request, | 		source:            source, | ||||||
| 		sink:    sink, | 		request:           request, | ||||||
|  | 		sink:              sink, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -150,7 +152,7 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Ensure we have the canonical manifest descriptor here
 | 	// Ensure we have the canonical manifest descriptor here
 | ||||||
| 	_, desc, err := distribution.UnmarshalManifest(mt, p) | 	manifest, desc, err := distribution.UnmarshalManifest(mt, p) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -159,6 +161,9 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis | ||||||
| 	event.Target.Length = desc.Size | 	event.Target.Length = desc.Size | ||||||
| 	event.Target.Size = desc.Size | 	event.Target.Size = desc.Size | ||||||
| 	event.Target.Digest = desc.Digest | 	event.Target.Digest = desc.Digest | ||||||
|  | 	if b.includeReferences { | ||||||
|  | 		event.Target.References = append(event.Target.References, manifest.References()...) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ref, err := reference.WithDigest(repo, event.Target.Digest) | 	ref, err := reference.WithDigest(repo, event.Target.Digest) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -26,9 +26,18 @@ var ( | ||||||
| 		Name: "test", | 		Name: "test", | ||||||
| 	} | 	} | ||||||
| 	request = RequestRecord{} | 	request = RequestRecord{} | ||||||
| 	m       = schema1.Manifest{ | 	layers  = []schema1.FSLayer{ | ||||||
| 		Name: repo, | 		{ | ||||||
| 		Tag:  "latest", | 			BlobSum: "asdf", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			BlobSum: "qwer", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	m = schema1.Manifest{ | ||||||
|  | 		Name:     repo, | ||||||
|  | 		Tag:      "latest", | ||||||
|  | 		FSLayers: layers, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sm      *schema1.SignedManifest | 	sm      *schema1.SignedManifest | ||||||
|  | @ -150,7 +159,7 @@ func createTestEnv(t *testing.T, fn testSinkFn) Listener { | ||||||
| 	payload = sm.Canonical | 	payload = sm.Canonical | ||||||
| 	dgst = digest.FromBytes(payload) | 	dgst = digest.FromBytes(payload) | ||||||
| 
 | 
 | ||||||
| 	return NewBridge(ub, source, actor, request, fn) | 	return NewBridge(ub, source, actor, request, fn, true) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func checkDeleted(t *testing.T, action string, events ...Event) { | func checkDeleted(t *testing.T, action string, events ...Event) { | ||||||
|  | @ -195,6 +204,15 @@ func checkCommonManifest(t *testing.T, action string, events ...Event) { | ||||||
| 	if event.Target.URL != u { | 	if event.Target.URL != u { | ||||||
| 		t.Fatalf("incorrect url passed: \n%q != \n%q", event.Target.URL, u) | 		t.Fatalf("incorrect url passed: \n%q != \n%q", event.Target.URL, u) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(event.Target.References) != len(layers) { | ||||||
|  | 		t.Fatalf("unexpected number of references %v != %v", len(event.Target.References), len(layers)) | ||||||
|  | 	} | ||||||
|  | 	for i, targetReference := range event.Target.References { | ||||||
|  | 		if targetReference.Digest != layers[i].BlobSum { | ||||||
|  | 			t.Fatalf("unexpected reference: %q != %q", targetReference.Digest, layers[i].BlobSum) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func checkCommon(t *testing.T, events ...Event) { | func checkCommon(t *testing.T, events ...Event) { | ||||||
|  |  | ||||||
|  | @ -71,6 +71,9 @@ type Event struct { | ||||||
| 
 | 
 | ||||||
| 		// Tag provides the tag
 | 		// Tag provides the tag
 | ||||||
| 		Tag string `json:"tag,omitempty"` | 		Tag string `json:"tag,omitempty"` | ||||||
|  | 
 | ||||||
|  | 		// References provides the references descriptors.
 | ||||||
|  | 		References []distribution.Descriptor `json:"references,omitempty"` | ||||||
| 	} `json:"target,omitempty"` | 	} `json:"target,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// Request covers the request that generated the event.
 | 	// Request covers the request that generated the event.
 | ||||||
|  |  | ||||||
|  | @ -880,7 +880,7 @@ func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listene | ||||||
| 	} | 	} | ||||||
| 	request := notifications.NewRequestRecord(dcontext.GetRequestID(ctx), r) | 	request := notifications.NewRequestRecord(dcontext.GetRequestID(ctx), r) | ||||||
| 
 | 
 | ||||||
| 	return notifications.NewBridge(ctx.urlBuilder, app.events.source, actor, request, app.events.sink) | 	return notifications.NewBridge(ctx.urlBuilder, app.events.source, actor, request, app.events.sink, app.Config.Notifications.EventConfig.IncludeReferences) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // nameRequired returns true if the route requires a name.
 | // nameRequired returns true if the route requires a name.
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue