mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
kubeadm: Retire MarshalClusterConfigurationToBytes
MarshalClusterConfigurationToBytes has capabilities to output the component configs, as separate YAML documents, besides the kubeadm ClusterConfiguration kind. This is no longer necessary for the following reasons: - All current use cases of this function require only the ClusterConfiguration. - It will output component configs only if they are not the default ones. This can produce undeterministic output and, thus, cause potential problems. - There are only hacky ways to dump the ClusterConfiguration only (without the component configs). Hence, we simplify things by replacing the function with direct calls to the underlaying MarshalToYamlForCodecs. Thus marshalling only ClusterConfiguration, when needed. Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
This commit is contained in:
parent
4e0b76469f
commit
94c56c81ba
@ -41,8 +41,6 @@ func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) {
|
||||
switch internalcfg := obj.(type) {
|
||||
case *kubeadmapi.InitConfiguration:
|
||||
return MarshalInitConfigurationToBytes(internalcfg, kubeadmapiv1beta2.SchemeGroupVersion)
|
||||
case *kubeadmapi.ClusterConfiguration:
|
||||
return MarshalClusterConfigurationToBytes(internalcfg, kubeadmapiv1beta2.SchemeGroupVersion)
|
||||
default:
|
||||
return kubeadmutil.MarshalToYamlForCodecs(obj, kubeadmapiv1beta2.SchemeGroupVersion, kubeadmscheme.Codecs)
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -342,7 +340,7 @@ func MarshalInitConfigurationToBytes(cfg *kubeadmapi.InitConfiguration, gv schem
|
||||
// Exception: If the specified groupversion is targeting the internal type, don't print embedded ClusterConfiguration contents
|
||||
// This is mostly used for unit testing. In a real scenario the internal version of the API is never marshalled as-is.
|
||||
if gv.Version != runtime.APIVersionInternal {
|
||||
clusterbytes, err := MarshalClusterConfigurationToBytes(&cfg.ClusterConfiguration, gv)
|
||||
clusterbytes, err := kubeadmutil.MarshalToYamlForCodecs(&cfg.ClusterConfiguration, gv, kubeadmscheme.Codecs)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
@ -350,60 +348,3 @@ func MarshalInitConfigurationToBytes(cfg *kubeadmapi.InitConfiguration, gv schem
|
||||
}
|
||||
return bytes.Join(allFiles, []byte(kubeadmconstants.YAMLDocumentSeparator)), nil
|
||||
}
|
||||
|
||||
// MarshalClusterConfigurationToBytes marshals the internal ClusterConfiguration object to bytes. It writes the embedded
|
||||
// ComponentConfiguration objects out as separate YAML documents
|
||||
func MarshalClusterConfigurationToBytes(clustercfg *kubeadmapi.ClusterConfiguration, gv schema.GroupVersion) ([]byte, error) {
|
||||
clusterbytes, err := kubeadmutil.MarshalToYamlForCodecs(clustercfg, gv, kubeadmscheme.Codecs)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
allFiles := [][]byte{clusterbytes}
|
||||
componentConfigContent := map[string][]byte{}
|
||||
defaultedcfg := defaultedInternalConfig()
|
||||
|
||||
for kind, registration := range componentconfigs.Known {
|
||||
// If the ComponentConfig struct for the current registration is nil, skip it when marshalling
|
||||
realobj, ok := registration.GetFromInternalConfig(clustercfg)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
defaultedobj, ok := registration.GetFromInternalConfig(defaultedcfg)
|
||||
// Invalid: The caller asked to not print the componentconfigs if defaulted, but defaultComponentConfigs() wasn't able to create default objects to use for reference
|
||||
if !ok {
|
||||
return []byte{}, errors.New("couldn't create a default componentconfig object")
|
||||
}
|
||||
|
||||
// If the real ComponentConfig object differs from the default, print it out. If not, there's no need to print it out, so skip it
|
||||
if !reflect.DeepEqual(realobj, defaultedobj) {
|
||||
contentBytes, err := registration.Marshal(realobj)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
componentConfigContent[string(kind)] = contentBytes
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the ComponentConfig files by kind when marshalling
|
||||
sortedComponentConfigFiles := consistentOrderByteSlice(componentConfigContent)
|
||||
allFiles = append(allFiles, sortedComponentConfigFiles...)
|
||||
return bytes.Join(allFiles, []byte(kubeadmconstants.YAMLDocumentSeparator)), nil
|
||||
}
|
||||
|
||||
// consistentOrderByteSlice takes a map of a string key and a byte slice, and returns a byte slice of byte slices
|
||||
// with consistent ordering, where the keys in the map determine the ordering of the return value. This has to be
|
||||
// done as the order of a for...range loop over a map in go is undeterministic, and could otherwise lead to flakes
|
||||
// in e.g. unit tests when marshalling content with a random order
|
||||
func consistentOrderByteSlice(content map[string][]byte) [][]byte {
|
||||
keys := []string{}
|
||||
sortedContent := [][]byte{}
|
||||
for key := range content {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
sortedContent = append(sortedContent, content[key])
|
||||
}
|
||||
return sortedContent
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
@ -199,95 +198,6 @@ func TestInitConfigurationMarshallingFromFile(t *testing.T) {
|
||||
}
|
||||
*/
|
||||
|
||||
func TestConsistentOrderByteSlice(t *testing.T) {
|
||||
var (
|
||||
aKind = "Akind"
|
||||
aFile = []byte(`
|
||||
kind: Akind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
aaKind = "Aakind"
|
||||
aaFile = []byte(`
|
||||
kind: Aakind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
abKind = "Abkind"
|
||||
abFile = []byte(`
|
||||
kind: Abkind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
)
|
||||
var tests = []struct {
|
||||
name string
|
||||
in map[string][]byte
|
||||
expected [][]byte
|
||||
}{
|
||||
{
|
||||
name: "a_aa_ab",
|
||||
in: map[string][]byte{
|
||||
aKind: aFile,
|
||||
aaKind: aaFile,
|
||||
abKind: abFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "a_ab_aa",
|
||||
in: map[string][]byte{
|
||||
aKind: aFile,
|
||||
abKind: abFile,
|
||||
aaKind: aaFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "aa_a_ab",
|
||||
in: map[string][]byte{
|
||||
aaKind: aaFile,
|
||||
aKind: aFile,
|
||||
abKind: abFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "aa_ab_a",
|
||||
in: map[string][]byte{
|
||||
aaKind: aaFile,
|
||||
abKind: abFile,
|
||||
aKind: aFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "ab_a_aa",
|
||||
in: map[string][]byte{
|
||||
abKind: abFile,
|
||||
aKind: aFile,
|
||||
aaKind: aaFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "ab_aa_a",
|
||||
in: map[string][]byte{
|
||||
abKind: abFile,
|
||||
aaKind: aaFile,
|
||||
aKind: aFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
actual := consistentOrderByteSlice(rt.in)
|
||||
if !reflect.DeepEqual(rt.expected, actual) {
|
||||
t2.Errorf("the expected and actual output differs.\n\texpected: %s\n\tout: %s\n", rt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultTaintsMarshaling(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
|
Loading…
Reference in New Issue
Block a user