Enforce not using newer kubeadm to upgrade older kubeadm
This commit is contained in:
		@@ -116,6 +116,12 @@ func EnforceVersionPolicies(versionGetter VersionGetter, newK8sVersionStr string
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if kubeadmVersion.Major() > newK8sVersion.Major() ||
 | 
				
			||||||
 | 
							kubeadmVersion.Minor() > newK8sVersion.Minor() {
 | 
				
			||||||
 | 
							skewErrors.Mandatory = append(skewErrors.Mandatory, fmt.Errorf("Kubeadm version %s can only be used to upgrade to Kubernetes versions %d.%d", kubeadmVersionStr, kubeadmVersion.Major(), kubeadmVersion.Minor()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Detect if the version is unstable and the user didn't allow that
 | 
						// Detect if the version is unstable and the user didn't allow that
 | 
				
			||||||
	if err = detectUnstableVersionError(newK8sVersion, newK8sVersionStr, allowExperimentalUpgrades, allowRCUpgrades); err != nil {
 | 
						if err = detectUnstableVersionError(newK8sVersion, newK8sVersionStr, allowExperimentalUpgrades, allowRCUpgrades); err != nil {
 | 
				
			||||||
		skewErrors.Skippable = append(skewErrors.Skippable, err)
 | 
							skewErrors.Skippable = append(skewErrors.Skippable, err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,13 +24,15 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestEnforceVersionPolicies(t *testing.T) {
 | 
					func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name                        string
 | 
				
			||||||
		vg                          *fakeVersionGetter
 | 
							vg                          *fakeVersionGetter
 | 
				
			||||||
		expectedMandatoryErrs       int
 | 
							expectedMandatoryErrs       int
 | 
				
			||||||
		expectedSkippableErrs       int
 | 
							expectedSkippableErrs       int
 | 
				
			||||||
		allowExperimental, allowRCs bool
 | 
							allowExperimental, allowRCs bool
 | 
				
			||||||
		newK8sVersion               string
 | 
							newK8sVersion               string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{ // everything ok
 | 
							{
 | 
				
			||||||
 | 
								name: "minor upgrade",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -38,7 +40,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion: "v1.9.5",
 | 
								newK8sVersion: "v1.9.5",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // everything ok
 | 
							{
 | 
				
			||||||
 | 
								name: "major upgrade",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.2",
 | 
									kubeletVersion: "v1.9.2",
 | 
				
			||||||
@@ -46,7 +49,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion: "v1.10.0",
 | 
								newK8sVersion: "v1.10.0",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // downgrades ok
 | 
							{
 | 
				
			||||||
 | 
								name: "downgrade",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -54,7 +58,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion: "v1.9.2",
 | 
								newK8sVersion: "v1.9.2",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // upgrades without bumping the version number ok
 | 
							{
 | 
				
			||||||
 | 
								name: "same version upgrade",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -62,16 +67,18 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion: "v1.9.3",
 | 
								newK8sVersion: "v1.9.3",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // new version must be higher than v1.9.0
 | 
							{
 | 
				
			||||||
 | 
								name: "new version must be higher than v1.9.0",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
				kubeadmVersion: "v1.9.3",
 | 
									kubeadmVersion: "v1.9.3",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion:         "v1.8.10",
 | 
								newK8sVersion:         "v1.8.10",
 | 
				
			||||||
			expectedMandatoryErrs: 1, // version must be higher than v1.9.0
 | 
								expectedMandatoryErrs: 2, // version must be higher than v1.9.0, can't upgrade old k8s with newer kubeadm
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // upgrading two minor versions in one go is not supported
 | 
							{
 | 
				
			||||||
 | 
								name: "upgrading two minor versions in one go is not supported",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -81,16 +88,18 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			expectedMandatoryErrs: 1, // can't upgrade two minor versions
 | 
								expectedMandatoryErrs: 1, // can't upgrade two minor versions
 | 
				
			||||||
			expectedSkippableErrs: 1, // kubelet <-> apiserver skew too large
 | 
								expectedSkippableErrs: 1, // kubelet <-> apiserver skew too large
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // downgrading two minor versions in one go is not supported
 | 
							{
 | 
				
			||||||
 | 
								name: "downgrading two minor versions in one go is not supported",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.11.3",
 | 
									clusterVersion: "v1.11.3",
 | 
				
			||||||
				kubeletVersion: "v1.11.3",
 | 
									kubeletVersion: "v1.11.3",
 | 
				
			||||||
				kubeadmVersion: "v1.11.0",
 | 
									kubeadmVersion: "v1.11.0",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			newK8sVersion:         "v1.9.3",
 | 
								newK8sVersion:         "v1.9.3",
 | 
				
			||||||
			expectedMandatoryErrs: 1, // can't downgrade two minor versions
 | 
								expectedMandatoryErrs: 2, // can't downgrade two minor versions, can't upgrade old k8s with newer kubeadm
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // kubeadm version must be higher than the new kube version. However, patch version skews may be forced
 | 
							{
 | 
				
			||||||
 | 
								name: "kubeadm version must be higher than the new kube version. However, patch version skews may be forced",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -99,7 +108,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:         "v1.9.5",
 | 
								newK8sVersion:         "v1.9.5",
 | 
				
			||||||
			expectedSkippableErrs: 1,
 | 
								expectedSkippableErrs: 1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // kubeadm version must be higher than the new kube version. Trying to upgrade k8s to a higher minor version than kubeadm itself should never be supported
 | 
							{
 | 
				
			||||||
 | 
								name: "kubeadm version must be higher than the new kube version. Trying to upgrade k8s to a higher minor version than kubeadm itself should never be supported",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -108,7 +118,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:         "v1.10.0",
 | 
								newK8sVersion:         "v1.10.0",
 | 
				
			||||||
			expectedMandatoryErrs: 1,
 | 
								expectedMandatoryErrs: 1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // the maximum skew between the cluster version and the kubelet versions should be one minor version. This may be forced through though.
 | 
							{
 | 
				
			||||||
 | 
								name: "the maximum skew between the cluster version and the kubelet versions should be one minor version. This may be forced through though.",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.8.8",
 | 
									kubeletVersion: "v1.8.8",
 | 
				
			||||||
@@ -117,7 +128,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:         "v1.10.0",
 | 
								newK8sVersion:         "v1.10.0",
 | 
				
			||||||
			expectedSkippableErrs: 1,
 | 
								expectedSkippableErrs: 1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // experimental upgrades supported if the flag is set
 | 
							{
 | 
				
			||||||
 | 
								name: "experimental upgrades supported if the flag is set",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -126,7 +138,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:     "v1.10.0-beta.1",
 | 
								newK8sVersion:     "v1.10.0-beta.1",
 | 
				
			||||||
			allowExperimental: true,
 | 
								allowExperimental: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // release candidate upgrades supported if the flag is set
 | 
							{
 | 
				
			||||||
 | 
								name: "release candidate upgrades supported if the flag is set",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -135,7 +148,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion: "v1.10.0-rc.1",
 | 
								newK8sVersion: "v1.10.0-rc.1",
 | 
				
			||||||
			allowRCs:      true,
 | 
								allowRCs:      true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // release candidate upgrades supported if the flag is set
 | 
							{
 | 
				
			||||||
 | 
								name: "release candidate upgrades supported if the flag is set",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -144,7 +158,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:     "v1.10.0-rc.1",
 | 
								newK8sVersion:     "v1.10.0-rc.1",
 | 
				
			||||||
			allowExperimental: true,
 | 
								allowExperimental: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // the user should not be able to upgrade to an experimental version if they haven't opted into that
 | 
							{
 | 
				
			||||||
 | 
								name: "the user should not be able to upgrade to an experimental version if they haven't opted into that",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -154,7 +169,8 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			allowRCs:              true,
 | 
								allowRCs:              true,
 | 
				
			||||||
			expectedSkippableErrs: 1,
 | 
								expectedSkippableErrs: 1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{ // the user should not be able to upgrade to an release candidate version if they haven't opted into that
 | 
							{
 | 
				
			||||||
 | 
								name: "the user should not be able to upgrade to an release candidate version if they haven't opted into that",
 | 
				
			||||||
			vg: &fakeVersionGetter{
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
				clusterVersion: "v1.9.3",
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
				kubeletVersion: "v1.9.3",
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
@@ -163,9 +179,20 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			newK8sVersion:         "v1.10.0-rc.1",
 | 
								newK8sVersion:         "v1.10.0-rc.1",
 | 
				
			||||||
			expectedSkippableErrs: 1,
 | 
								expectedSkippableErrs: 1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "the user can't use a newer minor version of kubeadm to upgrade an older version of kubeadm",
 | 
				
			||||||
 | 
								vg: &fakeVersionGetter{
 | 
				
			||||||
 | 
									clusterVersion: "v1.9.3",
 | 
				
			||||||
 | 
									kubeletVersion: "v1.9.3",
 | 
				
			||||||
 | 
									kubeadmVersion: "v1.10.0",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								newK8sVersion:         "v1.9.6",
 | 
				
			||||||
 | 
								expectedMandatoryErrs: 1, // can't upgrade old k8s with newer kubeadm
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, rt := range tests {
 | 
						for _, rt := range tests {
 | 
				
			||||||
 | 
							t.Run(rt.name, func(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			newK8sVer, err := version.ParseSemantic(rt.newK8sVersion)
 | 
								newK8sVer, err := version.ParseSemantic(rt.newK8sVersion)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
@@ -179,7 +206,7 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
					t.Errorf("failed TestEnforceVersionPolicies\n\texpected errors but got none")
 | 
										t.Errorf("failed TestEnforceVersionPolicies\n\texpected errors but got none")
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Otherwise, just move on with the next test
 | 
									// Otherwise, just move on with the next test
 | 
				
			||||||
			continue
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if len(actualSkewErrs.Skippable) != rt.expectedSkippableErrs {
 | 
								if len(actualSkewErrs.Skippable) != rt.expectedSkippableErrs {
 | 
				
			||||||
@@ -188,5 +215,6 @@ func TestEnforceVersionPolicies(t *testing.T) {
 | 
				
			|||||||
			if len(actualSkewErrs.Mandatory) != rt.expectedMandatoryErrs {
 | 
								if len(actualSkewErrs.Mandatory) != rt.expectedMandatoryErrs {
 | 
				
			||||||
				t.Errorf("failed TestEnforceVersionPolicies\n\texpected mandatory errors: %d\n\tgot mandatory errors: %d %v", rt.expectedMandatoryErrs, len(actualSkewErrs.Mandatory), *rt.vg)
 | 
									t.Errorf("failed TestEnforceVersionPolicies\n\texpected mandatory errors: %d\n\tgot mandatory errors: %d %v", rt.expectedMandatoryErrs, len(actualSkewErrs.Mandatory), *rt.vg)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user