From 94c56c81bacc0fa0601958b78700a4871b004b06 Mon Sep 17 00:00:00 2001 From: "Rostislav M. Georgiev" Date: Wed, 19 Jun 2019 17:06:47 +0300 Subject: [PATCH] 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 --- cmd/kubeadm/app/util/config/common.go | 2 - .../app/util/config/initconfiguration.go | 61 +------------ .../app/util/config/initconfiguration_test.go | 90 ------------------- 3 files changed, 1 insertion(+), 152 deletions(-) diff --git a/cmd/kubeadm/app/util/config/common.go b/cmd/kubeadm/app/util/config/common.go index ae955748c16..329397127e5 100644 --- a/cmd/kubeadm/app/util/config/common.go +++ b/cmd/kubeadm/app/util/config/common.go @@ -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) } diff --git a/cmd/kubeadm/app/util/config/initconfiguration.go b/cmd/kubeadm/app/util/config/initconfiguration.go index 3fd70eccd95..c0c4675a64f 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration.go +++ b/cmd/kubeadm/app/util/config/initconfiguration.go @@ -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 -} diff --git a/cmd/kubeadm/app/util/config/initconfiguration_test.go b/cmd/kubeadm/app/util/config/initconfiguration_test.go index 0cbc509e048..d71f291dc5e 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration_test.go +++ b/cmd/kubeadm/app/util/config/initconfiguration_test.go @@ -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