Merge pull request #48060 from thaJeztah/27.0_backport_api_deprecate_ContainerJSONBase_Node

[27.0 backport] api/types: deprecate ContainerJSONBase.Node, ContainerNode
diff --git a/api/types/types.go b/api/types/types.go
index f0c648e..fe99b74 100644
--- a/api/types/types.go
+++ b/api/types/types.go
@@ -245,18 +245,6 @@
 	Health     *Health `json:",omitempty"`
 }
 
-// ContainerNode stores information about the node that a container
-// is running on.  It's only used by the Docker Swarm standalone API
-type ContainerNode struct {
-	ID        string
-	IPAddress string `json:"IP"`
-	Addr      string
-	Name      string
-	Cpus      int
-	Memory    int64
-	Labels    map[string]string
-}
-
 // ContainerJSONBase contains response of Engine API:
 // GET "/containers/{name:.*}/json"
 type ContainerJSONBase struct {
@@ -270,7 +258,7 @@
 	HostnamePath    string
 	HostsPath       string
 	LogPath         string
-	Node            *ContainerNode `json:",omitempty"` // Node is only propagated by Docker Swarm standalone API
+	Node            *ContainerNode `json:",omitempty"` // Deprecated: Node was only propagated by Docker Swarm standalone API. It sill be removed in the next release.
 	Name            string
 	RestartCount    int
 	Driver          string
diff --git a/api/types/types_deprecated.go b/api/types/types_deprecated.go
index 8edf70b..43ffe10 100644
--- a/api/types/types_deprecated.go
+++ b/api/types/types_deprecated.go
@@ -194,3 +194,17 @@
 //
 // Deprecated: use [image.LoadResponse].
 type ImageLoadResponse = image.LoadResponse
+
+// ContainerNode stores information about the node that a container
+// is running on.  It's only used by the Docker Swarm standalone API.
+//
+// Deprecated: ContainerNode was used for the classic Docker Swarm standalone API. It will be removed in the next release.
+type ContainerNode struct {
+	ID        string
+	IPAddress string `json:"IP"`
+	Addr      string
+	Name      string
+	Cpus      int
+	Memory    int64
+	Labels    map[string]string
+}
diff --git a/client/container_inspect_test.go b/client/container_inspect_test.go
index 4a6cbfa..2b1a276 100644
--- a/client/container_inspect_test.go
+++ b/client/container_inspect_test.go
@@ -83,55 +83,3 @@
 		t.Fatalf("expected `name`, got %s", r.Name)
 	}
 }
-
-// TestContainerInspectNode tests that the "Node" field is included in the "inspect"
-// output. This information is only present when connected to a Swarm standalone API.
-func TestContainerInspectNode(t *testing.T) {
-	client := &Client{
-		client: newMockClient(func(req *http.Request) (*http.Response, error) {
-			content, err := json.Marshal(types.ContainerJSON{
-				ContainerJSONBase: &types.ContainerJSONBase{
-					ID:    "container_id",
-					Image: "image",
-					Name:  "name",
-					Node: &types.ContainerNode{
-						ID:     "container_node_id",
-						Addr:   "container_node",
-						Labels: map[string]string{"foo": "bar"},
-					},
-				},
-			})
-			if err != nil {
-				return nil, err
-			}
-			return &http.Response{
-				StatusCode: http.StatusOK,
-				Body:       io.NopCloser(bytes.NewReader(content)),
-			}, nil
-		}),
-	}
-
-	r, err := client.ContainerInspect(context.Background(), "container_id")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if r.ID != "container_id" {
-		t.Fatalf("expected `container_id`, got %s", r.ID)
-	}
-	if r.Image != "image" {
-		t.Fatalf("expected `image`, got %s", r.Image)
-	}
-	if r.Name != "name" {
-		t.Fatalf("expected `name`, got %s", r.Name)
-	}
-	if r.Node.ID != "container_node_id" {
-		t.Fatalf("expected `container_node_id`, got %s", r.Node.ID)
-	}
-	if r.Node.Addr != "container_node" {
-		t.Fatalf("expected `container_node`, got %s", r.Node.Addr)
-	}
-	foo, ok := r.Node.Labels["foo"]
-	if foo != "bar" || !ok {
-		t.Fatalf("expected `bar` for label `foo`")
-	}
-}