package cmd import ( "bufio" "context" "fmt" "os" "strings" "github.com/rancher/rke/cluster" "github.com/rancher/rke/dind" "github.com/rancher/rke/hosts" "github.com/rancher/rke/log" "github.com/rancher/rke/pki" v3 "github.com/rancher/rke/types" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) func RemoveCommand() cli.Command { removeFlags := []cli.Flag{ cli.StringFlag{ Name: "config", Usage: "Specify an alternate cluster YAML file", Value: pki.ClusterConfig, EnvVar: "RKE_CONFIG", }, cli.BoolFlag{ Name: "force", Usage: "Force removal of the cluster", }, cli.BoolFlag{ Name: "local", Usage: "Remove Kubernetes cluster locally", }, cli.BoolFlag{ Name: "dind", Usage: "Remove Kubernetes cluster deployed in dind mode", }, } removeFlags = append(removeFlags, commonFlags...) return cli.Command{ Name: "remove", Usage: "Teardown the cluster and clean cluster nodes", Action: clusterRemoveFromCli, Flags: removeFlags, } } func ClusterRemove( ctx context.Context, rkeConfig *v3.RancherKubernetesEngineConfig, dialersOptions hosts.DialersOptions, flags cluster.ExternalFlags) error { log.Infof(ctx, "Tearing down Kubernetes cluster") kubeCluster, err := cluster.InitClusterObject(ctx, rkeConfig, flags, "") if err != nil { return err } if err := kubeCluster.SetupDialers(ctx, dialersOptions); err != nil { return err } err = kubeCluster.TunnelHosts(ctx, flags) if err != nil { return err } logrus.Debugf("Starting Cluster removal") err = kubeCluster.ClusterRemove(ctx) if err != nil { return err } log.Infof(ctx, "Cluster removed successfully") return nil } func clusterRemoveFromCli(ctx *cli.Context) error { logrus.Infof("Running RKE version: %v", ctx.App.Version) if ctx.Bool("local") { return clusterRemoveLocal(ctx) } clusterFile, filePath, err := resolveClusterFile(ctx) if err != nil { return fmt.Errorf("Failed to resolve cluster file: %v", err) } force := ctx.Bool("force") if !force { reader := bufio.NewReader(os.Stdin) fmt.Printf("Are you sure you want to remove Kubernetes cluster [y/n]: ") input, err := reader.ReadString('\n') input = strings.TrimSpace(input) if err != nil { return err } if input != "y" && input != "Y" { return nil } } if ctx.Bool("dind") { return clusterRemoveDind(ctx) } rkeConfig, err := cluster.ParseConfig(clusterFile) if err != nil { return fmt.Errorf("Failed to parse cluster file: %v", err) } rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) if err != nil { return err } // setting up the flags flags := cluster.GetExternalFlags(false, false, false, "", filePath) return ClusterRemove(context.Background(), rkeConfig, hosts.DialersOptions{}, flags) } func clusterRemoveLocal(ctx *cli.Context) error { var rkeConfig *v3.RancherKubernetesEngineConfig clusterFile, filePath, err := resolveClusterFile(ctx) if err != nil { log.Warnf(context.Background(), "Failed to resolve cluster file, using default cluster instead") rkeConfig = cluster.GetLocalRKEConfig() } else { rkeConfig, err = cluster.ParseConfig(clusterFile) if err != nil { return fmt.Errorf("Failed to parse cluster file: %v", err) } rkeConfig.Nodes = []v3.RKEConfigNode{*cluster.GetLocalRKENodeConfig()} } rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) if err != nil { return err } // setting up the flags flags := cluster.GetExternalFlags(true, false, false, "", filePath) return ClusterRemove(context.Background(), rkeConfig, hosts.DialersOptions{}, flags) } func clusterRemoveDind(ctx *cli.Context) error { clusterFile, filePath, err := resolveClusterFile(ctx) if err != nil { return fmt.Errorf("Failed to resolve cluster file: %v", err) } rkeConfig, err := cluster.ParseConfig(clusterFile) if err != nil { return fmt.Errorf("Failed to parse cluster file: %v", err) } rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) if err != nil { return err } for _, node := range rkeConfig.Nodes { if err = dind.RmoveDindContainer(context.Background(), node.Address); err != nil { return err } } localKubeConfigPath := pki.GetLocalKubeConfig(filePath, "") // remove the kube config file pki.RemoveAdminConfig(context.Background(), localKubeConfigPath) return err }