diff --git a/daemon/containerd/image_events.go b/daemon/containerd/image_events.go index 11e9a9900f..c3f507e7ba 100644 --- a/daemon/containerd/image_events.go +++ b/daemon/containerd/image_events.go @@ -1,13 +1,40 @@ package containerd -// LogImageEvent generates an event related to an image with only the -// default attributes. +import ( + "context" + + "github.com/docker/docker/api/types/events" + imagetypes "github.com/docker/docker/api/types/image" +) + +// LogImageEvent generates an event related to an image with only the default attributes. func (i *ImageService) LogImageEvent(imageID, refName, action string) { - panic("not implemented") + ctx := context.TODO() + attributes := map[string]string{} + + img, err := i.GetImage(ctx, imageID, imagetypes.GetImageOpts{}) + if err == nil && img.Config != nil { + // image has not been removed yet. + // it could be missing if the event is `delete`. + copyAttributes(attributes, img.Config.Labels) + } + if refName != "" { + attributes["name"] = refName + } + actor := events.Actor{ + ID: imageID, + Attributes: attributes, + } + + i.eventsService.Log(action, events.ImageEventType, actor) } -// LogImageEventWithAttributes generates an event related to an image with -// specific given attributes. -func (i *ImageService) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) { - panic("not implemented") +// copyAttributes guarantees that labels are not mutated by event triggers. +func copyAttributes(attributes, labels map[string]string) { + if labels == nil { + return + } + for k, v := range labels { + attributes[k] = v + } } diff --git a/daemon/containerd/service.go b/daemon/containerd/service.go index fc691735c7..3021fa9a1c 100644 --- a/daemon/containerd/service.go +++ b/daemon/containerd/service.go @@ -10,6 +10,7 @@ import ( "github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/snapshots" "github.com/docker/docker/container" + daemonevents "github.com/docker/docker/daemon/events" "github.com/docker/docker/daemon/images" "github.com/docker/docker/errdefs" "github.com/docker/docker/image" @@ -27,6 +28,7 @@ type ImageService struct { snapshotter string registryHosts RegistryHostsProvider registryService RegistryConfigProvider + eventsService *daemonevents.Events } type RegistryHostsProvider interface { @@ -37,14 +39,24 @@ type RegistryConfigProvider interface { IsInsecureRegistry(host string) bool } +type ImageServiceConfig struct { + Client *containerd.Client + Containers container.Store + Snapshotter string + HostsProvider RegistryHostsProvider + Registry RegistryConfigProvider + EventsService *daemonevents.Events +} + // NewService creates a new ImageService. -func NewService(c *containerd.Client, containers container.Store, snapshotter string, hostsProvider RegistryHostsProvider, registry RegistryConfigProvider) *ImageService { +func NewService(config ImageServiceConfig) *ImageService { return &ImageService{ - client: c, - containers: containers, - snapshotter: snapshotter, - registryHosts: hostsProvider, - registryService: registry, + client: config.Client, + containers: config.Containers, + snapshotter: config.Snapshotter, + registryHosts: config.HostsProvider, + registryService: config.Registry, + eventsService: config.EventsService, } } diff --git a/daemon/daemon.go b/daemon/daemon.go index 0736944ead..70f169d224 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -1012,7 +1012,14 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S if err := configureKernelSecuritySupport(config, driverName); err != nil { return nil, err } - d.imageService = ctrd.NewService(d.containerdCli, d.containers, driverName, d, d.registryService) + d.imageService = ctrd.NewService(ctrd.ImageServiceConfig{ + Client: d.containerdCli, + Containers: d.containers, + Snapshotter: driverName, + HostsProvider: d, + Registry: d.registryService, + EventsService: d.EventsService, + }) } else { layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{ Root: config.Root, diff --git a/daemon/image_service.go b/daemon/image_service.go index 78ac874f4e..75a45dc30e 100644 --- a/daemon/image_service.go +++ b/daemon/image_service.go @@ -34,7 +34,6 @@ type ImageService interface { LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error) LogImageEvent(imageID, refName, action string) - LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) CountImages() int ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) ImportImage(ctx context.Context, ref reference.Named, platform *v1.Platform, msg string, layerReader io.Reader, changes []string) (image.ID, error) diff --git a/daemon/images/image_events.go b/daemon/images/image_events.go index 1a824f5c64..84803b4ad8 100644 --- a/daemon/images/image_events.go +++ b/daemon/images/image_events.go @@ -9,12 +9,9 @@ import ( // LogImageEvent generates an event related to an image with only the default attributes. func (i *ImageService) LogImageEvent(imageID, refName, action string) { - i.LogImageEventWithAttributes(imageID, refName, action, map[string]string{}) -} - -// LogImageEventWithAttributes generates an event related to an image with specific given attributes. -func (i *ImageService) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) { ctx := context.TODO() + attributes := map[string]string{} + img, err := i.GetImage(ctx, imageID, imagetypes.GetImageOpts{}) if err == nil && img.Config != nil { // image has not been removed yet.