Skip to content

Commit 6505d38

Browse files
committed
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 eacbbde, and re-applies a variant of 5d20062 Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 81116f7 commit 6505d38

8 files changed

Lines changed: 144 additions & 16 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
2+
//go:build go1.23
3+
4+
package system
5+
6+
import (
7+
"encoding/json"
8+
9+
"github.com/docker/docker/api/types/system"
10+
)
11+
12+
// infoResponse is a wrapper around [system.Info] with a custom
13+
// marshal function for legacy fields.
14+
type infoResponse struct {
15+
*system.Info
16+
17+
// extraFields is for internal use to include deprecated fields on older API versions.
18+
extraFields map[string]any
19+
}
20+
21+
// MarshalJSON implements a custom marshaler to include legacy fields
22+
// in API responses.
23+
func (sc *infoResponse) MarshalJSON() ([]byte, error) {
24+
type tmp *system.Info
25+
base, err := json.Marshal((tmp)(sc.Info))
26+
if err != nil {
27+
return nil, err
28+
}
29+
if len(sc.extraFields) == 0 {
30+
return base, nil
31+
}
32+
var merged map[string]any
33+
_ = json.Unmarshal(base, &merged)
34+
35+
for k, v := range sc.extraFields {
36+
merged[k] = v
37+
}
38+
return json.Marshal(merged)
39+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package system
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
"testing"
7+
8+
"github.com/docker/docker/api/types/system"
9+
)
10+
11+
func TestLegacyFields(t *testing.T) {
12+
infoResp := &infoResponse{
13+
Info: &system.Info{
14+
Containers: 10,
15+
},
16+
extraFields: map[string]any{
17+
"LegacyFoo": false,
18+
"LegacyBar": true,
19+
},
20+
}
21+
22+
data, err := json.MarshalIndent(infoResp, "", " ")
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
27+
if expected := `"LegacyFoo": false`; !strings.Contains(string(data), expected) {
28+
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
29+
}
30+
if expected := `"LegacyBar": true`; !strings.Contains(string(data), expected) {
31+
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
32+
}
33+
}

api/server/router/system/system.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package system // import "github.com/docker/docker/api/server/router/system"
55

66
import (
77
"github.com/docker/docker/api/server/router"
8-
"github.com/docker/docker/api/types/system"
98
"resenje.org/singleflight"
109
)
1110

@@ -21,7 +20,7 @@ type systemRouter struct {
2120
// collectSystemInfo is a single-flight for the /info endpoint,
2221
// unique per API version (as different API versions may return
2322
// a different API response).
24-
collectSystemInfo singleflight.Group[string, *system.Info]
23+
collectSystemInfo singleflight.Group[string, *infoResponse]
2524
}
2625

2726
// NewRouter initializes a new system router

api/server/router/system/system_routes.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (s *systemRouter) swarmStatus() string {
6363

6464
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
6565
version := httputils.VersionFromContext(ctx)
66-
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*system.Info, error) {
66+
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*infoResponse, error) {
6767
info, err := s.backend.SystemInfo(ctx)
6868
if err != nil {
6969
return nil, err
@@ -117,6 +117,7 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
117117
info.FirewallBackend = nil
118118
}
119119

120+
extraFields := map[string]any{}
120121
if versions.LessThan(version, "1.49") {
121122
// Expected commits are omitted in API 1.49, but should still be
122123
// included in older versions.
@@ -129,9 +130,17 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
129130
}
130131
if versions.LessThan(version, "1.50") {
131132
info.DiscoveredDevices = nil
133+
134+
// These fields are omitted in > API 1.49, and always false
135+
// older API versions.
136+
extraFields = map[string]any{
137+
"BridgeNfIptables": json.RawMessage("false"),
138+
"BridgeNfIp6tables": json.RawMessage("false"),
139+
}
132140
}
133-
return info, nil
141+
return &infoResponse{Info: info, extraFields: extraFields}, nil
134142
})
143+
135144
return httputils.WriteJSON(w, http.StatusOK, info)
136145
}
137146

api/types/system/info.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ type Info struct {
2929
CPUSet bool
3030
PidsLimit bool
3131
IPv4Forwarding bool
32-
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.
33-
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.
3432
Debug bool
3533
NFd int
3634
OomKillDisable bool

docs/api/version-history.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ keywords: "API, Docker, rcli, REST, documentation"
2121
`DeviceInfo` objects, each providing details about a device discovered by a
2222
device driver.
2323
Currently only the CDI device driver is supported.
24+
* Deprecated: The `BridgeNfIptables` and `BridgeNfIp6tables` fields in the
25+
`GET /info` response were deprecated in API v1.48, and are now omitted
26+
in API v1.50.
2427

2528
## v1.49 API changes
2629

integration/system/info_linux_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
package system // import "github.com/docker/docker/integration/system"
44

55
import (
6+
"encoding/json"
7+
"io"
8+
"net/http"
69
"testing"
710

811
"github.com/docker/docker/client"
12+
"github.com/docker/docker/testutil/request"
913
"gotest.tools/v3/assert"
1014
is "gotest.tools/v3/assert/cmp"
1115
)
@@ -47,3 +51,56 @@ func TestInfoBinaryCommits(t *testing.T) {
4751
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.
4852
})
4953
}
54+
55+
func TestInfoLegacyFields(t *testing.T) {
56+
ctx := setupTest(t)
57+
58+
const notPresent = "expected field to not be present"
59+
60+
tests := []struct {
61+
name string
62+
url string
63+
expectedFields map[string]any
64+
}{
65+
{
66+
name: "api v1.49 legacy bridge-nftables",
67+
url: "/v1.49/info",
68+
expectedFields: map[string]any{
69+
"BridgeNfIp6tables": false,
70+
"BridgeNfIptables": false,
71+
},
72+
},
73+
{
74+
name: "api v1.50 legacy bridge-nftables",
75+
url: "/v1.50/info",
76+
expectedFields: map[string]any{
77+
"BridgeNfIp6tables": notPresent,
78+
"BridgeNfIptables": notPresent,
79+
},
80+
},
81+
}
82+
for _, tc := range tests {
83+
t.Run(tc.name, func(t *testing.T) {
84+
res, _, err := request.Get(ctx, tc.url)
85+
assert.NilError(t, err)
86+
assert.Equal(t, res.StatusCode, http.StatusOK)
87+
body, err := io.ReadAll(res.Body)
88+
assert.NilError(t, err)
89+
90+
actual := map[string]any{}
91+
err = json.Unmarshal(body, &actual)
92+
assert.NilError(t, err, string(body))
93+
94+
for field, expectedValue := range tc.expectedFields {
95+
if expectedValue == notPresent {
96+
_, found := actual[field]
97+
assert.Assert(t, !found, "field %s should not be present", field)
98+
} else {
99+
_, found := actual[field]
100+
assert.Assert(t, found, "field %s should be present", field)
101+
assert.Check(t, is.DeepEqual(actual[field], expectedValue))
102+
}
103+
}
104+
})
105+
}
106+
}

pkg/sysinfo/sysinfo.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@ type SysInfo struct {
2424
// Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work
2525
IPv4ForwardingDisabled bool
2626

27-
// Whether bridge-nf-call-iptables is supported or not
28-
//
29-
// 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.
30-
BridgeNFCallIPTablesDisabled bool
31-
32-
// Whether bridge-nf-call-ip6tables is supported or not
33-
//
34-
// 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.
35-
BridgeNFCallIP6TablesDisabled bool
36-
3727
// Whether the cgroup has the mountpoint of "devices" or not
3828
CgroupDevicesEnabled bool
3929

0 commit comments

Comments
 (0)