Merge pull request #50832 from thaJeztah/events_remove_deprecated

api/types/events: Message: remove deprecated Status, ID, and From fields
This commit is contained in:
Sebastiaan van Stijn
2025-09-11 21:22:57 +02:00
committed by GitHub
6 changed files with 45 additions and 51 deletions

View File

@@ -22,6 +22,9 @@ keywords: "API, Docker, rcli, REST, documentation"
saved.
* `POST /images/load` now accepts multiple `platform` query-arguments
to allow selecting which platform(s) of a multi-platform image to load.
* `GET /events` no longer includes the deprecated `status`, `id`, and `from`
fields. These fields were removed in API v1.22, but still included
in the response.
* Deprecated: the Engine was automatically backfilling empty `PortBindings` lists with
a PortBinding with an empty HostIP and HostPort when calling `POST /containers/{id}/start`.
This behavior is now deprecated, and a warning is returned by `POST /containers/create`.

View File

@@ -110,15 +110,6 @@ type Actor struct {
// Message represents the information an event contains
type Message struct {
// Deprecated: use Action instead.
// Information from JSONMessage.
// With data only in container events.
Status string `json:"status,omitempty"`
// Deprecated: use Actor.ID instead.
ID string `json:"id,omitempty"`
// Deprecated: use Actor.Attributes["image"] instead.
From string `json:"from,omitempty"`
Type Type
Action Action
Actor Actor

View File

@@ -82,29 +82,14 @@ func (e *Events) Evict(l chan any) {
// Log creates a local scope message and publishes it
func (e *Events) Log(action eventtypes.Action, eventType eventtypes.Type, actor eventtypes.Actor) {
now := time.Now().UTC()
jm := eventtypes.Message{
e.PublishMessage(eventtypes.Message{
Action: action,
Type: eventType,
Actor: actor,
Scope: "local",
Time: now.Unix(),
TimeNano: now.UnixNano(),
}
// fill deprecated fields for container and images
switch eventType {
case eventtypes.ContainerEventType:
jm.ID = actor.ID //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
jm.Status = string(action) //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
jm.From = actor.Attributes["image"] //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
case eventtypes.ImageEventType:
jm.ID = actor.ID //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
jm.Status = string(action) //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
default:
// TODO(thaJeztah): make switch exhaustive
}
e.PublishMessage(jm)
})
}
// PublishMessage broadcasts event to listeners. Each listener has 100 milliseconds to

View File

@@ -12,19 +12,6 @@ import (
is "gotest.tools/v3/assert/cmp"
)
// validateLegacyFields validates that the legacy "Status", "ID", and "From"
// fields are set to the same value as their "current" (non-legacy) fields.
//
// These fields were deprecated since v1.10 (https://github.com/moby/moby/pull/18888).
//
// TODO remove this once we removed the deprecated `ID`, `Status`, and `From` fields.
func validateLegacyFields(t *testing.T, msg events.Message) {
t.Helper()
assert.Check(t, is.Equal(msg.Status, string(msg.Action)), "Legacy Status field does not match Action") //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
assert.Check(t, is.Equal(msg.ID, msg.Actor.ID), "Legacy ID field does not match Actor.ID") //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
assert.Check(t, is.Equal(msg.From, msg.Actor.Attributes["image"]), "Legacy From field does not match Actor.Attributes.image") //nolint:staticcheck // ignore SA1019: field is deprecated but set for backward compatibility.
}
func TestEventsLog(t *testing.T) {
e := New()
_, l1, _ := e.Subscribe()
@@ -44,7 +31,6 @@ func TestEventsLog(t *testing.T) {
jmsg, ok := msg.(events.Message)
assert.Assert(t, ok, "unexpected type: %T", msg)
validateLegacyFields(t, jmsg)
assert.Check(t, is.Equal(jmsg.Action, events.Action("test")))
assert.Check(t, is.Equal(jmsg.Actor.ID, "cont"))
assert.Check(t, is.Equal(jmsg.Actor.Attributes["image"], "image"))
@@ -57,7 +43,6 @@ func TestEventsLog(t *testing.T) {
jmsg, ok := msg.(events.Message)
assert.Assert(t, ok, "unexpected type: %T", msg)
validateLegacyFields(t, jmsg)
assert.Check(t, is.Equal(jmsg.Action, events.Action("test")))
assert.Check(t, is.Equal(jmsg.Actor.ID, "cont"))
assert.Check(t, is.Equal(jmsg.Actor.Attributes["image"], "image"))
@@ -120,7 +105,6 @@ func TestLogEvents(t *testing.T) {
assert.Assert(t, is.Len(current, eventsLimit))
first := current[0]
validateLegacyFields(t, first)
assert.Check(t, is.Equal(first.Action, events.Action("action_16")))
last := current[len(current)-1]

View File

@@ -17,6 +17,7 @@ import (
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/api/types/versions"
"github.com/moby/moby/v2/daemon/internal/compat"
"github.com/moby/moby/v2/daemon/internal/timestamp"
"github.com/moby/moby/v2/daemon/server/backend"
"github.com/moby/moby/v2/daemon/server/httputils"
@@ -369,10 +370,21 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
}
}
var includeLegacyFields bool
if versions.LessThan(httputils.VersionFromContext(ctx), "1.52") {
includeLegacyFields = true
}
for _, ev := range buffered {
if shouldSkip(ev) {
continue
}
if includeLegacyFields {
if err := enc.Encode(backFillLegacy(&ev)); err != nil {
return err
}
continue
}
if err := enc.Encode(ev); err != nil {
return err
}
@@ -393,6 +405,12 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
if shouldSkip(jev) {
continue
}
if includeLegacyFields {
if err := enc.Encode(backFillLegacy(&jev)); err != nil {
return err
}
continue
}
if err := enc.Encode(jev); err != nil {
return err
}
@@ -430,3 +448,25 @@ func eventTime(formTime string) (time.Time, error) {
}
return time.Unix(t, tNano), nil
}
// These fields were deprecated in docker v1.10, API v1.22, but not removed
// from the API responses. Unfortunately, the Docker CLI (and compose indirectly),
// continued using these fields up until v25.0.0, and panic if the fields are
// omitted, or left empty (due to a bug), see: https://github.com/moby/moby/pull/50832#issuecomment-3276600925
func backFillLegacy(ev *events.Message) any {
switch ev.Type {
case events.ContainerEventType:
return compat.Wrap(ev, compat.WithExtraFields(map[string]any{
"id": ev.Actor.ID,
"status": ev.Action,
"from": ev.Actor.Attributes["image"],
}))
case events.ImageEventType:
return compat.Wrap(ev, compat.WithExtraFields(map[string]any{
"id": ev.Actor.ID,
"status": ev.Action,
}))
default:
return &ev
}
}

View File

@@ -110,15 +110,6 @@ type Actor struct {
// Message represents the information an event contains
type Message struct {
// Deprecated: use Action instead.
// Information from JSONMessage.
// With data only in container events.
Status string `json:"status,omitempty"`
// Deprecated: use Actor.ID instead.
ID string `json:"id,omitempty"`
// Deprecated: use Actor.Attributes["image"] instead.
From string `json:"from,omitempty"`
Type Type
Action Action
Actor Actor