diff --git a/cmd/kubeadm/app/cmd/upgrade/plan.go b/cmd/kubeadm/app/cmd/upgrade/plan.go index e1a161400a9..7921f408144 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan.go @@ -28,7 +28,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" @@ -118,19 +117,19 @@ func RunPlan(flags *planFlags) error { // Compute which upgrade possibilities there are glog.V(1).Infof("[upgrade/plan] computing upgrade possibilities") - availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates) + availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades, etcdClient, upgradeVars.cfg.FeatureGates, upgradeVars.client) if err != nil { return fmt.Errorf("[upgrade/versions] FATAL: %v", err) } // Tell the user which upgrades are available - printAvailableUpgrades(availUpgrades, os.Stdout, upgradeVars.cfg.FeatureGates, isExternalEtcd) + printAvailableUpgrades(availUpgrades, os.Stdout, isExternalEtcd) return nil } // printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to // TODO look into columnize or some other formatter when time permits instead of using the tabwriter -func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGates map[string]bool, isExternalEtcd bool) { +func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, isExternalEtcd bool) { // Return quickly if no upgrades can be made if len(upgrades) == 0 { @@ -182,11 +181,37 @@ func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGate fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) - if features.Enabled(featureGates, features.CoreDNS) { - fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion) - } else { - fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion) + + // TODO There is currently no way to cleanly output upgrades that involve adding, removing, or changing components + // https://github.com/kubernetes/kubeadm/issues/810 was created to track addressing this. + printCoreDNS, printKubeDNS := false, false + coreDNSBeforeVersion, coreDNSAfterVersion, kubeDNSBeforeVersion, kubeDNSAfterVersion := "", "", "", "" + + switch upgrade.Before.DNSType { + case constants.CoreDNS: + printCoreDNS = true + coreDNSBeforeVersion = upgrade.Before.DNSVersion + case constants.KubeDNS: + printKubeDNS = true + kubeDNSBeforeVersion = upgrade.Before.DNSVersion } + + switch upgrade.After.DNSType { + case constants.CoreDNS: + printCoreDNS = true + coreDNSAfterVersion = upgrade.After.DNSVersion + case constants.KubeDNS: + printKubeDNS = true + kubeDNSAfterVersion = upgrade.After.DNSVersion + } + + if printCoreDNS { + fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", coreDNSBeforeVersion, coreDNSAfterVersion) + } + if printKubeDNS { + fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", kubeDNSBeforeVersion, kubeDNSAfterVersion) + } + if !isExternalEtcd { fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion) } diff --git a/cmd/kubeadm/app/cmd/upgrade/plan_test.go b/cmd/kubeadm/app/cmd/upgrade/plan_test.go index f83c183f15a..f8513d6609c 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan_test.go @@ -60,7 +60,6 @@ func TestSortedSliceFromStringIntMap(t *testing.T) { // TODO Think about modifying this test to be less verbose checking b/c it can be brittle. func TestPrintAvailableUpgrades(t *testing.T) { - featureGates := make(map[string]bool) var tests = []struct { name string upgrades []upgrade.Upgrade @@ -92,12 +91,14 @@ func TestPrintAvailableUpgrades(t *testing.T) { "v1.8.1": 1, }, KubeadmVersion: "v1.8.2", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.8.3", KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, @@ -138,12 +139,14 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.9.0", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0", KubeadmVersion: "v1.9.0", + DNSType: "kube-dns", DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, @@ -182,12 +185,14 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.8.5", KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, @@ -200,12 +205,14 @@ _____________________________________________________________________ "v1.8.3": 1, }, KubeadmVersion: "v1.8.3", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0", KubeadmVersion: "v1.9.0", + DNSType: "kube-dns", DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, @@ -266,12 +273,14 @@ _____________________________________________________________________ "v1.8.5": 1, }, KubeadmVersion: "v1.8.5", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0-beta.1", KubeadmVersion: "v1.9.0-beta.1", + DNSType: "kube-dns", DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, @@ -312,12 +321,14 @@ _____________________________________________________________________ "v1.8.5": 1, }, KubeadmVersion: "v1.8.5", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.0-rc.1", KubeadmVersion: "v1.9.0-rc.1", + DNSType: "kube-dns", DNSVersion: "1.14.10", EtcdVersion: "3.1.12", }, @@ -359,12 +370,14 @@ _____________________________________________________________________ "v1.9.3": 2, }, KubeadmVersion: "v1.9.2", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.3", KubeadmVersion: "v1.9.3", + DNSType: "kube-dns", DNSVersion: "1.14.8", EtcdVersion: "3.1.12", }, @@ -395,6 +408,7 @@ _____________________________________________________________________ `), }, + { name: "external etcd upgrade available", upgrades: []upgrade.Upgrade{ @@ -406,12 +420,14 @@ _____________________________________________________________________ "v1.9.2": 1, }, KubeadmVersion: "v1.9.2", + DNSType: "kube-dns", DNSVersion: "1.14.5", EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ KubeVersion: "v1.9.3", KubeadmVersion: "v1.9.3", + DNSType: "kube-dns", DNSVersion: "1.14.8", EtcdVersion: "3.1.12", }, @@ -443,13 +459,153 @@ Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.3. _____________________________________________________________________ +`), + }, + { + name: "kubedns to coredns", + upgrades: []upgrade.Upgrade{ + { + Description: "kubedns to coredns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest kubedns to coredns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.6 +Kube DNS 1.14.7 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + +`), + }, + { + name: "coredns", + upgrades: []upgrade.Upgrade{ + { + Description: "coredns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.5", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest coredns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.5 1.0.6 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + +`), + }, + { + name: "coredns to kubedns", + upgrades: []upgrade.Upgrade{ + { + Description: "coredns to kubedns", + Before: upgrade.ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.1.11", + }, + After: upgrade.ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.9", + EtcdVersion: "3.2.18", + }, + }, + }, + expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': +COMPONENT CURRENT AVAILABLE +Kubelet 1 x v1.10.2 v1.11.0 + +Upgrade to the latest coredns to kubedns: + +COMPONENT CURRENT AVAILABLE +API Server v1.10.2 v1.11.0 +Controller Manager v1.10.2 v1.11.0 +Scheduler v1.10.2 v1.11.0 +Kube Proxy v1.10.2 v1.11.0 +CoreDNS 1.0.6 +Kube DNS 1.14.9 +Etcd 3.1.11 3.2.18 + +You can now apply the upgrade by executing the following command: + + kubeadm upgrade apply v1.11.0 + +_____________________________________________________________________ + `), }, } for _, rt := range tests { t.Run(rt.name, func(t *testing.T) { rt.buf = bytes.NewBufferString("") - printAvailableUpgrades(rt.upgrades, rt.buf, featureGates, rt.externalEtcd) + printAvailableUpgrades(rt.upgrades, rt.buf, rt.externalEtcd) actualBytes := rt.buf.Bytes() if !bytes.Equal(actualBytes, rt.expectedBytes) { t.Errorf( diff --git a/cmd/kubeadm/app/features/features.go b/cmd/kubeadm/app/features/features.go index f9f5ee281bb..92678008a32 100644 --- a/cmd/kubeadm/app/features/features.go +++ b/cmd/kubeadm/app/features/features.go @@ -30,7 +30,7 @@ const ( // HighAvailability is alpha in v1.9 HighAvailability = "HighAvailability" - // CoreDNS is alpha in v1.9 + // CoreDNS is GA in v1.11 CoreDNS = "CoreDNS" // SelfHosting is alpha in v1.8 and v1.9 @@ -54,7 +54,7 @@ var InitFeatureGates = FeatureList{ StoreCertsInSecrets: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, // We don't want to advertise this feature gate exists in v1.9 to avoid confusion as it is not yet working HighAvailability: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190, HiddenInHelpText: true}, - CoreDNS: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}, MinimumVersion: v190}, + CoreDNS: {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.GA}, MinimumVersion: v190}, DynamicKubeletConfig: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190}, Auditing: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}}, } @@ -92,7 +92,10 @@ func ValidateVersion(allFeatures FeatureList, requestedFeatures map[string]bool, // Enabled indicates whether a feature name has been enabled func Enabled(featureList map[string]bool, featureName string) bool { - return featureList[string(featureName)] + if enabled, ok := featureList[string(featureName)]; ok { + return enabled + } + return InitFeatureGates[string(featureName)].Default } // Supports indicates whether a feature name is supported on the given diff --git a/cmd/kubeadm/app/features/features_test.go b/cmd/kubeadm/app/features/features_test.go index 1d64da4046e..3e050d04650 100644 --- a/cmd/kubeadm/app/features/features_test.go +++ b/cmd/kubeadm/app/features/features_test.go @@ -168,8 +168,8 @@ func TestResolveFeatureGateDependencies(t *testing.T) { expectedFeatures: map[string]bool{}, }, { // others flags - inputFeatures: map[string]bool{CoreDNS: true}, - expectedFeatures: map[string]bool{CoreDNS: true}, + inputFeatures: map[string]bool{CoreDNS: false}, + expectedFeatures: map[string]bool{CoreDNS: false}, }, { // just StoreCertsInSecrets flags inputFeatures: map[string]bool{StoreCertsInSecrets: true}, @@ -189,3 +189,16 @@ func TestResolveFeatureGateDependencies(t *testing.T) { } } } + +// TestEnabledDefaults tests that Enabled returns the default values for +// each feature gate when no feature gates are specified. +func TestEnabledDefaults(t *testing.T) { + for featureName, feature := range InitFeatureGates { + featureList := make(map[string]bool) + + enabled := Enabled(featureList, featureName) + if enabled != feature.Default { + t.Errorf("Enabled returned %v instead of default value %v for feature %s", enabled, feature.Default, featureName) + } + } +} diff --git a/cmd/kubeadm/app/phases/addons/dns/dns.go b/cmd/kubeadm/app/phases/addons/dns/dns.go index 55ba3cb0a1c..d0207f1b433 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -48,6 +48,28 @@ const ( kubeDNSFederation = "federations" ) +// DeployedDNSAddon returns the type of DNS addon currently deployed +func DeployedDNSAddon(client clientset.Interface) (string, string, error) { + deploymentsClient := client.AppsV1().Deployments(metav1.NamespaceSystem) + deployments, err := deploymentsClient.List(metav1.ListOptions{LabelSelector: "k8s-app=kube-dns"}) + if err != nil { + return "", "", fmt.Errorf("couldn't retrieve DNS addon deployments: %v", err) + } + + switch len(deployments.Items) { + case 0: + return "", "", nil + case 1: + addonName := deployments.Items[0].Name + addonImage := deployments.Items[0].Spec.Template.Spec.Containers[0].Image + addonImageParts := strings.Split(addonImage, ":") + addonVersion := addonImageParts[len(addonImageParts)-1] + return addonName, addonVersion, nil + default: + return "", "", fmt.Errorf("multiple DNS addon deployments found: %v", deployments.Items) + } +} + // EnsureDNSAddon creates the kube-dns or CoreDNS addon func EnsureDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) diff --git a/cmd/kubeadm/app/phases/upgrade/BUILD b/cmd/kubeadm/app/phases/upgrade/BUILD index f6d79128d0b..2e916fdae05 100644 --- a/cmd/kubeadm/app/phases/upgrade/BUILD +++ b/cmd/kubeadm/app/phases/upgrade/BUILD @@ -91,6 +91,10 @@ go_test( "//pkg/util/version:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", + "//vendor/k8s.io/api/apps/v1:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/upgrade/compute.go b/cmd/kubeadm/app/phases/upgrade/compute.go index dca2c9939f8..a149dc887e2 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute.go +++ b/cmd/kubeadm/app/phases/upgrade/compute.go @@ -20,6 +20,7 @@ import ( "fmt" "strings" + clientset "k8s.io/client-go/kubernetes" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" @@ -67,6 +68,8 @@ func ActiveDNSAddon(featureGates map[string]bool) string { type ClusterState struct { // KubeVersion describes the version of the Kubernetes API Server, Controller Manager, Scheduler and Proxy. KubeVersion string + // DNSType + DNSType string // DNSVersion describes the version of the kube-dns images used and manifest version DNSVersion string // KubeadmVersion describes the version of the kubeadm CLI @@ -79,7 +82,7 @@ type ClusterState struct { // GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which // kinds of upgrades can be performed -func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, etcdClient etcdutil.ClusterInterrogator, featureGates map[string]bool) ([]Upgrade, error) { +func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, etcdClient etcdutil.ClusterInterrogator, featureGates map[string]bool, client clientset.Interface) ([]Upgrade, error) { fmt.Println("[upgrade] Fetching available versions to upgrade to") // Collect the upgrades kubeadm can do in this list @@ -117,10 +120,16 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA return upgrades, err } + dnsType, dnsVersion, err := dns.DeployedDNSAddon(client) + if err != nil { + return nil, err + } + // Construct a descriptor for the current state of the world beforeState := ClusterState{ KubeVersion: clusterVersionStr, - DNSVersion: dns.GetDNSVersion(clusterVersion, ActiveDNSAddon(featureGates)), + DNSType: dnsType, + DNSVersion: dnsVersion, KubeadmVersion: kubeadmVersionStr, KubeletVersions: kubeletVersions, EtcdVersion: etcdVersion, @@ -163,6 +172,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: patchVersionStr, + DNSType: ActiveDNSAddon(featureGates), DNSVersion: dns.GetDNSVersion(patchVersion, ActiveDNSAddon(featureGates)), KubeadmVersion: newKubeadmVer, EtcdVersion: getSuggestedEtcdVersion(patchVersionStr), @@ -179,6 +189,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: stableVersionStr, + DNSType: ActiveDNSAddon(featureGates), DNSVersion: dns.GetDNSVersion(stableVersion, ActiveDNSAddon(featureGates)), KubeadmVersion: stableVersionStr, EtcdVersion: getSuggestedEtcdVersion(stableVersionStr), @@ -224,6 +235,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: previousBranchLatestVersionStr, + DNSType: ActiveDNSAddon(featureGates), DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, ActiveDNSAddon(featureGates)), KubeadmVersion: previousBranchLatestVersionStr, EtcdVersion: getSuggestedEtcdVersion(previousBranchLatestVersionStr), @@ -250,6 +262,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA Before: beforeState, After: ClusterState{ KubeVersion: unstableKubeVersion, + DNSType: ActiveDNSAddon(featureGates), DNSVersion: unstableKubeDNSVersion, KubeadmVersion: unstableKubeVersion, EtcdVersion: getSuggestedEtcdVersion(unstableKubeVersion), diff --git a/cmd/kubeadm/app/phases/upgrade/compute_test.go b/cmd/kubeadm/app/phases/upgrade/compute_test.go index c5341a75f2f..75930febbdb 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute_test.go +++ b/cmd/kubeadm/app/phases/upgrade/compute_test.go @@ -23,6 +23,11 @@ import ( "time" "github.com/coreos/etcd/clientv3" + apps "k8s.io/api/apps/v1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientsetfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" versionutil "k8s.io/kubernetes/pkg/util/version" ) @@ -103,7 +108,6 @@ func (f fakeEtcdClient) GetClusterVersions() (map[string]string, error) { } func TestGetAvailableUpgrades(t *testing.T) { - featureGates := make(map[string]bool) etcdClient := fakeEtcdClient{} tests := []struct { name string @@ -112,6 +116,9 @@ func TestGetAvailableUpgrades(t *testing.T) { allowExperimental, allowRCs bool errExpected bool etcdClient etcdutil.ClusterInterrogator + beforeDNSType string + beforeDNSVersion string + featureGates map[string]bool }{ { name: "no action needed, already up-to-date", @@ -123,6 +130,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.9.3", stableVersion: "v1.9.3", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "v1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{}, allowExperimental: false, errExpected: false, @@ -138,6 +148,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.9.3", stableVersion: "v1.9.3", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "version in the v1.9 series", @@ -147,13 +160,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.1": 1, }, KubeadmVersion: "v1.9.2", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.9.3", KubeadmVersion: "v1.9.3", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -172,6 +187,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.9.3", stableVersion: "v1.9.3", }, ""), + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "version in the v1.9 series", @@ -181,13 +199,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.1": 1, }, KubeadmVersion: "v1.9.2", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.9.3", KubeadmVersion: "v1.9.3", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -206,6 +226,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.9.1", stableVersion: "v1.10.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "stable version", @@ -215,13 +238,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.1": 1, }, KubeadmVersion: "v1.10.0", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0", KubeadmVersion: "v1.10.0", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -240,6 +265,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.9.5", stableVersion: "v1.10.1", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "version in the v1.9 series", @@ -249,13 +277,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.3": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.9.5", KubeadmVersion: "v1.9.5", // Note: The kubeadm version mustn't be "downgraded" here - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -267,13 +297,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.3": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.1", KubeadmVersion: "v1.10.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -293,6 +325,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stableVersion: "v1.9.5", latestVersion: "v1.10.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "v1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{}, allowExperimental: true, errExpected: false, @@ -309,6 +344,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stableVersion: "v1.9.5", latestVersion: "v1.10.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", @@ -318,13 +356,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0-alpha.2", KubeadmVersion: "v1.10.0-alpha.2", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -344,6 +384,9 @@ func TestGetAvailableUpgrades(t *testing.T) { stableVersion: "v1.9.5", latestVersion: "v1.10.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", @@ -353,13 +396,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0-alpha.2", KubeadmVersion: "v1.10.0-alpha.2", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -380,6 +425,9 @@ func TestGetAvailableUpgrades(t *testing.T) { latestDevBranchVersion: "v1.10.0-beta.1", latestVersion: "v1.11.0-alpha.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", @@ -389,13 +437,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0-beta.1", KubeadmVersion: "v1.10.0-beta.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -416,6 +466,9 @@ func TestGetAvailableUpgrades(t *testing.T) { latestDevBranchVersion: "v1.10.0-rc.1", latestVersion: "v1.11.0-alpha.1", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "release candidate version", @@ -425,13 +478,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0-rc.1", KubeadmVersion: "v1.10.0-rc.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -452,6 +507,9 @@ func TestGetAvailableUpgrades(t *testing.T) { latestDevBranchVersion: "v1.10.6-rc.1", latestVersion: "v1.11.1-alpha.0", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "experimental version", // Note that this is considered an experimental version in this uncommon scenario @@ -461,13 +519,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.6-rc.1", KubeadmVersion: "v1.10.6-rc.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -488,6 +548,9 @@ func TestGetAvailableUpgrades(t *testing.T) { latestDevBranchVersion: "v1.10.0-rc.1", latestVersion: "v1.11.0-alpha.2", }, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "release candidate version", @@ -497,13 +560,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.10.0-rc.1", KubeadmVersion: "v1.10.0-rc.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, }, @@ -515,13 +580,15 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.9.5": 1, }, KubeadmVersion: "v1.9.5", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.11.0-alpha.2", KubeadmVersion: "v1.11.0-alpha.2", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.2.18", }, }, @@ -553,7 +620,10 @@ func TestGetAvailableUpgrades(t *testing.T) { kubeletVersion: "v1.10.0", kubeadmVersion: "v1.10.1", }, "v1.11.1"), - etcdClient: etcdClient, + etcdClient: etcdClient, + beforeDNSType: constants.CoreDNS, + beforeDNSVersion: "1.0.6", + featureGates: make(map[string]bool), expectedUpgrades: []Upgrade{ { Description: "version in the v1.1 series", @@ -563,12 +633,88 @@ func TestGetAvailableUpgrades(t *testing.T) { "v1.10.0": 1, }, KubeadmVersion: "v1.10.1", - DNSVersion: "1.14.10", + DNSType: "coredns", + DNSVersion: "1.0.6", EtcdVersion: "3.1.12", }, After: ClusterState{ KubeVersion: "v1.11.1", KubeadmVersion: "v1.11.1", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + }, + { + name: "kubedns to coredns", + vg: &fakeVersionGetter{ + clusterVersion: "v1.10.2", + kubeletVersion: "v1.10.2", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.11.0", + + stablePatchVersion: "v1.11.0", + stableVersion: "v1.11.0", + }, + etcdClient: etcdClient, + beforeDNSType: constants.KubeDNS, + beforeDNSVersion: "1.14.7", + featureGates: make(map[string]bool), + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.1 series", + Before: ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "coredns", + DNSVersion: "1.0.6", + EtcdVersion: "3.2.18", + }, + }, + }, + }, + { + name: "keep coredns", + vg: &fakeVersionGetter{ + clusterVersion: "v1.10.2", + kubeletVersion: "v1.10.2", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.11.0", + + stablePatchVersion: "v1.11.0", + stableVersion: "v1.11.0", + }, + etcdClient: etcdClient, + beforeDNSType: constants.KubeDNS, + beforeDNSVersion: "1.14.7", + featureGates: map[string]bool{"CoreDNS": false}, + expectedUpgrades: []Upgrade{ + { + Description: "version in the v1.1 series", + Before: ClusterState{ + KubeVersion: "v1.10.2", + KubeletVersions: map[string]uint16{ + "v1.10.2": 1, + }, + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.12", + }, + After: ClusterState{ + KubeVersion: "v1.11.0", + KubeadmVersion: "v1.11.0", + DNSType: "kube-dns", DNSVersion: "1.14.10", EtcdVersion: "3.2.18", }, @@ -581,10 +727,36 @@ func TestGetAvailableUpgrades(t *testing.T) { // kubernetes release. for _, rt := range tests { t.Run(rt.name, func(t *testing.T) { - actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, rt.etcdClient, featureGates) - fmt.Printf("actualErr: %v\n", actualErr) - fmt.Printf("actualErr != nil: %v\n", actualErr != nil) - fmt.Printf("errExpected: %v\n", rt.errExpected) + + client := clientsetfake.NewSimpleClientset(&apps.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: rt.beforeDNSType, + Namespace: "kube-system", + Labels: map[string]string{ + "k8s-app": "kube-dns", + }, + }, + Spec: apps.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Image: "test:" + rt.beforeDNSVersion, + }, + }, + }, + }, + }, + }) + + actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, rt.etcdClient, rt.featureGates, client) + if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) { + t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades) + } if (actualErr != nil) != rt.errExpected { fmt.Printf("Hello error") t.Errorf("failed TestGetAvailableUpgrades\n\texpected error: %t\n\tgot error: %t", rt.errExpected, (actualErr != nil))