Skip to content

Commit 9315ddb

Browse files
committed
kubeadm: fix panic when no UpgradeConfiguration was found in the config file
1 parent edc1fd2 commit 9315ddb

File tree

4 files changed

+44
-115
lines changed

4 files changed

+44
-115
lines changed

cmd/kubeadm/app/util/config/common.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -492,13 +492,3 @@ func defaultEmptyMigrateMutators() migrateMutators {
492492

493493
return *mutators
494494
}
495-
496-
// isKubeadmConfigPresent checks if a kubeadm config type is found in the provided document map
497-
func isKubeadmConfigPresent(docmap kubeadmapi.DocumentMap) bool {
498-
for gvk := range docmap {
499-
if gvk.Group == kubeadmapi.GroupName {
500-
return true
501-
}
502-
}
503-
return false
504-
}

cmd/kubeadm/app/util/config/common_test.go

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -972,52 +972,3 @@ func TestDefaultMigrateMutators(t *testing.T) {
972972
})
973973
}
974974
}
975-
976-
func TestIsKubeadmConfigPresent(t *testing.T) {
977-
var tcases = []struct {
978-
name string
979-
gvkmap kubeadmapi.DocumentMap
980-
expected bool
981-
}{
982-
{
983-
name: " Wrong Group value",
984-
gvkmap: kubeadmapi.DocumentMap{
985-
{Group: "foo.k8s.io", Version: "v1", Kind: "Foo"}: []byte(`kind: Foo`),
986-
},
987-
expected: false,
988-
},
989-
{
990-
name: "Empty Group value",
991-
gvkmap: kubeadmapi.DocumentMap{
992-
{Group: "", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
993-
},
994-
expected: false,
995-
},
996-
{
997-
name: "Nil value",
998-
gvkmap: nil,
999-
expected: false,
1000-
},
1001-
{
1002-
name: "Correct Group value 1",
1003-
gvkmap: kubeadmapi.DocumentMap{
1004-
{Group: "kubeadm.k8s.io", Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
1005-
},
1006-
expected: true,
1007-
},
1008-
{
1009-
name: "Correct Group value 2",
1010-
gvkmap: kubeadmapi.DocumentMap{
1011-
{Group: kubeadmapi.GroupName, Version: "v1", Kind: "Empty"}: []byte(`kind: Empty`),
1012-
},
1013-
expected: true,
1014-
},
1015-
}
1016-
for _, tt := range tcases {
1017-
t.Run(tt.name, func(t *testing.T) {
1018-
if isKubeadmConfigPresent(tt.gvkmap) != tt.expected {
1019-
t.Error("unexpected result")
1020-
}
1021-
})
1022-
}
1023-
}

cmd/kubeadm/app/util/config/upgradeconfiguration.go

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,34 @@ import (
2222
"github.com/pkg/errors"
2323

2424
"k8s.io/apimachinery/pkg/runtime"
25-
"k8s.io/apimachinery/pkg/util/sets"
2625
"k8s.io/klog/v2"
27-
kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1"
28-
kubeletconfig "k8s.io/kubelet/config/v1beta1"
2926

3027
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3128
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
3229
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
3330
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
3431
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
32+
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
3533
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
3634
"k8s.io/kubernetes/cmd/kubeadm/app/util/config/strict"
3735
)
3836

39-
var componentCfgGV = sets.New(kubeproxyconfig.GroupName, kubeletconfig.GroupName)
40-
4137
// documentMapToUpgradeConfiguration takes a map between GVKs and YAML documents (as returned by SplitYAMLDocuments),
4238
// finds a UpgradeConfiguration, decodes it, dynamically defaults it and then validates it prior to return.
4339
func documentMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated bool) (*kubeadmapi.UpgradeConfiguration, error) {
44-
var internalcfg *kubeadmapi.UpgradeConfiguration
40+
upgradeBytes := []byte{}
4541

4642
for gvk, bytes := range gvkmap {
43+
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvk) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvk) || componentconfigs.Scheme.IsGroupRegistered(gvk.Group) {
44+
klog.Warningf("[config] WARNING: YAML document with GroupVersionKind %v is deprecated for upgrade, please use config file with kind of UpgradeConfiguration instead \n", gvk)
45+
continue
46+
}
47+
48+
if gvk.Kind != constants.UpgradeConfigurationKind {
49+
klog.Warningf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk)
50+
continue
51+
}
52+
4753
// check if this version is supported and possibly not deprecated
4854
if err := validateSupportedVersion(gvk, allowDeprecated, true); err != nil {
4955
return nil, err
@@ -54,37 +60,19 @@ func documentMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap, allowDepre
5460
klog.Warning(err.Error())
5561
}
5662

57-
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvk) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvk) {
58-
klog.Warningf("[config] WARNING: YAML document with GroupVersionKind %v is deprecated for upgrade, please use config file with kind of UpgradeConfiguration instead \n", gvk)
59-
continue
60-
}
61-
62-
if kubeadmutil.GroupVersionKindsHasUpgradeConfiguration(gvk) {
63-
// Set internalcfg to an empty struct value the deserializer will populate
64-
internalcfg = &kubeadmapi.UpgradeConfiguration{}
65-
// Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the
66-
// right external version, defaulted, and converted into the internal version.
67-
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), bytes, internalcfg); err != nil {
68-
return nil, err
69-
}
70-
continue
71-
}
63+
upgradeBytes = bytes
64+
}
7265

73-
// If the group is neither a kubeadm core type or of a supported component config group, we dump a warning about it being ignored
74-
if !componentconfigs.Scheme.IsGroupRegistered(gvk.Group) {
75-
klog.Warningf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk)
76-
}
66+
if len(upgradeBytes) == 0 {
67+
return nil, errors.Errorf("no %s found in the supplied config", constants.UpgradeConfigurationKind)
7768
}
7869

