2015-01-28 03:37:16 +00:00
|
|
|
package notifications
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2020-08-24 11:18:39 +00:00
|
|
|
"github.com/distribution/distribution/v3"
|
2018-03-14 00:08:11 +00:00
|
|
|
events "github.com/docker/go-events"
|
2015-01-28 03:37:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// EventAction constants used in action field of Event.
|
|
|
|
const (
|
|
|
|
EventActionPull = "pull"
|
|
|
|
EventActionPush = "push"
|
2016-01-06 23:57:35 +00:00
|
|
|
EventActionMount = "mount"
|
2015-01-28 03:37:16 +00:00
|
|
|
EventActionDelete = "delete"
|
2015-01-28 23:55:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2015-03-05 04:57:14 +00:00
|
|
|
// EventsMediaType is the mediatype for the json event envelope. If the
|
|
|
|
// Event, ActorRecord, SourceRecord or Envelope structs change, the version
|
|
|
|
// number should be incremented.
|
2023-08-28 11:33:50 +00:00
|
|
|
EventsMediaType = "application/vnd.docker.distribution.events.v2+json"
|
2015-03-05 04:57:14 +00:00
|
|
|
// LayerMediaType is the media type for image rootfs diffs (aka "layers")
|
|
|
|
// used by Docker. We don't expect this to change for quite a while.
|
|
|
|
layerMediaType = "application/vnd.docker.container.image.rootfs.diff+x-gtar"
|
2015-01-28 03:37:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Envelope defines the fields of a json event envelope message that can hold
|
|
|
|
// one or more events.
|
|
|
|
type Envelope struct {
|
|
|
|
// Events make up the contents of the envelope. Events present in a single
|
|
|
|
// envelope are not necessarily related.
|
2018-03-14 00:08:11 +00:00
|
|
|
Events []events.Event `json:"events,omitempty"`
|
2015-01-28 03:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(stevvooe): The event type should be separate from the json format. It
|
|
|
|
// should be defined as an interface. Leaving as is for now since we don't
|
|
|
|
// need that at this time. If we make this change, the struct below would be
|
|
|
|
// called "EventRecord".
|
|
|
|
|
|
|
|
// Event provides the fields required to describe a registry event.
|
|
|
|
type Event struct {
|
|
|
|
// ID provides a unique identifier for the event.
|
2015-01-28 07:27:46 +00:00
|
|
|
ID string `json:"id,omitempty"`
|
2015-01-28 03:37:16 +00:00
|
|
|
|
|
|
|
// Timestamp is the time at which the event occurred.
|
|
|
|
Timestamp time.Time `json:"timestamp,omitempty"`
|
|
|
|
|
|
|
|
// Action indicates what action encompasses the provided event.
|
|
|
|
Action string `json:"action,omitempty"`
|
|
|
|
|
|
|
|
// Target uniquely describes the target of the event.
|
|
|
|
Target struct {
|
2015-03-05 04:57:14 +00:00
|
|
|
// TODO(stevvooe): Use http.DetectContentType for layers, maybe.
|
2015-01-28 03:37:16 +00:00
|
|
|
|
2015-03-05 04:57:14 +00:00
|
|
|
distribution.Descriptor
|
2015-01-28 03:37:16 +00:00
|
|
|
|
2015-07-18 00:07:11 +00:00
|
|
|
// Length in bytes of content. Same as Size field in Descriptor.
|
|
|
|
// Provided for backwards compatibility.
|
|
|
|
Length int64 `json:"length,omitempty"`
|
|
|
|
|
2015-03-05 04:57:14 +00:00
|
|
|
// Repository identifies the named repository.
|
|
|
|
Repository string `json:"repository,omitempty"`
|
2015-01-28 03:37:16 +00:00
|
|
|
|
2016-01-06 23:57:35 +00:00
|
|
|
// FromRepository identifies the named repository which a blob was mounted
|
|
|
|
// from if appropriate.
|
|
|
|
FromRepository string `json:"fromRepository,omitempty"`
|
|
|
|
|
2015-03-05 04:57:14 +00:00
|
|
|
// URL provides a direct link to the content.
|
2015-01-28 03:37:16 +00:00
|
|
|
URL string `json:"url,omitempty"`
|
2016-03-18 22:30:47 +00:00
|
|
|
|
|
|
|
// Tag provides the tag
|
|
|
|
Tag string `json:"tag,omitempty"`
|
2018-06-27 15:47:40 +00:00
|
|
|
|
2018-08-20 17:01:40 +00:00
|
|
|
// References provides the references descriptors.
|
|
|
|
References []distribution.Descriptor `json:"references,omitempty"`
|
2015-01-28 03:37:16 +00:00
|
|
|
} `json:"target,omitempty"`
|
|
|
|
|
2015-02-03 21:28:10 +00:00
|
|
|
// Request covers the request that generated the event.
|
|
|
|
Request RequestRecord `json:"request,omitempty"`
|
|
|
|
|
2015-01-28 03:37:16 +00:00
|
|
|
// Actor specifies the agent that initiated the event. For most
|
2017-03-20 12:15:55 +00:00
|
|
|
// situations, this could be from the authorization context of the request.
|
2015-01-28 03:37:16 +00:00
|
|
|
Actor ActorRecord `json:"actor,omitempty"`
|
|
|
|
|
|
|
|
// Source identifies the registry node that generated the event. Put
|
|
|
|
// differently, while the actor "initiates" the event, the source
|
|
|
|
// "generates" it.
|
|
|
|
Source SourceRecord `json:"source,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// ActorRecord specifies the agent that initiated the event. For most
|
2017-03-20 12:15:55 +00:00
|
|
|
// situations, this could be from the authorization context of the request.
|
2015-01-28 07:27:46 +00:00
|
|
|
// Data in this record can refer to both the initiating client and the
|
|
|
|
// generating request.
|
2015-01-28 03:37:16 +00:00
|
|
|
type ActorRecord struct {
|
|
|
|
// Name corresponds to the subject or username associated with the
|
|
|
|
// request context that generated the event.
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
|
2015-02-03 21:28:10 +00:00
|
|
|
// TODO(stevvooe): Look into setting a session cookie to get this
|
|
|
|
// without docker daemon.
|
|
|
|
// SessionID
|
|
|
|
|
|
|
|
// TODO(stevvooe): Push the "Docker-Command" header to replace cookie and
|
|
|
|
// get the actual 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"`
|
|
|
|
|
2015-01-28 03:37:16 +00:00
|
|
|
// Addr contains the ip or hostname and possibly port of the client
|
2015-02-03 21:28:10 +00:00
|
|
|
// connection that initiated the event. This is the RemoteAddr from
|
|
|
|
// the standard http request.
|
2015-01-28 03:37:16 +00:00
|
|
|
Addr string `json:"addr,omitempty"`
|
2015-01-28 07:27:46 +00:00
|
|
|
|
|
|
|
// 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"`
|
|
|
|
|
2015-02-03 21:28:10 +00:00
|
|
|
// Method has the request method that generated the event.
|
|
|
|
Method string `json:"method"`
|
2015-01-28 07:27:46 +00:00
|
|
|
|
2015-02-03 21:28:10 +00:00
|
|
|
// UserAgent contains the user agent header of the request.
|
|
|
|
UserAgent string `json:"useragent"`
|
2015-01-28 03:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SourceRecord identifies the registry node that generated the event. Put
|
|
|
|
// differently, while the actor "initiates" the event, the source "generates"
|
|
|
|
// it.
|
|
|
|
type SourceRecord struct {
|
|
|
|
// Addr contains the ip or hostname and the port of the registry node
|
|
|
|
// that generated the event. Generally, this will be resolved by
|
|
|
|
// os.Hostname() along with the running port.
|
|
|
|
Addr string `json:"addr,omitempty"`
|
|
|
|
|
2015-01-28 07:27:46 +00:00
|
|
|
// InstanceID identifies a running instance of an application. Changes
|
|
|
|
// after each restart.
|
|
|
|
InstanceID string `json:"instanceID,omitempty"`
|
2015-01-28 03:37:16 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 21:05:45 +00:00
|
|
|
// ErrSinkClosed is returned if a write is issued to a sink that has been
|
|
|
|
// closed. If encountered, the error should be considered terminal and
|
|
|
|
// retries will not be successful.
|
|
|
|
var ErrSinkClosed = fmt.Errorf("sink: closed")
|