diff --git a/cmd/kubeadm/app/cmd/cmd.go b/cmd/kubeadm/app/cmd/cmd.go index a3124b31be2..b0ed29535ea 100644 --- a/cmd/kubeadm/app/cmd/cmd.go +++ b/cmd/kubeadm/app/cmd/cmd.go @@ -32,7 +32,7 @@ import ( ) // NewKubeadmCommand return cobra.Command to run kubeadm command -func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command { +func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command { cmds := &cobra.Command{ Use: "kubeadm", Short: "kubeadm: easily bootstrap a secure Kubernetes cluster", @@ -77,7 +77,7 @@ func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command { cmds.AddCommand(NewCmdConfig(out)) cmds.AddCommand(NewCmdInit(out)) cmds.AddCommand(NewCmdJoin(out)) - cmds.AddCommand(NewCmdReset(out)) + cmds.AddCommand(NewCmdReset(in, out)) cmds.AddCommand(NewCmdVersion(out)) cmds.AddCommand(NewCmdToken(out, err)) cmds.AddCommand(upgrade.NewCmdUpgrade(out)) diff --git a/cmd/kubeadm/app/cmd/reset.go b/cmd/kubeadm/app/cmd/reset.go index b41d2b048e5..5f914aa1251 100644 --- a/cmd/kubeadm/app/cmd/reset.go +++ b/cmd/kubeadm/app/cmd/reset.go @@ -17,6 +17,8 @@ limitations under the License. package cmd import ( + "bufio" + "errors" "fmt" "io" "os" @@ -44,11 +46,12 @@ var ( ) // NewCmdReset returns the "kubeadm reset" command -func NewCmdReset(out io.Writer) *cobra.Command { +func NewCmdReset(in io.Reader, out io.Writer) *cobra.Command { var skipPreFlight bool var certsDir string var criSocketPath string var ignorePreflightErrors []string + var forceReset bool cmd := &cobra.Command{ Use: "reset", @@ -57,7 +60,7 @@ func NewCmdReset(out io.Writer) *cobra.Command { ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) kubeadmutil.CheckErr(err) - r, err := NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath) + r, err := NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) kubeadmutil.CheckErr(err) kubeadmutil.CheckErr(r.Run(out)) }, @@ -83,6 +86,11 @@ func NewCmdReset(out io.Writer) *cobra.Command { "The path to the CRI socket to use with crictl when cleaning up containers.", ) + cmd.PersistentFlags().BoolVar( + &forceReset, "force", false, + "Reset the node without prompting for confirmation.", + ) + return cmd } @@ -93,9 +101,21 @@ type Reset struct { } // NewReset instantiate Reset struct -func NewReset(ignorePreflightErrors sets.String, certsDir, criSocketPath string) (*Reset, error) { - glog.Infoln("[preflight] running pre-flight checks") +func NewReset(in io.Reader, ignorePreflightErrors sets.String, forceReset bool, certsDir, criSocketPath string) (*Reset, error) { + if !forceReset { + fmt.Println("[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.") + fmt.Print("[reset] are you sure you want to proceed? [y/N]: ") + s := bufio.NewScanner(in) + s.Scan() + if err := s.Err(); err != nil { + return nil, err + } + if s.Text() != "y" { + return nil, errors.New("Aborted reset operation") + } + } + glog.Infoln("[preflight] running pre-flight checks") if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil { return nil, err } diff --git a/cmd/kubeadm/app/cmd/reset_test.go b/cmd/kubeadm/app/cmd/reset_test.go index 605d0c01c35..dee7984630b 100644 --- a/cmd/kubeadm/app/cmd/reset_test.go +++ b/cmd/kubeadm/app/cmd/reset_test.go @@ -56,28 +56,31 @@ func assertDirEmpty(t *testing.T, path string) { } func TestNewReset(t *testing.T) { + var in io.Reader certsDir := kubeadmapiext.DefaultCertificatesDir criSocketPath := "/var/run/dockershim.sock" skipPreFlight := false + forceReset := true ignorePreflightErrors := []string{"all"} ignorePreflightErrorsSet, _ := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) - NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath) + NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) ignorePreflightErrors = []string{} ignorePreflightErrorsSet, _ = validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight) - NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath) + NewReset(in, ignorePreflightErrorsSet, forceReset, certsDir, criSocketPath) } func TestNewCmdReset(t *testing.T) { var out io.Writer - cmd := NewCmdReset(out) + var in io.Reader + cmd := NewCmdReset(in, out) tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test") if err != nil { t.Errorf("Unable to create temporary directory: %v", err) } - args := []string{"--ignore-preflight-errors=all", "--cert-dir=" + tmpDir} + args := []string{"--ignore-preflight-errors=all", "--cert-dir=" + tmpDir, "--force"} cmd.SetArgs(args) if err := cmd.Execute(); err != nil { t.Errorf("Cannot execute reset command: %v", err)