79-
// If UpgradeConfiguration wasn't given, default it by creating an external struct instance, default it and convert into the internal type
80-
if internalcfg == nil {
81-
extinitcfg := &kubeadmapiv1.UpgradeConfiguration{}
82-
kubeadmscheme.Scheme.Default(extinitcfg)
83-
// Set upgradeCfg to an empty struct value the deserializer will populate
84-
internalcfg = &kubeadmapi.UpgradeConfiguration{}
85-
if err := kubeadmscheme.Scheme.Convert(extinitcfg, internalcfg, nil); err != nil {
86-
return nil, err
87-
}
70+
// Set internalcfg to an empty struct value the deserializer will populate
71+
internalcfg := &kubeadmapi.UpgradeConfiguration{}
72+
// Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the
73+
// right external version, defaulted, and converted into the internal version.
74+
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), upgradeBytes, internalcfg); err != nil {
75+
return nil, err
8876
}
8977

9078
// Validates cfg
@@ -96,9 +84,6 @@ func documentMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap, allowDepre
9684
}
9785

9886
// DocMapToUpgradeConfiguration converts documentMap to an internal, defaulted and validated UpgradeConfiguration object.
99-
// The map may contain many different YAML documents. These YAML documents are parsed one-by-one
100-
// and well-known ComponentConfig GroupVersionKinds are stored inside of the internal UpgradeConfiguration struct.
101-
// The resulting UpgradeConfiguration is then dynamically defaulted and validated prior to return.
10287
func DocMapToUpgradeConfiguration(gvkmap kubeadmapi.DocumentMap) (*kubeadmapi.UpgradeConfiguration, error) {
10388
return documentMapToUpgradeConfiguration(gvkmap, false)
10489
}
@@ -123,18 +108,8 @@ func LoadUpgradeConfigurationFromFile(cfgPath string, _ LoadOrDefaultConfigurati
123108
// Convert documentMap to internal UpgradeConfiguration, InitConfiguration and ClusterConfiguration from config file will be ignored.
124109
// Upgrade should respect the cluster configuration from the existing cluster, re-configure the cluster with a InitConfiguration and
125110
// ClusterConfiguration from the config file is not allowed for upgrade.
126-
if isKubeadmConfigPresent(docmap) {
127-
if upgradeCfg, err = DocMapToUpgradeConfiguration(docmap); err != nil {
128-
return nil, err
129-
}
130-
}
131-
132-
// Check is there any component configs defined in the config file.
133-
for gvk := range docmap {
134-
if componentCfgGV.Has(gvk.Group) {
135-
klog.Warningf("[config] WARNING: YAML document with Component Configs %v is deprecated for upgrade and will be ignored \n", gvk.Group)
136-
continue
137-
}
111+
if upgradeCfg, err = DocMapToUpgradeConfiguration(docmap); err != nil {
112+
return nil, err
138113
}
139114

140115
return upgradeCfg, nil

cmd/kubeadm/app/util/config/upgradeconfiguration_test.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ import (
3838

3939
func TestDocMapToUpgradeConfiguration(t *testing.T) {
4040
tests := []struct {
41-
name string
42-
cfg kubeadmapiv1.UpgradeConfiguration
43-
expectedCfg kubeadmapi.UpgradeConfiguration
41+
name string
42+
cfg interface{}
43+
expectedCfg kubeadmapi.UpgradeConfiguration
44+
expectedError bool
4445
}{
4546
{
4647
name: "default config is set correctly",
@@ -103,6 +104,16 @@ func TestDocMapToUpgradeConfiguration(t *testing.T) {
103104
},
104105
},
105106
},
107+
{
108+
name: "no UpgradeConfiguration found",
109+
cfg: kubeadmapiv1.InitConfiguration{
110+
TypeMeta: metav1.TypeMeta{
111+
APIVersion: kubeadmapiv1.SchemeGroupVersion.String(),
112+
Kind: constants.InitConfigurationKind,
113+
},
114+
},
115+
expectedError: true,
116+
},
106117
}
107118

108119
for _, tc := range tests {
@@ -116,11 +127,13 @@ func TestDocMapToUpgradeConfiguration(t *testing.T) {
116127
t.Fatalf("Unexpected error of SplitYAMLDocuments: %v", err)
117128
}
118129
cfg, err := DocMapToUpgradeConfiguration(docmap)
119-
if err != nil {
120-
t.Fatalf("unexpected error of DocMapToUpgradeConfiguration: %v\nconfig: %s", err, string(b))
130+
if (err != nil) != tc.expectedError {
131+
t.Fatalf("failed DocMapToUpgradeConfiguration:\n\texpected error: %t\n\t actual error: %v", tc.expectedError, err)
121132
}
122-
if diff := cmp.Diff(*cfg, tc.expectedCfg, cmpopts.IgnoreFields(kubeadmapi.UpgradeConfiguration{}, "Timeouts")); diff != "" {
123-
t.Fatalf("DocMapToUpgradeConfiguration returned unexpected diff (-want,+got):\n%s", diff)
133+
if err == nil {
134+
if diff := cmp.Diff(*cfg, tc.expectedCfg, cmpopts.IgnoreFields(kubeadmapi.UpgradeConfiguration{}, "Timeouts")); diff != "" {
135+
t.Fatalf("DocMapToUpgradeConfiguration returned unexpected diff (-want,+got):\n%s", diff)
136+
}
124137
}
125138
})
126139
}

0 commit comments

Comments
 (0)