Separate request data from actor in Event
To clarify the role of actor, the request data that initiates an event has been separated. The ActorRecord is pared down to just the username. This eliminates confusion about where event related data should be added. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
0a29b59e14
commit
080e329cb1
@ -337,12 +337,10 @@ func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listene
|
|||||||
// addition of user and google context type.
|
// addition of user and google context type.
|
||||||
actor := notifications.ActorRecord{
|
actor := notifications.ActorRecord{
|
||||||
Name: "--todo--",
|
Name: "--todo--",
|
||||||
Addr: r.RemoteAddr,
|
|
||||||
Host: r.Host,
|
|
||||||
RequestID: ctx.RequestID,
|
|
||||||
}
|
}
|
||||||
|
request := notifications.NewRequestRecord(ctx.RequestID, r)
|
||||||
|
|
||||||
return notifications.NewBridge(ctx.urlBuilder, app.events.source, actor, app.events.sink)
|
return notifications.NewBridge(ctx.urlBuilder, app.events.source, actor, request, app.events.sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
// apiBase implements a simple yes-man for doing overall checks against the
|
// apiBase implements a simple yes-man for doing overall checks against the
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package notifications
|
package notifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/distribution/manifest"
|
"github.com/docker/distribution/manifest"
|
||||||
@ -14,6 +15,7 @@ type bridge struct {
|
|||||||
ub URLBuilder
|
ub URLBuilder
|
||||||
actor ActorRecord
|
actor ActorRecord
|
||||||
source SourceRecord
|
source SourceRecord
|
||||||
|
request RequestRecord
|
||||||
sink Sink
|
sink Sink
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,15 +30,29 @@ type URLBuilder interface {
|
|||||||
// NewBridge returns a notification listener that writes records to sink,
|
// NewBridge returns a notification listener that writes records to sink,
|
||||||
// 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.
|
||||||
func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, sink Sink) Listener {
|
// TODO(stevvooe): Update this to simply take a context.Context object.
|
||||||
|
func NewBridge(ub URLBuilder, source SourceRecord, actor ActorRecord, request RequestRecord, sink Sink) Listener {
|
||||||
return &bridge{
|
return &bridge{
|
||||||
ub: ub,
|
ub: ub,
|
||||||
actor: actor,
|
actor: actor,
|
||||||
source: source,
|
source: source,
|
||||||
|
request: request,
|
||||||
sink: sink,
|
sink: sink,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRequestRecord builds a RequestRecord for use in NewBridge from an
|
||||||
|
// http.Request, associating it with a request id.
|
||||||
|
func NewRequestRecord(id string, r *http.Request) RequestRecord {
|
||||||
|
return RequestRecord{
|
||||||
|
ID: id,
|
||||||
|
Addr: r.RemoteAddr,
|
||||||
|
Host: r.Host,
|
||||||
|
Method: r.Method,
|
||||||
|
UserAgent: r.UserAgent(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *bridge) ManifestPushed(repo storage.Repository, sm *manifest.SignedManifest) error {
|
func (b *bridge) ManifestPushed(repo storage.Repository, sm *manifest.SignedManifest) error {
|
||||||
return b.createManifestEventAndWrite(EventActionPush, repo, sm)
|
return b.createManifestEventAndWrite(EventActionPush, repo, sm)
|
||||||
}
|
}
|
||||||
@ -125,6 +141,7 @@ func (b *bridge) createEvent(action string) *Event {
|
|||||||
event := createEvent(action)
|
event := createEvent(action)
|
||||||
event.Source = b.source
|
event.Source = b.source
|
||||||
event.Actor = b.actor
|
event.Actor = b.actor
|
||||||
|
event.Request = b.request
|
||||||
|
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,9 @@ type Event struct {
|
|||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
} `json:"target,omitempty"`
|
} `json:"target,omitempty"`
|
||||||
|
|
||||||
|
// Request covers the request that generated the event.
|
||||||
|
Request RequestRecord `json:"request,omitempty"`
|
||||||
|
|
||||||
// Actor specifies the agent that initiated the event. For most
|
// Actor specifies the agent that initiated the event. For most
|
||||||
// situations, this could be from the authorizaton context of the request.
|
// situations, this could be from the authorizaton context of the request.
|
||||||
Actor ActorRecord `json:"actor,omitempty"`
|
Actor ActorRecord `json:"actor,omitempty"`
|
||||||
@ -86,18 +89,6 @@ type ActorRecord struct {
|
|||||||
// request context that generated the event.
|
// request context that generated the event.
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
// Addr contains the ip or hostname and possibly port of the client
|
|
||||||
// connection that initiated the event.
|
|
||||||
Addr string `json:"addr,omitempty"`
|
|
||||||
|
|
||||||
// Host is the externally accessible host name of the registry instance,
|
|
||||||
// as specified by the http host header on incoming requests.
|
|
||||||
Host string `json:"host,omitempty"`
|
|
||||||
|
|
||||||
// RequestID uniquely identifies the registry request that generated the
|
|
||||||
// event.
|
|
||||||
RequestID string `json:"requestID,omitempty"`
|
|
||||||
|
|
||||||
// TODO(stevvooe): Look into setting a session cookie to get this
|
// TODO(stevvooe): Look into setting a session cookie to get this
|
||||||
// without docker daemon.
|
// without docker daemon.
|
||||||
// SessionID
|
// SessionID
|
||||||
@ -107,6 +98,27 @@ type ActorRecord struct {
|
|||||||
// Command
|
// Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestRecord covers the request that generated the event.
|
||||||
|
type RequestRecord struct {
|
||||||
|
// ID uniquely identifies the request that initiated the event.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Addr contains the ip or hostname and possibly port of the client
|
||||||
|
// connection that initiated the event. This is the RemoteAddr from
|
||||||
|
// the standard http request.
|
||||||
|
Addr string `json:"addr,omitempty"`
|
||||||
|
|
||||||
|
// Host is the externally accessible host name of the registry instance,
|
||||||
|
// as specified by the http host header on incoming requests.
|
||||||
|
Host string `json:"host,omitempty"`
|
||||||
|
|
||||||
|
// Method has the request method that generated the event.
|
||||||
|
Method string `json:"method"`
|
||||||
|
|
||||||
|
// UserAgent contains the user agent header of the request.
|
||||||
|
UserAgent string `json:"useragent"`
|
||||||
|
}
|
||||||
|
|
||||||
// SourceRecord identifies the registry node that generated the event. Put
|
// SourceRecord identifies the registry node that generated the event. Put
|
||||||
// differently, while the actor "initiates" the event, the source "generates"
|
// differently, while the actor "initiates" the event, the source "generates"
|
||||||
// it.
|
// it.
|
||||||
|
@ -25,11 +25,15 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
|||||||
"tag": "latest",
|
"tag": "latest",
|
||||||
"url": "http://example.com/v2/library/test/manifests/latest"
|
"url": "http://example.com/v2/library/test/manifests/latest"
|
||||||
},
|
},
|
||||||
"actor": {
|
"request": {
|
||||||
"name": "test-actor",
|
"id": "asdfasdf",
|
||||||
"addr": "client.local",
|
"addr": "client.local",
|
||||||
"host": "registrycluster.local",
|
"host": "registrycluster.local",
|
||||||
"requestID": "asdfasdf"
|
"method": "PUT",
|
||||||
|
"useragent": "test/0.1"
|
||||||
|
},
|
||||||
|
"actor": {
|
||||||
|
"name": "test-actor"
|
||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"addr": "hostname.local:port"
|
"addr": "hostname.local:port"
|
||||||
@ -45,11 +49,15 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
|||||||
"digest": "tarsum.v2+sha256:0123456789abcdef1",
|
"digest": "tarsum.v2+sha256:0123456789abcdef1",
|
||||||
"url": "http://example.com/v2/library/test/manifests/latest"
|
"url": "http://example.com/v2/library/test/manifests/latest"
|
||||||
},
|
},
|
||||||
"actor": {
|
"request": {
|
||||||
"name": "test-actor",
|
"id": "asdfasdf",
|
||||||
"addr": "client.local",
|
"addr": "client.local",
|
||||||
"host": "registrycluster.local",
|
"host": "registrycluster.local",
|
||||||
"requestID": "asdfasdf"
|
"method": "PUT",
|
||||||
|
"useragent": "test/0.1"
|
||||||
|
},
|
||||||
|
"actor": {
|
||||||
|
"name": "test-actor"
|
||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"addr": "hostname.local:port"
|
"addr": "hostname.local:port"
|
||||||
@ -65,11 +73,15 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
|||||||
"digest": "tarsum.v2+sha256:0123456789abcdef2",
|
"digest": "tarsum.v2+sha256:0123456789abcdef2",
|
||||||
"url": "http://example.com/v2/library/test/manifests/latest"
|
"url": "http://example.com/v2/library/test/manifests/latest"
|
||||||
},
|
},
|
||||||
"actor": {
|
"request": {
|
||||||
"name": "test-actor",
|
"id": "asdfasdf",
|
||||||
"addr": "client.local",
|
"addr": "client.local",
|
||||||
"host": "registrycluster.local",
|
"host": "registrycluster.local",
|
||||||
"requestID": "asdfasdf"
|
"method": "PUT",
|
||||||
|
"useragent": "test/0.1"
|
||||||
|
},
|
||||||
|
"actor": {
|
||||||
|
"name": "test-actor"
|
||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"addr": "hostname.local:port"
|
"addr": "hostname.local:port"
|
||||||
@ -87,10 +99,12 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
|||||||
var prototype Event
|
var prototype Event
|
||||||
prototype.Action = "push"
|
prototype.Action = "push"
|
||||||
prototype.Timestamp = tm
|
prototype.Timestamp = tm
|
||||||
prototype.Actor.Addr = "client.local"
|
|
||||||
prototype.Actor.Name = "test-actor"
|
prototype.Actor.Name = "test-actor"
|
||||||
prototype.Actor.RequestID = "asdfasdf"
|
prototype.Request.ID = "asdfasdf"
|
||||||
prototype.Actor.Host = "registrycluster.local"
|
prototype.Request.Addr = "client.local"
|
||||||
|
prototype.Request.Host = "registrycluster.local"
|
||||||
|
prototype.Request.Method = "PUT"
|
||||||
|
prototype.Request.UserAgent = "test/0.1"
|
||||||
prototype.Source.Addr = "hostname.local:port"
|
prototype.Source.Addr = "hostname.local:port"
|
||||||
|
|
||||||
var manifestPush Event
|
var manifestPush Event
|
||||||
|
Loading…
Reference in New Issue
Block a user