mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
API: /info: remove BridgeNfIptables, BridgeNfIp6tables fields
The `BridgeNfIptables` and `BridgeNfIp6tables` fields in the
`GET /info` response were deprecated in API v1.48, and are now omitted
in API v1.50.
With this patch, old API version continue to return the field:
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.48/info | jq .BridgeNfIp6tables
false
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.48/info | jq .BridgeNfIptables
false
Omitting the field in API v1.50 and above
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.50/info | jq .BridgeNfIp6tables
null
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.50/info | jq .BridgeNfIptables
null
This reverts commit eacbbdeec6, and re-applies
a variant of 5d2006256f
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
39
api/server/router/system/info_response.go
Normal file
39
api/server/router/system/info_response.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||
//go:build go1.23
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/docker/api/types/system"
|
||||
)
|
||||
|
||||
// infoResponse is a wrapper around [system.Info] with a custom
|
||||
// marshal function for legacy fields.
|
||||
type infoResponse struct {
|
||||
*system.Info
|
||||
|
||||
// extraFields is for internal use to include deprecated fields on older API versions.
|
||||
extraFields map[string]any
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshaler to include legacy fields
|
||||
// in API responses.
|
||||
func (sc *infoResponse) MarshalJSON() ([]byte, error) {
|
||||
type tmp *system.Info
|
||||
base, err := json.Marshal((tmp)(sc.Info))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(sc.extraFields) == 0 {
|
||||
return base, nil
|
||||
}
|
||||
var merged map[string]any
|
||||
_ = json.Unmarshal(base, &merged)
|
||||
|
||||
for k, v := range sc.extraFields {
|
||||
merged[k] = v
|
||||
}
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
33
api/server/router/system/info_response_test.go
Normal file
33
api/server/router/system/info_response_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/system"
|
||||
)
|
||||
|
||||
func TestLegacyFields(t *testing.T) {
|
||||
infoResp := &infoResponse{
|
||||
Info: &system.Info{
|
||||
Containers: 10,
|
||||
},
|
||||
extraFields: map[string]any{
|
||||
"LegacyFoo": false,
|
||||
"LegacyBar": true,
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(infoResp, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected := `"LegacyFoo": false`; !strings.Contains(string(data), expected) {
|
||||
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
|
||||
}
|
||||
if expected := `"LegacyBar": true`; !strings.Contains(string(data), expected) {
|
||||
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ package system // import "github.com/docker/docker/api/server/router/system"
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"resenje.org/singleflight"
|
||||
)
|
||||
|
||||
@@ -21,7 +20,7 @@ type systemRouter struct {
|
||||
// collectSystemInfo is a single-flight for the /info endpoint,
|
||||
// unique per API version (as different API versions may return
|
||||
// a different API response).
|
||||
collectSystemInfo singleflight.Group[string, *system.Info]
|
||||
collectSystemInfo singleflight.Group[string, *infoResponse]
|
||||
}
|
||||
|
||||
// NewRouter initializes a new system router
|
||||
|
||||
@@ -63,7 +63,7 @@ func (s *systemRouter) swarmStatus() string {
|
||||
|
||||
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*system.Info, error) {
|
||||
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*infoResponse, error) {
|
||||
info, err := s.backend.SystemInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -117,6 +117,7 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
info.FirewallBackend = nil
|
||||
}
|
||||
|
||||
extraFields := map[string]any{}
|
||||
if versions.LessThan(version, "1.49") {
|
||||
// Expected commits are omitted in API 1.49, but should still be
|
||||
// included in older versions.
|
||||
@@ -129,9 +130,17 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
}
|
||||
if versions.LessThan(version, "1.50") {
|
||||
info.DiscoveredDevices = nil
|
||||
|
||||
// These fields are omitted in > API 1.49, and always false
|
||||
// older API versions.
|
||||
extraFields = map[string]any{
|
||||
"BridgeNfIptables": json.RawMessage("false"),
|
||||
"BridgeNfIp6tables": json.RawMessage("false"),
|
||||
}
|
||||
}
|
||||
return info, nil
|
||||
return &infoResponse{Info: info, extraFields: extraFields}, nil
|
||||
})
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusOK, info)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ type Info struct {
|
||||
CPUSet bool
|
||||
PidsLimit bool
|
||||
IPv4Forwarding bool
|
||||
BridgeNfIptables bool `json:"BridgeNfIptables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
Debug bool
|
||||
NFd int
|
||||
OomKillDisable bool
|
||||
|
||||
@@ -21,6 +21,9 @@ keywords: "API, Docker, rcli, REST, documentation"
|
||||
`DeviceInfo` objects, each providing details about a device discovered by a
|
||||
device driver.
|
||||
Currently only the CDI device driver is supported.
|
||||
* Deprecated: The `BridgeNfIptables` and `BridgeNfIp6tables` fields in the
|
||||
`GET /info` response were deprecated in API v1.48, and are now omitted
|
||||
in API v1.50.
|
||||
|
||||
## v1.49 API changes
|
||||
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/testutil/request"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
@@ -47,3 +51,56 @@ func TestInfoBinaryCommits(t *testing.T) {
|
||||
assert.Check(t, is.Equal(info.RuncCommit.Expected, info.RuncCommit.ID)) //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfoLegacyFields(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
|
||||
const notPresent = "expected field to not be present"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
expectedFields map[string]any
|
||||
}{
|
||||
{
|
||||
name: "api v1.49 legacy bridge-nftables",
|
||||
url: "/v1.49/info",
|
||||
expectedFields: map[string]any{
|
||||
"BridgeNfIp6tables": false,
|
||||
"BridgeNfIptables": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "api v1.50 legacy bridge-nftables",
|
||||
url: "/v1.50/info",
|
||||
expectedFields: map[string]any{
|
||||
"BridgeNfIp6tables": notPresent,
|
||||
"BridgeNfIptables": notPresent,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, _, err := request.Get(ctx, tc.url)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, res.StatusCode, http.StatusOK)
|
||||
body, err := io.ReadAll(res.Body)
|
||||
assert.NilError(t, err)
|
||||
|
||||
actual := map[string]any{}
|
||||
err = json.Unmarshal(body, &actual)
|
||||
assert.NilError(t, err, string(body))
|
||||
|
||||
for field, expectedValue := range tc.expectedFields {
|
||||
if expectedValue == notPresent {
|
||||
_, found := actual[field]
|
||||
assert.Assert(t, !found, "field %s should not be present", field)
|
||||
} else {
|
||||
_, found := actual[field]
|
||||
assert.Assert(t, found, "field %s should be present", field)
|
||||
assert.Check(t, is.DeepEqual(actual[field], expectedValue))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,6 @@ type SysInfo struct {
|
||||
// Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work
|
||||
IPv4ForwardingDisabled bool
|
||||
|
||||
// Whether bridge-nf-call-iptables is supported or not
|
||||
//
|
||||
// Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
BridgeNFCallIPTablesDisabled bool
|
||||
|
||||
// Whether bridge-nf-call-ip6tables is supported or not
|
||||
//
|
||||
// Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release.
|
||||
BridgeNFCallIP6TablesDisabled bool
|
||||
|
||||
// Whether the cgroup has the mountpoint of "devices" or not
|
||||
CgroupDevicesEnabled bool
|
||||
|
||||
|
||||
Reference in New Issue
Block a user