mirror of
https://github.com/kubernetes-sigs/kind.git
synced 2025-12-01 07:26:05 +07:00
add patch.TOML
This commit is contained in:
2
go.mod
2
go.mod
@@ -3,9 +3,11 @@ module sigs.k8s.io/kind
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053
|
github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible
|
github.com/evanphx/json-patch v4.5.0+incompatible
|
||||||
github.com/mattn/go-isatty v0.0.10
|
github.com/mattn/go-isatty v0.0.10
|
||||||
|
github.com/pelletier/go-toml v1.2.0
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/spf13/cobra v0.0.5
|
github.com/spf13/cobra v0.0.5
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
|
|||||||
3
go.sum
3
go.sum
@@ -1,3 +1,4 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
@@ -11,6 +12,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
@@ -68,6 +70,7 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
|||||||
100
pkg/internal/util/patch/toml.go
Normal file
100
pkg/internal/util/patch/toml.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package patch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
burntoml "github.com/BurntSushi/toml"
|
||||||
|
jsonpatch "github.com/evanphx/json-patch"
|
||||||
|
toml "github.com/pelletier/go-toml"
|
||||||
|
yaml "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kind/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TOML patches toPatch with the patches (should be TOML merge patches) and patches6902 (should be JSON 6902 patches)
|
||||||
|
func TOML(toPatch string, patches []string, patches6902 []string) (string, error) {
|
||||||
|
// convert to JSON for patching
|
||||||
|
j, err := tomlToJSON([]byte(toPatch))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// apply merge patches
|
||||||
|
for _, patch := range patches {
|
||||||
|
pj, err := tomlToJSON([]byte(patch))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
patched, err := jsonpatch.MergePatch(j, pj)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
j = patched
|
||||||
|
}
|
||||||
|
// apply JSON 6902 patches
|
||||||
|
for _, patch6902 := range patches6902 {
|
||||||
|
patch, err := jsonpatch.DecodePatch([]byte(patch6902))
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
patched, err := patch.Apply(j)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
j = patched
|
||||||
|
}
|
||||||
|
// convert result back to TOML
|
||||||
|
return jsonToTOMLString(j)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tomlToJSON converts arbitrary TOML to JSON
|
||||||
|
func tomlToJSON(t []byte) ([]byte, error) {
|
||||||
|
// we use github.com.pelletier/go-toml here to unmarshal arbitrary TOML to JSON
|
||||||
|
tree, err := toml.LoadBytes(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(tree.ToMap())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsonToTOMLString converts arbitrary JSON to TOML
|
||||||
|
func jsonToTOMLString(j []byte) (string, error) {
|
||||||
|
var unstruct interface{}
|
||||||
|
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
|
||||||
|
// Go JSON library doesn't try to pick the right number type (int, float,
|
||||||
|
// etc.) when unmarshalling to interface{}, it just picks float64
|
||||||
|
// universally. go-yaml does go through the effort of picking the right
|
||||||
|
// number type, so we can preserve number type throughout this process.
|
||||||
|
if err := yaml.Unmarshal(j, &unstruct); err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
// we use github.com/BurntSushi/toml here because github.com.pelletier/go-toml
|
||||||
|
// can only marshal structs AND BurntSushi/toml is what contained uses
|
||||||
|
// and has more canonically formatted output (we initially plan to use
|
||||||
|
// this package for patching containerd config)
|
||||||
|
var buff bytes.Buffer
|
||||||
|
if err := burntoml.NewEncoder(&buff).Encode(unstruct); err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
return buff.String(), nil
|
||||||
|
}
|
||||||
198
pkg/internal/util/patch/toml_test.go
Normal file
198
pkg/internal/util/patch/toml_test.go
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package patch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/kind/pkg/internal/util/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTOML(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
type testCase struct {
|
||||||
|
Name string
|
||||||
|
ToPatch string
|
||||||
|
Patches []string
|
||||||
|
PatchesJSON6902 []string
|
||||||
|
ExpectError bool
|
||||||
|
ExpectOutput string
|
||||||
|
}
|
||||||
|
cases := []testCase{
|
||||||
|
{
|
||||||
|
Name: "invalid TOML",
|
||||||
|
ToPatch: `🗿`,
|
||||||
|
ExpectError: true,
|
||||||
|
ExpectOutput: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "no patches",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
ExpectError: false,
|
||||||
|
ExpectOutput: `disabled_plugins = ["restart"]
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalid patch TOML",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
Patches: []string{"🏰"},
|
||||||
|
ExpectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalid 6902 patch JSON",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
PatchesJSON6902: []string{"🏰"},
|
||||||
|
ExpectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "trivial patch",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
Patches: []string{`disabled_plugins=[]`},
|
||||||
|
ExpectError: false,
|
||||||
|
ExpectOutput: `[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "trivial 6902 patch",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
PatchesJSON6902: []string{`[{"op": "remove", "path": "/disabled_plugins"}]`},
|
||||||
|
ExpectError: false,
|
||||||
|
ExpectOutput: `[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "trivial patch and trivial 6902 patch",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
Patches: []string{`disabled_plugins=["foo"]`},
|
||||||
|
PatchesJSON6902: []string{`[{"op": "remove", "path": "/disabled_plugins"}]`},
|
||||||
|
ExpectError: false,
|
||||||
|
ExpectOutput: `[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalid path 6902 patch",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
PatchesJSON6902: []string{`[{"op": "remove", "path": "/fooooooo"}]`},
|
||||||
|
ExpectError: true,
|
||||||
|
ExpectOutput: `[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "patch registry",
|
||||||
|
ToPatch: `disabled_plugins = ["restart"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"`,
|
||||||
|
Patches: []string{`[plugins.cri.registry.mirrors]
|
||||||
|
[plugins.cri.registry.mirrors."registry:5000"]
|
||||||
|
endpoint = ["http://registry:5000"]`},
|
||||||
|
ExpectError: false,
|
||||||
|
ExpectOutput: `disabled_plugins = ["restart"]
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
[plugins.cri]
|
||||||
|
[plugins.cri.containerd]
|
||||||
|
[plugins.cri.containerd.runtimes]
|
||||||
|
[plugins.cri.containerd.runtimes.runsc]
|
||||||
|
runtime_type = "io.containerd.runsc.v1"
|
||||||
|
[plugins.cri.registry]
|
||||||
|
[plugins.cri.registry.mirrors]
|
||||||
|
[plugins.cri.registry.mirrors."registry:5000"]
|
||||||
|
endpoint = ["http://registry:5000"]
|
||||||
|
[plugins.linux]
|
||||||
|
shim_debug = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
tc := tc // capture test case
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
out, err := TOML(tc.ToPatch, tc.Patches, tc.PatchesJSON6902)
|
||||||
|
assert.ExpectError(t, tc.ExpectError, err)
|
||||||
|
if err == nil {
|
||||||
|
assert.StringEqual(t, tc.ExpectOutput, out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user