diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index c5bfa27083a..95c9ed77579 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -51,7 +51,6 @@ go_library( "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/audit:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 1c0a14984d7..0b02142c349 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -48,7 +48,6 @@ import ( clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" - controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster" @@ -58,7 +57,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/preflight" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" - auditutil "k8s.io/kubernetes/cmd/kubeadm/app/util/audit" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" @@ -169,6 +167,7 @@ func NewCmdInit(out io.Writer) *cobra.Command { initRunner.AppendPhase(phases.NewKubeletStartPhase()) initRunner.AppendPhase(phases.NewCertsPhase()) initRunner.AppendPhase(phases.NewKubeConfigPhase()) + initRunner.AppendPhase(phases.NewControlPlanePhase()) // TODO: add other phases to the runner. // sets the data builder function, that will be used by the runner @@ -425,7 +424,6 @@ func runInit(i *initData, out io.Writer) error { // Get directories to write files to; can be faked if we're dry-running glog.V(1).Infof("[init] Getting certificates directory from configuration") - realCertsDir := i.cfg.CertificatesDir certsDirToWriteTo, kubeConfigDir, manifestDir, _, err := getDirectoriesToUse(i.dryRun, i.dryRunDir, i.cfg.CertificatesDir) if err != nil { return errors.Wrap(err, "error getting directories to use") @@ -436,31 +434,6 @@ func runInit(i *initData, out io.Writer) error { adminKubeConfigPath := filepath.Join(kubeConfigDir, kubeadmconstants.AdminKubeConfigFileName) - if features.Enabled(i.cfg.FeatureGates, features.Auditing) { - // Setup the AuditPolicy (either it was passed in and exists or it wasn't passed in and generate a default policy) - if i.cfg.AuditPolicyConfiguration.Path != "" { - // TODO(chuckha) ensure passed in audit policy is valid so users don't have to find the error in the api server log. - if _, err := os.Stat(i.cfg.AuditPolicyConfiguration.Path); err != nil { - return errors.Wrapf(err, "error getting file info for audit policy file %q", i.cfg.AuditPolicyConfiguration.Path) - } - } else { - i.cfg.AuditPolicyConfiguration.Path = filepath.Join(kubeConfigDir, kubeadmconstants.AuditPolicyDir, kubeadmconstants.AuditPolicyFile) - if err := auditutil.CreateDefaultAuditLogPolicy(i.cfg.AuditPolicyConfiguration.Path); err != nil { - return errors.Wrapf(err, "error creating default audit policy %q ", i.cfg.AuditPolicyConfiguration.Path) - } - } - } - - // Temporarily set cfg.CertificatesDir to the "real value" when writing controlplane manifests - // This is needed for writing the right kind of manifests - i.cfg.CertificatesDir = realCertsDir - - // PHASE 3: Bootstrap the control plane - glog.V(1).Infof("[init] bootstraping the control plane") - glog.V(1).Infof("[init] creating static pod manifest") - if err := controlplanephase.CreateInitStaticPodManifestFiles(manifestDir, i.cfg); err != nil { - return errors.Wrap(err, "error creating init static pod manifest files") - } // Add etcd static pod spec only if external etcd is not configured if i.cfg.Etcd.External == nil { glog.V(1).Infof("[init] no external etcd found. Creating manifest for local etcd static pod") @@ -469,9 +442,6 @@ func runInit(i *initData, out io.Writer) error { } } - // Revert the earlier CertificatesDir assignment to the directory that can be written to - i.cfg.CertificatesDir = certsDirToWriteTo - // If we're dry-running, print the generated manifests if err := printFilesIfDryRunning(i.dryRun, manifestDir); err != nil { return errors.Wrap(err, "error printing files on dryrun") diff --git a/cmd/kubeadm/app/cmd/phases/BUILD b/cmd/kubeadm/app/cmd/phases/BUILD index 1eac7f5ae17..5bb49f8242e 100644 --- a/cmd/kubeadm/app/cmd/phases/BUILD +++ b/cmd/kubeadm/app/cmd/phases/BUILD @@ -46,6 +46,7 @@ go_library( "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", + "//cmd/kubeadm/app/util/audit:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//pkg/util/normalizer:go_default_library", @@ -53,7 +54,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library", "//vendor/github.com/golang/glog:go_default_library", @@ -68,7 +68,6 @@ go_test( name = "go_default_test", srcs = [ "addons_test.go", - "controlplane_test.go", "etcd_test.go", "kubeconfig_test.go", "kubelet_test.go", diff --git a/cmd/kubeadm/app/cmd/phases/controlplane.go b/cmd/kubeadm/app/cmd/phases/controlplane.go index 8882311e9f2..40ee1d95609 100644 --- a/cmd/kubeadm/app/cmd/phases/controlplane.go +++ b/cmd/kubeadm/app/cmd/phases/controlplane.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,186 +17,122 @@ limitations under the License. package phases import ( + "errors" "fmt" - "strings" + "os" + "path/filepath" - "github.com/spf13/cobra" - - utilflag "k8s.io/apiserver/pkg/util/flag" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" - kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" - kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" - cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" - controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" + "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" + auditutil "k8s.io/kubernetes/cmd/kubeadm/app/util/audit" "k8s.io/kubernetes/pkg/util/normalizer" ) var ( - allControlplaneLongDesc = normalizer.LongDesc(` - Generates all static Pod manifest files necessary to establish the control plane. - ` + cmdutil.AlphaDisclaimer) - - allControlplaneExample = normalizer.Examples(` + controlPlaneExample = normalizer.Examples(` # Generates all static Pod manifest files for control plane components, - # functionally equivalent to what generated by kubeadm init. - kubeadm alpha phase controlplane all + # functionally equivalent to what is generated by kubeadm init. + kubeadm init phase control-plane # Generates all static Pod manifest files using options read from a configuration file. - kubeadm alpha phase controlplane --config masterconfiguration.yaml + kubeadm init phase control-plane --config config.yaml `) - apiServerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Generates the static Pod manifest file for the API server and saves it into %s file. - `+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, kubeadmconstants.GetStaticPodDirectory())) - - controllerManagerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Generates the static Pod manifest file for the controller-manager and saves it into %s file. - `+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeControllerManager, kubeadmconstants.GetStaticPodDirectory())) - - schedulerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(` - Generates the static Pod manifest file for the scheduler and saves it into %s file. - `+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeScheduler, kubeadmconstants.GetStaticPodDirectory())) + controlPlanePhaseProperties = map[string]struct { + name string + short string + }{ + kubeadmconstants.KubeAPIServer: { + name: "apiserver", + short: getPhaseDescription(kubeadmconstants.KubeAPIServer), + }, + kubeadmconstants.KubeControllerManager: { + name: "controller-manager", + short: getPhaseDescription(kubeadmconstants.KubeControllerManager), + }, + kubeadmconstants.KubeScheduler: { + name: "scheduler", + short: getPhaseDescription(kubeadmconstants.KubeScheduler), + }, + } ) -// NewCmdControlplane returns main command for Controlplane phase -func NewCmdControlplane() *cobra.Command { - cmd := &cobra.Command{ - Use: "controlplane", - Short: "Generates all static Pod manifest files necessary to establish the control plane", - Long: cmdutil.MacroCommandLongDescription, - } - - manifestPath := kubeadmconstants.GetStaticPodDirectory() - cmd.AddCommand(getControlPlaneSubCommands(manifestPath, "")...) - return cmd +type controlPlaneData interface { + Cfg() *kubeadmapi.InitConfiguration + KubeConfigDir() string + ManifestDir() string } -// getControlPlaneSubCommands returns sub commands for Controlplane phase -func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command { - - cfg := &kubeadmapiv1beta1.InitConfiguration{} - - // This is used for unit testing only... - // If we wouldn't set this to something, the code would dynamically look up the version from the internet - // By setting this explicitly for tests workarounds that - if defaultKubernetesVersion != "" { - cfg.KubernetesVersion = defaultKubernetesVersion - } - - // Default values for the cobra help text - kubeadmscheme.Scheme.Default(cfg) - - var cfgPath, featureGatesString string - var subCmds []*cobra.Command - - subCmdProperties := []struct { - use string - short string - long string - examples string - cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration) error - }{ - { - use: "all", - short: "Generates all static Pod manifest files necessary to establish the control plane", - long: allControlplaneLongDesc, - examples: allControlplaneExample, - cmdFunc: controlplanephase.CreateInitStaticPodManifestFiles, - }, - { - use: "apiserver", - short: "Generates the API server static Pod manifest", - long: apiServerControlplaneLongDesc, - cmdFunc: controlplanephase.CreateAPIServerStaticPodManifestFile, - }, - { - use: "controller-manager", - short: "Generates the controller-manager static Pod manifest", - long: controllerManagerControlplaneLongDesc, - cmdFunc: controlplanephase.CreateControllerManagerStaticPodManifestFile, - }, - { - use: "scheduler", - short: "Generates the scheduler static Pod manifest", - long: schedulerControlplaneLongDesc, - cmdFunc: controlplanephase.CreateSchedulerStaticPodManifestFile, - }, - } - - for _, properties := range subCmdProperties { - // Creates the UX Command - cmd := &cobra.Command{ - Use: properties.use, - Short: properties.short, - Long: properties.long, - Example: properties.examples, - Run: runCmdControlPlane(properties.cmdFunc, &outDir, &cfgPath, &featureGatesString, cfg), - } - - // Add flags to the command - cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`) - cmd.Flags().StringVar(&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, `Choose a specific Kubernetes version for the control plane`) - - if properties.use == "all" || properties.use == "apiserver" { - cmd.Flags().StringVar(&cfg.APIEndpoint.AdvertiseAddress, "apiserver-advertise-address", cfg.APIEndpoint.AdvertiseAddress, "The IP address of the API server is accessible on") - cmd.Flags().Int32Var(&cfg.APIEndpoint.BindPort, "apiserver-bind-port", cfg.APIEndpoint.BindPort, "The port the API server is accessible on") - cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "The range of IP address used for service VIPs") - cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+ - "Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n")) - cmd.Flags().Var(utilflag.NewMapStringString(&cfg.APIServerExtraArgs), "apiserver-extra-args", "A set of extra flags to pass to the API Server or override default ones in form of =") - } - - if properties.use == "all" || properties.use == "controller-manager" { - cmd.Flags().StringVar(&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet, "The range of IP addresses used for the Pod network") - cmd.Flags().Var(utilflag.NewMapStringString(&cfg.ControllerManagerExtraArgs), "controller-manager-extra-args", "A set of extra flags to pass to the Controller Manager or override default ones in form of =") - } - - if properties.use == "all" || properties.use == "scheduler" { - cmd.Flags().Var(utilflag.NewMapStringString(&cfg.SchedulerExtraArgs), "scheduler-extra-args", "A set of extra flags to pass to the Scheduler or override default ones in form of =") - } - - cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental") - - subCmds = append(subCmds, cmd) - } - - return subCmds +func getPhaseDescription(component string) string { + return fmt.Sprintf("Generates the %s static Pod manifest", component) } -// runCmdControlPlane creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runCmdControlPlane(cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration) error, outDir, cfgPath *string, featureGatesString *string, cfg *kubeadmapiv1beta1.InitConfiguration) func(cmd *cobra.Command, args []string) { +// NewControlPlanePhase creates a kubeadm workflow phase that implements bootstrapping the control plane. +func NewControlPlanePhase() workflow.Phase { + phase := workflow.Phase{ + Name: "control-plane", + Short: "Generates all static Pod manifest files necessary to establish the control plane", + Example: controlPlaneExample, + Phases: []workflow.Phase{ + newControlPlaneSubPhase(kubeadmconstants.KubeAPIServer), + newControlPlaneSubPhase(kubeadmconstants.KubeControllerManager), + newControlPlaneSubPhase(kubeadmconstants.KubeScheduler), + }, + Run: runControlPlanePhase, + } + return phase +} - // the following statement build a closure that wraps a call to a cmdFunc, binding - // the function itself with the specific parameters of each sub command. - // Please note that specific parameter should be passed as value, while other parameters - passed as reference - - // are shared between sub commands and gets access to current value e.g. flags value. - return func(cmd *cobra.Command, args []string) { - var err error - if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil { - kubeadmutil.CheckErr(err) +func newControlPlaneSubPhase(component string) workflow.Phase { + phase := workflow.Phase{ + Name: controlPlanePhaseProperties[component].name, + Short: controlPlanePhaseProperties[component].short, + Run: runControlPlaneSubPhase(component), + } + return phase +} + +func runControlPlanePhase(c workflow.RunData) error { + data, ok := c.(controlPlaneData) + if !ok { + return errors.New("control-plane phase invoked with an invalid data struct") + } + + fmt.Printf("[control-plane] Using manifest folder %q\n", data.ManifestDir()) + return nil +} + +func runControlPlaneSubPhase(component string) func(c workflow.RunData) error { + return func(c workflow.RunData) error { + data, ok := c.(controlPlaneData) + if !ok { + return errors.New("control-plane phase invoked with an invalid data struct") + } + cfg := data.Cfg() + + // special case to handle audit policy for the API server + if component == kubeadmconstants.KubeAPIServer && features.Enabled(cfg.FeatureGates, features.Auditing) { + // Setup the AuditPolicy (either it was passed in and exists or it wasn't passed in and generate a default policy) + if cfg.AuditPolicyConfiguration.Path != "" { + // TODO(chuckha) ensure passed in audit policy is valid so users don't have to find the error in the api server log. + if _, err := os.Stat(cfg.AuditPolicyConfiguration.Path); err != nil { + return fmt.Errorf("error getting file info for audit policy file %q [%v]", cfg.AuditPolicyConfiguration.Path, err) + } + } else { + cfg.AuditPolicyConfiguration.Path = filepath.Join(data.KubeConfigDir(), kubeadmconstants.AuditPolicyDir, kubeadmconstants.AuditPolicyFile) + if err := auditutil.CreateDefaultAuditLogPolicy(cfg.AuditPolicyConfiguration.Path); err != nil { + return fmt.Errorf("error creating default audit policy %q [%v]", cfg.AuditPolicyConfiguration.Path, err) + } + } } - if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, *featureGatesString); err != nil { - kubeadmutil.CheckErr(err) + fmt.Printf("[control-plane] creating static Pod manifest for %q\n", component) + if err := controlplane.CreateStaticPodFiles(data.ManifestDir(), cfg, component); err != nil { + return err } - - // This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags - internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg) - kubeadmutil.CheckErr(err) - err = configutil.VerifyAPIServerBindAddress(internalcfg.APIEndpoint.AdvertiseAddress) - kubeadmutil.CheckErr(err) - - if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil { - kubeadmutil.CheckErr(err) - } - - // Execute the cmdFunc - err = cmdFunc(*outDir, internalcfg) - kubeadmutil.CheckErr(err) + return nil } } diff --git a/cmd/kubeadm/app/cmd/phases/controlplane_test.go b/cmd/kubeadm/app/cmd/phases/controlplane_test.go deleted file mode 100644 index dc745129bb1..00000000000 --- a/cmd/kubeadm/app/cmd/phases/controlplane_test.go +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package phases - -import ( - "fmt" - "os" - "testing" - - testutil "k8s.io/kubernetes/cmd/kubeadm/test" - cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" -) - -const phaseTestK8sVersion = "v1.11.0" - -func TestControlPlaneSubCommandsHasFlags(t *testing.T) { - - subCmds := getControlPlaneSubCommands("", phaseTestK8sVersion) - - commonFlags := []string{ - "cert-dir", - "config", - } - - var tests = []struct { - command string - additionalFlags []string - }{ - { - command: "all", - additionalFlags: []string{ - "kubernetes-version", - "apiserver-advertise-address", - "apiserver-bind-port", - "service-cidr", - "pod-network-cidr", - "feature-gates", - }, - }, - { - command: "apiserver", - additionalFlags: []string{ - "kubernetes-version", - "apiserver-advertise-address", - "apiserver-bind-port", - "service-cidr", - "feature-gates", - }, - }, - { - command: "controller-manager", - additionalFlags: []string{ - "kubernetes-version", - "pod-network-cidr", - }, - }, - { - command: "scheduler", - additionalFlags: []string{ - "kubernetes-version", - }, - }, - } - - for _, test := range tests { - expectedFlags := append(commonFlags, test.additionalFlags...) - cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...) - } -} - -func TestControlPlaneCreateFilesWithFlags(t *testing.T) { - - var tests = []struct { - command string - additionalFlags []string - expectedFiles []string - }{ - { - command: "all", - additionalFlags: []string{ - "--kubernetes-version=v1.11.0", - "--apiserver-advertise-address=1.2.3.4", - "--apiserver-bind-port=6443", - "--service-cidr=1.2.3.4/16", - "--pod-network-cidr=1.2.3.4/16", - }, - expectedFiles: []string{ - "kube-apiserver.yaml", - "kube-controller-manager.yaml", - "kube-scheduler.yaml", - }, - }, - { - command: "apiserver", - additionalFlags: []string{ - "--kubernetes-version=v1.11.0", - "--apiserver-advertise-address=1.2.3.4", - "--apiserver-bind-port=6443", - "--service-cidr=1.2.3.4/16", - }, - expectedFiles: []string{"kube-apiserver.yaml"}, - }, - { - command: "controller-manager", - additionalFlags: []string{ - "--kubernetes-version=v1.11.0", - "--pod-network-cidr=1.2.3.4/16", - }, - expectedFiles: []string{"kube-controller-manager.yaml"}, - }, - { - command: "scheduler", - additionalFlags: []string{ - "--kubernetes-version=v1.11.0", - }, - expectedFiles: []string{"kube-scheduler.yaml"}, - }, - } - - for _, test := range tests { - - // Create temp folder for the test case - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) - - // Get subcommands working in the temporary directory - subCmds := getControlPlaneSubCommands(tmpdir, phaseTestK8sVersion) - - // Execute the subcommand - certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir) - allFlags := append(test.additionalFlags, certDirFlag) - cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...) - - // Checks that requested files are there - testutil.AssertFileExists(t, tmpdir, test.expectedFiles...) - } -} diff --git a/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go b/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go index 24392ccb030..26cfd3203b6 100644 --- a/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go +++ b/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go @@ -46,6 +46,8 @@ func TestKubeConfigCSubCommandsHasFlags(t *testing.T) { cmdtestutil.AssertSubCommandHasFlags(t, []*cobra.Command{cmd}, "user", flags...) } +const phaseTestK8sVersion = "v1.11.0" + func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) { // Temporary folders for the test case diff --git a/cmd/kubeadm/app/cmd/phases/phase.go b/cmd/kubeadm/app/cmd/phases/phase.go index 1ecd0a9ad9d..bce2b4d243e 100644 --- a/cmd/kubeadm/app/cmd/phases/phase.go +++ b/cmd/kubeadm/app/cmd/phases/phase.go @@ -34,7 +34,6 @@ func NewCmdPhase(out io.Writer) *cobra.Command { cmd.AddCommand(NewCmdAddon()) cmd.AddCommand(NewCmdBootstrapToken()) cmd.AddCommand(NewCmdCerts()) - cmd.AddCommand(NewCmdControlplane()) cmd.AddCommand(NewCmdEtcd()) cmd.AddCommand(NewCmdKubelet()) cmd.AddCommand(NewCmdKubeConfig(out)) diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index 665d606637d..aab929cc790 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -42,26 +42,8 @@ import ( // CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane. func CreateInitStaticPodManifestFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration) error { - glog.V(1).Infoln("[controlplane] creating static pod files") - return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler) -} - -// CreateAPIServerStaticPodManifestFile will write APIserver static pod manifest file. -func CreateAPIServerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.InitConfiguration) error { - glog.V(1).Infoln("creating APIserver static pod files") - return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeAPIServer) -} - -// CreateControllerManagerStaticPodManifestFile will write controller manager static pod manifest file. -func CreateControllerManagerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.InitConfiguration) error { - glog.V(1).Infoln("creating controller manager static pod files") - return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeControllerManager) -} - -// CreateSchedulerStaticPodManifestFile will write scheduler static pod manifest file. -func CreateSchedulerStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.InitConfiguration) error { - glog.V(1).Infoln("creating scheduler static pod files") - return createStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeScheduler) + glog.V(1).Infoln("[control-plane] creating static Pod files") + return CreateStaticPodFiles(manifestDir, cfg, kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler) } // GetStaticPodSpecs returns all staticPodSpecs actualized to the context of the current InitConfiguration @@ -106,8 +88,8 @@ func GetStaticPodSpecs(cfg *kubeadmapi.InitConfiguration, k8sVersion *version.Ve return staticPodSpecs } -// createStaticPodFiles creates all the requested static pod files. -func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration, componentNames ...string) error { +// CreateStaticPodFiles creates all the requested static pod files. +func CreateStaticPodFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration, componentNames ...string) error { // TODO: Move the "pkg/util/version".Version object into the internal API instead of always parsing the string k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion) if err != nil { @@ -115,7 +97,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration, } // gets the StaticPodSpecs, actualized for the current InitConfiguration - glog.V(1).Infoln("[controlplane] getting StaticPodSpecs") + glog.V(1).Infoln("[control-plane] getting StaticPodSpecs") specs := GetStaticPodSpecs(cfg, k8sVersion) // creates required static pod specs @@ -123,7 +105,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration, // retrives the StaticPodSpec for given component spec, exists := specs[componentName] if !exists { - return errors.Errorf("couldn't retrive StaticPodSpec for %s", componentName) + return errors.Errorf("couldn't retrive StaticPodSpec for %q", componentName) } // writes the StaticPodSpec to disk @@ -131,7 +113,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.InitConfiguration, return errors.Wrapf(err, "failed to create static pod manifest file for %q", componentName) } - fmt.Printf("[controlplane] wrote Static Pod manifest for component %s to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) + glog.V(1).Infof("[control-plane] wrote static Pod manifest for component %q to %q\n", componentName, kubeadmconstants.GetStaticPodFilepath(componentName, manifestDir)) } return nil diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index 103af4c1fca..2f24909b309 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -91,24 +91,19 @@ func TestGetStaticPodSpecs(t *testing.T) { func TestCreateStaticPodFilesAndWrappers(t *testing.T) { var tests = []struct { - createStaticPodFunction func(outDir string, cfg *kubeadmapi.InitConfiguration) error - expectedFiles []string + components []string }{ - { // CreateInitStaticPodManifestFiles - createStaticPodFunction: CreateInitStaticPodManifestFiles, - expectedFiles: []string{kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler}, + { + components: []string{kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeScheduler}, }, - { // CreateAPIServerStaticPodManifestFile - createStaticPodFunction: CreateAPIServerStaticPodManifestFile, - expectedFiles: []string{kubeadmconstants.KubeAPIServer}, + { + components: []string{kubeadmconstants.KubeAPIServer}, }, - { // CreateControllerManagerStaticPodManifestFile - createStaticPodFunction: CreateControllerManagerStaticPodManifestFile, - expectedFiles: []string{kubeadmconstants.KubeControllerManager}, + { + components: []string{kubeadmconstants.KubeControllerManager}, }, - { // CreateSchedulerStaticPodManifestFile - createStaticPodFunction: CreateSchedulerStaticPodManifestFile, - expectedFiles: []string{kubeadmconstants.KubeScheduler}, + { + components: []string{kubeadmconstants.KubeScheduler}, }, } @@ -127,16 +122,16 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) { // Execute createStaticPodFunction manifestPath := filepath.Join(tmpdir, kubeadmconstants.ManifestsSubDirName) - err := test.createStaticPodFunction(manifestPath, cfg) + err := CreateStaticPodFiles(manifestPath, cfg, test.components...) if err != nil { t.Errorf("Error executing createStaticPodFunction: %v", err) continue } // Assert expected files are there - testutil.AssertFilesCount(t, manifestPath, len(test.expectedFiles)) + testutil.AssertFilesCount(t, manifestPath, len(test.components)) - for _, fileName := range test.expectedFiles { + for _, fileName := range test.components { testutil.AssertFileExists(t, manifestPath, fileName+".yaml") } }