Merge pull request #2501 from xiaonancc77/master

Added ignore event types into notifications
This commit is contained in:
Derek McGowan 2018-03-14 10:37:02 -07:00 committed by GitHub
commit 607ae5d128
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 20 deletions

View File

@ -561,6 +561,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.

View File

@ -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"},
},
}, },
}, },
}, },
@ -148,6 +152,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
@ -176,6 +185,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]

View File

@ -236,6 +236,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
@ -858,6 +863,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
@ -878,6 +888,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`

View File

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

View File

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

View File

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

View File

@ -450,6 +450,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)