mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
daemon: marshal legacy registry.ServiceConfig extra fields for compatability
This change moves the logic that is used to marshal the legacy extra fields for `registry.ServiceConfig` type to the daemon backend. Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
This commit is contained in:
@@ -17,23 +17,6 @@ type ServiceConfig struct {
|
||||
ExtraFields map[string]any `json:"-"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshaler to include legacy fields
|
||||
// in API responses.
|
||||
func (sc *ServiceConfig) MarshalJSON() ([]byte, error) {
|
||||
type tmp ServiceConfig
|
||||
base, err := json.Marshal((*tmp)(sc))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var merged map[string]any
|
||||
_ = json.Unmarshal(base, &merged)
|
||||
|
||||
for k, v := range sc.ExtraFields {
|
||||
merged[k] = v
|
||||
}
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
|
||||
// NetIPNet is the net.IPNet type, which can be marshalled and
|
||||
// unmarshalled to JSON
|
||||
type NetIPNet net.IPNet
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestServiceConfigMarshalLegacyFields(t *testing.T) {
|
||||
t.Run("without legacy fields", func(t *testing.T) {
|
||||
b, err := json.Marshal(&ServiceConfig{})
|
||||
assert.NilError(t, err)
|
||||
const expected = `{"IndexConfigs":null,"InsecureRegistryCIDRs":null,"Mirrors":null}`
|
||||
assert.Check(t, is.Equal(string(b), expected), "Legacy nondistributable-artifacts fields should be omitted in output")
|
||||
})
|
||||
|
||||
// Legacy fields should be returned when set to an empty slice. This is
|
||||
// used for API versions < 1.49.
|
||||
t.Run("with legacy fields", func(t *testing.T) {
|
||||
b, err := json.Marshal(&ServiceConfig{
|
||||
ExtraFields: map[string]any{
|
||||
"AllowNondistributableArtifactsCIDRs": json.RawMessage(nil),
|
||||
"AllowNondistributableArtifactsHostnames": json.RawMessage(nil),
|
||||
},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
const expected = `{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"IndexConfigs":null,"InsecureRegistryCIDRs":null,"Mirrors":null}`
|
||||
assert.Check(t, is.Equal(string(b), expected))
|
||||
})
|
||||
}
|
||||
@@ -24,12 +24,21 @@ func (ir *infoResponse) MarshalJSON() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ir.extraFields) == 0 {
|
||||
if len(ir.extraFields) == 0 && (ir.Info == nil || ir.Info.RegistryConfig == nil || len(ir.Info.RegistryConfig.ExtraFields) == 0) {
|
||||
return base, nil
|
||||
}
|
||||
var merged map[string]any
|
||||
_ = json.Unmarshal(base, &merged)
|
||||
|
||||
// Merge top-level extraFields
|
||||
maps.Copy(merged, ir.extraFields)
|
||||
|
||||
// Merge RegistryConfig.ExtraFields if present
|
||||
if ir.Info != nil && ir.Info.RegistryConfig != nil && len(ir.Info.RegistryConfig.ExtraFields) > 0 {
|
||||
if rc, ok := merged["RegistryConfig"].(map[string]any); ok {
|
||||
maps.Copy(rc, ir.Info.RegistryConfig.ExtraFields)
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
"github.com/moby/moby/api/types/system"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLegacyFields(t *testing.T) {
|
||||
@@ -31,3 +34,71 @@ func TestLegacyFields(t *testing.T) {
|
||||
t.Errorf("legacy fields should contain %s: %s", expected, string(data))
|
||||
}
|
||||
}
|
||||
|
||||
// TestMarshalRegistryConfigLegacyFields verifies extra fields in the registry config
|
||||
// field in the info response are serialized if they are not empty.
|
||||
// This is used for backwards compatibility for API versions < 1.47.
|
||||
func TestMarshalRegistryConfigLegacyFields(t *testing.T) {
|
||||
expected := []string{"AllowNondistributableArtifactsCIDRs", "AllowNondistributableArtifactsHostnames"}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
info *infoResponse
|
||||
assert func(t *testing.T, data []byte, err error)
|
||||
}{
|
||||
{
|
||||
name: "without legacy fields",
|
||||
info: &infoResponse{
|
||||
Info: &system.Info{},
|
||||
},
|
||||
assert: func(t *testing.T, data []byte, err error) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
var resp map[string]any
|
||||
err = json.Unmarshal(data, &resp)
|
||||
assert.NilError(t, err)
|
||||
|
||||
rc, ok := resp["RegistryConfig"]
|
||||
assert.Check(t, ok)
|
||||
|
||||
for _, v := range expected {
|
||||
assert.Check(t, !is.Contains(rc, v)().Success())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with legacy fields",
|
||||
info: &infoResponse{
|
||||
Info: &system.Info{
|
||||
RegistryConfig: ®istry.ServiceConfig{
|
||||
ExtraFields: map[string]any{
|
||||
"AllowNondistributableArtifactsCIDRs": json.RawMessage(nil),
|
||||
"AllowNondistributableArtifactsHostnames": json.RawMessage(nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, data []byte, err error) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
var resp map[string]any
|
||||
err = json.Unmarshal(data, &resp)
|
||||
assert.NilError(t, err)
|
||||
|
||||
rc, ok := resp["RegistryConfig"]
|
||||
assert.Check(t, ok)
|
||||
|
||||
for _, v := range expected {
|
||||
assert.Check(t, is.Contains(rc, v))
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
data, err := json.MarshalIndent(tc.info, "", " ")
|
||||
tc.assert(t, data, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
17
vendor/github.com/moby/moby/api/types/registry/registry.go
generated
vendored
17
vendor/github.com/moby/moby/api/types/registry/registry.go
generated
vendored
@@ -17,23 +17,6 @@ type ServiceConfig struct {
|
||||
ExtraFields map[string]any `json:"-"`
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshaler to include legacy fields
|
||||
// in API responses.
|
||||
func (sc *ServiceConfig) MarshalJSON() ([]byte, error) {
|
||||
type tmp ServiceConfig
|
||||
base, err := json.Marshal((*tmp)(sc))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var merged map[string]any
|
||||
_ = json.Unmarshal(base, &merged)
|
||||
|
||||
for k, v := range sc.ExtraFields {
|
||||
merged[k] = v
|
||||
}
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
|
||||
// NetIPNet is the net.IPNet type, which can be marshalled and
|
||||
// unmarshalled to JSON
|
||||
type NetIPNet net.IPNet
|
||||
|
||||
Reference in New Issue
Block a user