Added ignore event typs into notifications
Signed-off-by: elsanli(李楠) <elsanli@tencent.com>master
							parent
							
								
									5cb406d511
								
							
						
					
					
						commit
						fc1d3647c6
					
				|  | @ -552,6 +552,13 @@ type Endpoint struct { | ||||||
| 	Threshold         int           `yaml:"threshold"`         // circuit breaker threshold before backing off on failure
 | 	Threshold         int           `yaml:"threshold"`         // circuit breaker threshold before backing off on failure
 | ||||||
| 	Backoff           time.Duration `yaml:"backoff"`           // backoff duration
 | 	Backoff           time.Duration `yaml:"backoff"`           // backoff duration
 | ||||||
| 	IgnoredMediaTypes []string      `yaml:"ignoredmediatypes"` // target media types to ignore
 | 	IgnoredMediaTypes []string      `yaml:"ignoredmediatypes"` // target media types to ignore
 | ||||||
|  | 	Ignore            Ignore        `yaml:"ignore"`            // ignore event types
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //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
 | ||||||
|  | 	Actions    []string `yaml:"actions"`    // ignore action types
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Reporting defines error reporting methods.
 | // Reporting defines error reporting methods.
 | ||||||
|  |  | ||||||
|  | @ -63,6 +63,10 @@ var configStruct = Configuration{ | ||||||
| 					"Authorization": []string{"Bearer <example>"}, | 					"Authorization": []string{"Bearer <example>"}, | ||||||
| 				}, | 				}, | ||||||
| 				IgnoredMediaTypes: []string{"application/octet-stream"}, | 				IgnoredMediaTypes: []string{"application/octet-stream"}, | ||||||
|  | 				Ignore: Ignore{ | ||||||
|  | 					MediaTypes: []string{"application/octet-stream"}, | ||||||
|  | 					Actions:    []string{"pull"}, | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
|  | @ -142,6 +146,11 @@ notifications: | ||||||
|         Authorization: [Bearer <example>] |         Authorization: [Bearer <example>] | ||||||
|       ignoredmediatypes: |       ignoredmediatypes: | ||||||
|         - application/octet-stream |         - application/octet-stream | ||||||
|  |       ignore: | ||||||
|  |         mediatypes: | ||||||
|  |            - application/octet-stream | ||||||
|  |         actions: | ||||||
|  |            - pull | ||||||
| reporting: | reporting: | ||||||
|   bugsnag: |   bugsnag: | ||||||
|     apikey: BugsnagApiKey |     apikey: BugsnagApiKey | ||||||
|  | @ -170,6 +179,11 @@ notifications: | ||||||
|         Authorization: [Bearer <example>] |         Authorization: [Bearer <example>] | ||||||
|       ignoredmediatypes: |       ignoredmediatypes: | ||||||
|         - application/octet-stream |         - application/octet-stream | ||||||
|  |       ignore: | ||||||
|  |         mediatypes: | ||||||
|  |            - application/octet-stream | ||||||
|  |         actions: | ||||||
|  |            - pull | ||||||
| http: | http: | ||||||
|   headers: |   headers: | ||||||
|     X-Content-Type-Options: [nosniff] |     X-Content-Type-Options: [nosniff] | ||||||
|  |  | ||||||
|  | @ -232,6 +232,11 @@ notifications: | ||||||
|       backoff: 1s |       backoff: 1s | ||||||
|       ignoredmediatypes: |       ignoredmediatypes: | ||||||
|         - application/octet-stream |         - application/octet-stream | ||||||
|  |       ignore: | ||||||
|  |         mediatypes: | ||||||
|  |            - application/octet-stream | ||||||
|  |         actions: | ||||||
|  |            - pull | ||||||
| redis: | redis: | ||||||
|   addr: localhost:6379 |   addr: localhost:6379 | ||||||
|   password: asecret |   password: asecret | ||||||
|  | @ -837,6 +842,11 @@ notifications: | ||||||
|       backoff: 1s |       backoff: 1s | ||||||
|       ignoredmediatypes: |       ignoredmediatypes: | ||||||
|         - application/octet-stream |         - application/octet-stream | ||||||
|  |       ignore: | ||||||
|  |         mediatypes: | ||||||
|  |            - application/octet-stream | ||||||
|  |         actions: | ||||||
|  |            - pull | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The notifications option is **optional** and currently may contain a single | The notifications option is **optional** and currently may contain a single | ||||||
|  | @ -857,6 +867,14 @@ accept event notifications. | ||||||
| | `threshold` | yes    | An integer specifying how long to wait before backing off a failure. | | | `threshold` | yes    | An integer specifying how long to wait before backing off a failure. | | ||||||
| | `backoff` | yes      | How long the system backs off before retrying after a failure. A positive integer and an optional suffix indicating the unit of time, which may be `ns`, `us`, `ms`, `s`, `m`, or `h`. If you omit the unit of time, `ns` is used. | | | `backoff` | yes      | How long the system backs off before retrying after a failure. A positive integer and an optional suffix indicating the unit of time, which may be `ns`, `us`, `ms`, `s`, `m`, or `h`. If you omit the unit of time, `ns` is used. | | ||||||
| | `ignoredmediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. | | | `ignoredmediatypes`|no| A list of target media types to ignore. Events with these target media types are not published to the endpoint. | | ||||||
|  | | `ignore`  |no| Events with these mediatypes or actions are not published to the endpoint. | | ||||||
|  | 
 | ||||||
|  | #### `ignore` | ||||||
|  | | Parameter | Required | Description                                           | | ||||||
|  | |-----------|----------|-------------------------------------------------------| | ||||||
|  | | `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. | | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| ## `redis` | ## `redis` | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| package notifications | package notifications | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/docker/distribution/configuration" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  | @ -14,6 +15,7 @@ type EndpointConfig struct { | ||||||
| 	Backoff           time.Duration | 	Backoff           time.Duration | ||||||
| 	IgnoredMediaTypes []string | 	IgnoredMediaTypes []string | ||||||
| 	Transport         *http.Transport `json:"-"` | 	Transport         *http.Transport `json:"-"` | ||||||
|  | 	Ignore            configuration.Ignore | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // defaults set any zero-valued fields to a reasonable default.
 | // defaults set any zero-valued fields to a reasonable default.
 | ||||||
|  | @ -63,7 +65,8 @@ func NewEndpoint(name, url string, config EndpointConfig) *Endpoint { | ||||||
| 		endpoint.Transport, endpoint.metrics.httpStatusListener()) | 		endpoint.Transport, endpoint.metrics.httpStatusListener()) | ||||||
| 	endpoint.Sink = newRetryingSink(endpoint.Sink, endpoint.Threshold, endpoint.Backoff) | 	endpoint.Sink = newRetryingSink(endpoint.Sink, endpoint.Threshold, endpoint.Backoff) | ||||||
| 	endpoint.Sink = newEventQueue(endpoint.Sink, endpoint.metrics.eventQueueListener()) | 	endpoint.Sink = newEventQueue(endpoint.Sink, endpoint.metrics.eventQueueListener()) | ||||||
| 	endpoint.Sink = newIgnoredMediaTypesSink(endpoint.Sink, config.IgnoredMediaTypes) | 	mediaTypes := append(config.Ignore.MediaTypes, config.IgnoredMediaTypes...) | ||||||
|  | 	endpoint.Sink = newIgnoredSink(endpoint.Sink, mediaTypes, config.Ignore.Actions) | ||||||
| 
 | 
 | ||||||
| 	register(&endpoint) | 	register(&endpoint) | ||||||
| 	return &endpoint | 	return &endpoint | ||||||
|  |  | ||||||
|  | @ -210,14 +210,15 @@ func (eq *eventQueue) next() []Event { | ||||||
| 	return block | 	return block | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ignoredMediaTypesSink discards events with ignored target media types and
 | // ignoredSink discards events with ignored target media types and actions.
 | ||||||
| // passes the rest along.
 | // passes the rest along.
 | ||||||
| type ignoredMediaTypesSink struct { | type ignoredSink struct { | ||||||
| 	Sink | 	Sink | ||||||
| 	ignored map[string]bool | 	ignoreMediaTypes map[string]bool | ||||||
|  | 	ignoreActions    map[string]bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newIgnoredMediaTypesSink(sink Sink, ignored []string) Sink { | func newIgnoredSink(sink Sink, ignored []string, ignoreActions []string) Sink { | ||||||
| 	if len(ignored) == 0 { | 	if len(ignored) == 0 { | ||||||
| 		return sink | 		return sink | ||||||
| 	} | 	} | ||||||
|  | @ -227,25 +228,41 @@ func newIgnoredMediaTypesSink(sink Sink, ignored []string) Sink { | ||||||
| 		ignoredMap[mediaType] = true | 		ignoredMap[mediaType] = true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &ignoredMediaTypesSink{ | 	ignoredActionsMap := make(map[string]bool) | ||||||
| 		Sink:    sink, | 	for _, action := range ignoreActions { | ||||||
| 		ignored: ignoredMap, | 		ignoredActionsMap[action] = true | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &ignoredSink{ | ||||||
|  | 		Sink:             sink, | ||||||
|  | 		ignoreMediaTypes: ignoredMap, | ||||||
|  | 		ignoreActions:    ignoredActionsMap, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Write discards events with ignored target media types and passes the rest
 | // Write discards events with ignored target media types and passes the rest
 | ||||||
| // along.
 | // along.
 | ||||||
| func (imts *ignoredMediaTypesSink) Write(events ...Event) error { | func (imts *ignoredSink) Write(events ...Event) error { | ||||||
| 	var kept []Event | 	var kept []Event | ||||||
| 	for _, e := range events { | 	for _, e := range events { | ||||||
| 		if !imts.ignored[e.Target.MediaType] { | 		if !imts.ignoreMediaTypes[e.Target.MediaType] { | ||||||
| 			kept = append(kept, e) | 			kept = append(kept, e) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if len(kept) == 0 { | 	if len(kept) == 0 { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	return imts.Sink.Write(kept...) | 
 | ||||||
|  | 	var results []Event | ||||||
|  | 	for _, e := range kept { | ||||||
|  | 		if !imts.ignoreActions[e.Action] { | ||||||
|  | 			results = append(results, e) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if len(results) == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return imts.Sink.Write(results...) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // retryingSink retries the write until success or an ErrSinkClosed is
 | // retryingSink retries the write until success or an ErrSinkClosed is
 | ||||||
|  |  | ||||||
|  | @ -113,25 +113,29 @@ func TestEventQueue(t *testing.T) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestIgnoredMediaTypesSink(t *testing.T) { | func TestIgnoredSink(t *testing.T) { | ||||||
| 	blob := createTestEvent("push", "library/test", "blob") | 	blob := createTestEvent("push", "library/test", "blob") | ||||||
| 	manifest := createTestEvent("push", "library/test", "manifest") | 	manifest := createTestEvent("pull", "library/test", "manifest") | ||||||
| 
 | 
 | ||||||
| 	type testcase struct { | 	type testcase struct { | ||||||
| 		ignored  []string | 		ignoreMediaTypes []string | ||||||
| 		expected []Event | 		ignoreActions    []string | ||||||
|  | 		expected         []Event | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	cases := []testcase{ | 	cases := []testcase{ | ||||||
| 		{nil, []Event{blob, manifest}}, | 		{nil, nil, []Event{blob, manifest}}, | ||||||
| 		{[]string{"other"}, []Event{blob, manifest}}, | 		{[]string{"other"}, []string{"other"}, []Event{blob, manifest}}, | ||||||
| 		{[]string{"blob"}, []Event{manifest}}, | 		{[]string{"blob"}, []string{"other"}, []Event{manifest}}, | ||||||
| 		{[]string{"blob", "manifest"}, nil}, | 		{[]string{"blob", "manifest"}, []string{"other"}, nil}, | ||||||
|  | 		{[]string{"other"}, []string{"push"}, []Event{manifest}}, | ||||||
|  | 		{[]string{"other"}, []string{"pull"}, []Event{blob}}, | ||||||
|  | 		{[]string{"other"}, []string{"pull", "push"}, nil}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, c := range cases { | 	for _, c := range cases { | ||||||
| 		ts := &testSink{} | 		ts := &testSink{} | ||||||
| 		s := newIgnoredMediaTypesSink(ts, c.ignored) | 		s := newIgnoredSink(ts, c.ignoreMediaTypes, c.ignoreActions) | ||||||
| 
 | 
 | ||||||
| 		if err := s.Write(blob, manifest); err != nil { | 		if err := s.Write(blob, manifest); err != nil { | ||||||
| 			t.Fatalf("error writing event: %v", err) | 			t.Fatalf("error writing event: %v", err) | ||||||
|  |  | ||||||
|  | @ -439,6 +439,7 @@ func (app *App) configureEvents(configuration *configuration.Configuration) { | ||||||
| 			Backoff:           endpoint.Backoff, | 			Backoff:           endpoint.Backoff, | ||||||
| 			Headers:           endpoint.Headers, | 			Headers:           endpoint.Headers, | ||||||
| 			IgnoredMediaTypes: endpoint.IgnoredMediaTypes, | 			IgnoredMediaTypes: endpoint.IgnoredMediaTypes, | ||||||
|  | 			Ignore:            endpoint.Ignore, | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		sinks = append(sinks, endpoint) | 		sinks = append(sinks, endpoint) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue