Add configurable layers in manifest events
Signed-off-by: Andrew Leung <anwleung@gmail.com>master
							parent
							
								
									749f6afb45
								
							
						
					
					
						commit
						276fdce3d9
					
				|  | @ -29,6 +29,8 @@ redis: | |||
|   readtimeout: 10ms | ||||
|   writetimeout: 10ms | ||||
| notifications: | ||||
|     events: | ||||
|         manifestlayers: true | ||||
|     endpoints: | ||||
|         - name: local-8082 | ||||
|           url: http://localhost:5003/callback | ||||
|  |  | |||
|  | @ -47,6 +47,8 @@ redis: | |||
|   readtimeout: 10ms | ||||
|   writetimeout: 10ms | ||||
| notifications: | ||||
|     events: | ||||
|         manifestlayers: true | ||||
|     endpoints: | ||||
|         - name: local-5003 | ||||
|           url: http://localhost:5003/callback | ||||
|  |  | |||
|  | @ -544,6 +544,8 @@ func (auth Auth) MarshalYAML() (interface{}, error) { | |||
| 
 | ||||
| // Notifications configures multiple http endpoints.
 | ||||
| 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
 | ||||
| 	// respond to webhook notifications. In the future, we may allow other
 | ||||
| 	// kinds of endpoints, such as external queues.
 | ||||
|  | @ -564,6 +566,11 @@ type Endpoint struct { | |||
| 	Ignore            Ignore        `yaml:"ignore"`            // ignore event types
 | ||||
| } | ||||
| 
 | ||||
| // Events configures notification events.
 | ||||
| type Events struct { | ||||
| 	ManifestLayers bool `yaml:"manifestlayers"` // include layer data in manifest events
 | ||||
| } | ||||
| 
 | ||||
| //Ignore configures mediaTypes and actions of the event, that it won't be propagated
 | ||||
| type Ignore struct { | ||||
| 	MediaTypes []string `yaml:"mediatypes"` // target media types to ignore
 | ||||
|  |  | |||
|  | @ -226,6 +226,8 @@ http: | |||
|   http2: | ||||
|     disabled: false | ||||
| notifications: | ||||
|   events: | ||||
|     manifestlayers: true | ||||
|   endpoints: | ||||
|     - name: alistener | ||||
|       disabled: false | ||||
|  | @ -853,6 +855,8 @@ settings for the registry. | |||
| 
 | ||||
| ```none | ||||
| notifications: | ||||
|   events: | ||||
|     manifestlayers: true | ||||
|   endpoints: | ||||
|     - name: alistener | ||||
|       disabled: false | ||||
|  | @ -896,6 +900,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. | | ||||
| | `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                                           | | ||||
| |-----------|----------|-------------------------------------------------------| | ||||
| | `manifestlayers` | no | If `true`, include layer information in manifest events. | | ||||
| 
 | ||||
| ## `redis` | ||||
| 
 | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ type Manifest struct { | |||
| 	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 { | ||||
| 	references := make([]distribution.Descriptor, 0, 1+len(m.Layers)) | ||||
| 	references = append(references, m.Config) | ||||
|  |  | |||
|  | @ -12,11 +12,12 @@ import ( | |||
| ) | ||||
| 
 | ||||
| type bridge struct { | ||||
| 	ub      URLBuilder | ||||
| 	actor   ActorRecord | ||||
| 	source  SourceRecord | ||||
| 	request RequestRecord | ||||
| 	sink    Sink | ||||
| 	ub             URLBuilder | ||||
| 	manfiestLayers bool | ||||
| 	actor          ActorRecord | ||||
| 	source         SourceRecord | ||||
| 	request        RequestRecord | ||||
| 	sink           Sink | ||||
| } | ||||
| 
 | ||||
| var _ Listener = &bridge{} | ||||
|  | @ -31,13 +32,14 @@ type URLBuilder interface { | |||
| // using the actor and source. Any urls populated in the events created by
 | ||||
| // this bridge will be created using the URLBuilder.
 | ||||
| // 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, manifestLayers bool) Listener { | ||||
| 	return &bridge{ | ||||
| 		ub:      ub, | ||||
| 		actor:   actor, | ||||
| 		source:  source, | ||||
| 		request: request, | ||||
| 		sink:    sink, | ||||
| 		ub:             ub, | ||||
| 		manfiestLayers: manifestLayers, | ||||
| 		actor:          actor, | ||||
| 		source:         source, | ||||
| 		request:        request, | ||||
| 		sink:           sink, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -135,7 +137,7 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis | |||
| 	} | ||||
| 
 | ||||
| 	// Ensure we have the canonical manifest descriptor here
 | ||||
| 	_, desc, err := distribution.UnmarshalManifest(mt, p) | ||||
| 	manifest, desc, err := distribution.UnmarshalManifest(mt, p) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -144,6 +146,9 @@ func (b *bridge) createManifestEvent(action string, repo reference.Named, sm dis | |||
| 	event.Target.Length = desc.Size | ||||
| 	event.Target.Size = desc.Size | ||||
| 	event.Target.Digest = desc.Digest | ||||
| 	if b.manfiestLayers { | ||||
| 		event.Target.Layers = append(event.Target.Layers, manifest.References()...) | ||||
| 	} | ||||
| 
 | ||||
| 	ref, err := reference.WithDigest(repo, event.Target.Digest) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -26,9 +26,18 @@ var ( | |||
| 		Name: "test", | ||||
| 	} | ||||
| 	request = RequestRecord{} | ||||
| 	m       = schema1.Manifest{ | ||||
| 		Name: repo, | ||||
| 		Tag:  "latest", | ||||
| 	layers  = []schema1.FSLayer{ | ||||
| 		{ | ||||
| 			BlobSum: "asdf", | ||||
| 		}, | ||||
| 		{ | ||||
| 			BlobSum: "qwer", | ||||
| 		}, | ||||
| 	} | ||||
| 	m = schema1.Manifest{ | ||||
| 		Name:     repo, | ||||
| 		Tag:      "latest", | ||||
| 		FSLayers: layers, | ||||
| 	} | ||||
| 
 | ||||
| 	sm      *schema1.SignedManifest | ||||
|  | @ -120,7 +129,7 @@ func createTestEnv(t *testing.T, fn testSinkFn) Listener { | |||
| 	payload = sm.Canonical | ||||
| 	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) { | ||||
|  | @ -170,6 +179,15 @@ func checkCommonManifest(t *testing.T, action string, events ...Event) { | |||
| 	if event.Target.URL != u { | ||||
| 		t.Fatalf("incorrect url passed: \n%q != \n%q", event.Target.URL, u) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(event.Target.Layers) != len(layers) { | ||||
| 		t.Fatalf("unexpected number of layers %v != %v", len(event.Target.Layers), len(layers)) | ||||
| 	} | ||||
| 	for i, layer := range event.Target.Layers { | ||||
| 		if layer.Digest != layers[i].BlobSum { | ||||
| 			t.Fatalf("unexpected layer: %q != %q", layer.Digest, layers[i].BlobSum) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func checkCommon(t *testing.T, events ...Event) { | ||||
|  |  | |||
|  | @ -71,6 +71,9 @@ type Event struct { | |||
| 
 | ||||
| 		// Tag provides the tag
 | ||||
| 		Tag string `json:"tag,omitempty"` | ||||
| 
 | ||||
| 		// Layers provides the layers descriptors.
 | ||||
| 		Layers []distribution.Descriptor `json:"layers,omitempty"` | ||||
| 	} `json:"target,omitempty"` | ||||
| 
 | ||||
| 	// Request covers the request that generated the event.
 | ||||
|  |  | |||
|  | @ -869,7 +869,7 @@ func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listene | |||
| 	} | ||||
| 	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.ManifestLayers) | ||||
| } | ||||
| 
 | ||||
| // nameRequired returns true if the route requires a name.
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue