1 package notifications 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/docker/distribution" 8 ) 9 10 // EventAction constants used in action field of Event. 11 const ( 12 EventActionPull = "pull" 13 EventActionPush = "push" 14 EventActionMount = "mount" 15 EventActionDelete = "delete" 16 ) 17 18 const ( 19 // EventsMediaType is the mediatype for the json event envelope. If the 20 // Event, ActorRecord, SourceRecord or Envelope structs change, the version 21 // number should be incremented. 22 EventsMediaType = "application/vnd.docker.distribution.events.v1+json" 23 // LayerMediaType is the media type for image rootfs diffs (aka "layers") 24 // used by Docker. We don't expect this to change for quite a while. 25 layerMediaType = "application/vnd.docker.container.image.rootfs.diff+x-gtar" 26 ) 27 28 // Envelope defines the fields of a json event envelope message that can hold 29 // one or more events. 30 type Envelope struct { 31 // Events make up the contents of the envelope. Events present in a single 32 // envelope are not necessarily related. 33 Events []Event `json:"events,omitempty"` 34 } 35 36 // TODO(stevvooe): The event type should be separate from the json format. It 37 // should be defined as an interface. Leaving as is for now since we don't 38 // need that at this time. If we make this change, the struct below would be 39 // called "EventRecord". 40 41 // Event provides the fields required to describe a registry event. 42 type Event struct { 43 // ID provides a unique identifier for the event. 44 ID string `json:"id,omitempty"` 45 46 // Timestamp is the time at which the event occurred. 47 Timestamp time.Time `json:"timestamp,omitempty"` 48 49 // Action indicates what action encompasses the provided event. 50 Action string `json:"action,omitempty"` 51 52 // Target uniquely describes the target of the event. 53 Target struct { 54 // TODO(stevvooe): Use http.DetectContentType for layers, maybe. 55 56 distribution.Descriptor 57 58 // Length in bytes of content. Same as Size field in Descriptor. 59 // Provided for backwards compatibility. 60 Length int64 `json:"length,omitempty"` 61 62 // Repository identifies the named repository. 63 Repository string `json:"repository,omitempty"` 64 65 // FromRepository identifies the named repository which a blob was mounted 66 // from if appropriate. 67 FromRepository string `json:"fromRepository,omitempty"` 68 69 // URL provides a direct link to the content. 70 URL string `json:"url,omitempty"` 71 72 // Tag provides the tag 73 Tag string `json:"tag,omitempty"` 74 75 // References provides the references descriptors. 76 References []distribution.Descriptor `json:"references,omitempty"` 77 } `json:"target,omitempty"` 78 79 // Request covers the request that generated the event. 80 Request RequestRecord `json:"request,omitempty"` 81 82 // Actor specifies the agent that initiated the event. For most 83 // situations, this could be from the authorization context of the request. 84 Actor ActorRecord `json:"actor,omitempty"` 85 86 // Source identifies the registry node that generated the event. Put 87 // differently, while the actor "initiates" the event, the source 88 // "generates" it. 89 Source SourceRecord `json:"source,omitempty"` 90 } 91 92 // ActorRecord specifies the agent that initiated the event. For most 93 // situations, this could be from the authorization context of the request. 94 // Data in this record can refer to both the initiating client and the 95 // generating request. 96 type ActorRecord struct { 97 // Name corresponds to the subject or username associated with the 98 // request context that generated the event. 99 Name string `json:"name,omitempty"` 100 101 // TODO(stevvooe): Look into setting a session cookie to get this 102 // without docker daemon. 103 // SessionID 104 105 // TODO(stevvooe): Push the "Docker-Command" header to replace cookie and 106 // get the actual command. 107 // Command 108 } 109 110 // RequestRecord covers the request that generated the event. 111 type RequestRecord struct { 112 // ID uniquely identifies the request that initiated the event. 113 ID string `json:"id"` 114 115 // Addr contains the ip or hostname and possibly port of the client 116 // connection that initiated the event. This is the RemoteAddr from 117 // the standard http request. 118 Addr string `json:"addr,omitempty"` 119 120 // Host is the externally accessible host name of the registry instance, 121 // as specified by the http host header on incoming requests. 122 Host string `json:"host,omitempty"` 123 124 // Method has the request method that generated the event. 125 Method string `json:"method"` 126 127 // UserAgent contains the user agent header of the request. 128 UserAgent string `json:"useragent"` 129 } 130 131 // SourceRecord identifies the registry node that generated the event. Put 132 // differently, while the actor "initiates" the event, the source "generates" 133 // it. 134 type SourceRecord struct { 135 // Addr contains the ip or hostname and the port of the registry node 136 // that generated the event. Generally, this will be resolved by 137 // os.Hostname() along with the running port. 138 Addr string `json:"addr,omitempty"` 139 140 // InstanceID identifies a running instance of an application. Changes 141 // after each restart. 142 InstanceID string `json:"instanceID,omitempty"` 143 } 144 145 var ( 146 // ErrSinkClosed is returned if a write is issued to a sink that has been 147 // closed. If encountered, the error should be considered terminal and 148 // retries will not be successful. 149 ErrSinkClosed = fmt.Errorf("sink: closed") 150 ) 151 152 // Sink accepts and sends events. 153 type Sink interface { 154 // Write writes one or more events to the sink. If no error is returned, 155 // the caller will assume that all events have been committed and will not 156 // try to send them again. If an error is received, the caller may retry 157 // sending the event. The caller should cede the slice of memory to the 158 // sink and not modify it after calling this method. 159 Write(events ...Event) error 160 161 // Close the sink, possibly waiting for pending events to flush. 162 Close() error 163 } 164