Unverified Commit 163b848a authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #59115 from alexbrand/kubeadm-confirm-reset-2

Automatic merge from submit-queue (batch tested with PRs 59965, 59115, 63076, 63059). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. kubeadm: prompt for confirmation when resetting a master Signed-off-by: 's avatarAlexander Brand <alexbrand09@gmail.com> **What this PR does / why we need it**: This PR implements a confirmation prompt when running `kubeadm reset` on a master node. This is to prevent users from mistakenly resetting a master node. **Which issue(s) this PR fixes**: Fixes https://github.com/kubernetes/kubeadm/issues/673 **Special notes for your reviewer**: I am somewhat torn on the approach on how to detect that kubeadm is running on a master node. I went with checking for the apiserver manfiest file on the local filesystem, as it seems like a simpler approach when compared to getting a k8s client, getting a list of nodes, finding the current node, and checking if it has the master taint. I am happy to rework if the latter is more desirable. Sample runs: ``` # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: no Aborted reset operation on master node # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: confirm [preflight] Running pre-flight checks. [reset] Stopping the kubelet service. [reset] WARNING: The kubelet service could not be stopped by kubeadm: [exit status 1] [reset] WARNING: Please ensure kubelet is stopped manually. [reset] Unmounting mounted directories in "/var/lib/kubelet" ........ # ./kubeadm reset [Warning] Are you sure you want to reset this master node? Type the word "confirm" to continue: Aborted reset operation on master node # ./kubeadm reset --confirm [preflight] Running pre-flight checks. [reset] Stopping the kubelet service. [reset] WARNING: The kubelet service could not be stopped by kubeadm: [exit status 1] [reset] WARNING: Please ensure kubelet is stopped manually. [reset] Unmounting mounted directories in "/var/lib/kubelet" ........ ``` **Release note**: ```release-note kubeadm: prompt the user for confirmation when resetting a master node ```
parents 37a798de 8ea5be8d
......@@ -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))
......
......@@ -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 strings.ToLower(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
}
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment