From 6aeaaa63b0e89aedf543a7e291145b330035e02e Mon Sep 17 00:00:00 2001 From: pixiake Date: Sun, 31 May 2020 12:42:01 +0800 Subject: [PATCH] confirmation before installation --- README.md | 5 +- docs/config-example.md | 2 +- go.mod | 5 +- go.sum | 14 ++++ pkg/cluster/preinstall/initOS.go | 5 ++ pkg/cluster/preinstall/precheck.go | 95 ++++++++++++++++++++++++++++ pkg/cluster/preinstall/preinstall.go | 14 ++-- pkg/install/install.go | 4 +- pkg/util/runner/runner.go | 2 +- 9 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 pkg/cluster/preinstall/precheck.go diff --git a/README.md b/README.md index ee09d821..d4f26689 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,10 @@ There are three scenarios to use KubeKey. * OS requirements: * `SSH` can access to all nodes. + * Time synchronization for all nodes. * `sudo`/`curl`/`openssl` can be used in all nodes. - * `ebtables`/`socat`/`ipset`/`conntrack` should be installed on all nodes. - * The [relevant client](./docs/storage-client.md) should be installed on all nodes, if NFS / Ceph / GlusterFS is used as persistent storage. + * `ebtables`/`socat`/`ipset`/`conntrack` should be installed in all nodes. + * The [relevant client](./docs/storage-client.md) should be installed in all nodes, if NFS / Ceph / GlusterFS is used as persistent storage. * `docker` can be installed by yourself or by KubeKey. > It's recommended that Your OS is clean (without any other software installed), otherwise there may be conflicts. diff --git a/docs/config-example.md b/docs/config-example.md index 1595fb1c..ae19160a 100644 --- a/docs/config-example.md +++ b/docs/config-example.md @@ -23,7 +23,7 @@ spec: port: "6443" kubernetes: version: v1.17.6 - imageRepo: kubekey + imageRepo: kubesphere clusterName: cluster.local network: plugin: calico diff --git a/go.mod b/go.mod index a66b0947..baa1879c 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,18 @@ module github.com/kubesphere/kubekey go 1.13 require ( + github.com/gizak/termui/v3 v3.1.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/lithammer/dedent v1.1.0 + github.com/mitchellh/mapstructure v1.1.2 + github.com/modood/table v0.0.0-20200225102042-88de94bb9876 github.com/operator-framework/operator-sdk v0.17.0 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.11.0 github.com/sirupsen/logrus v1.5.0 github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.4.0 + github.com/spf13/viper v1.4.0 // indirect github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 gopkg.in/yaml.v2 v2.2.8 diff --git a/go.sum b/go.sum index 787baa9f..03c64d1b 100644 --- a/go.sum +++ b/go.sum @@ -239,6 +239,9 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= +github.com/gizak/termui v3.1.0+incompatible h1:N3CFm+j087lanTxPpHOmQs0uS3s5I9TxoAFy6DqPqv8= +github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= +github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= @@ -389,6 +392,7 @@ github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEo github.com/gophercloud/gophercloud v0.6.0 h1:Xb2lcqZtml1XjgYZxbeayEemq7ASbeTp09m36gQFpEU= github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU= github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -483,6 +487,7 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/jsonnet-bundler/jsonnet-bundler v0.2.0/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -540,6 +545,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -559,6 +565,8 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= @@ -576,6 +584,8 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modood/table v0.0.0-20200225102042-88de94bb9876 h1:B4Xx3qOvn+rJip+843KkfIn0zefjyr6A5FS5PjMlpLY= +github.com/modood/table v0.0.0-20200225102042-88de94bb9876/go.mod h1:41qyXVI5QH9/ObyPj27CGCVau5v/njfc3Gjj7yzr0HQ= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/go-cos v0.13.0/go.mod h1:Zp6DvvXn0RUOXGJ2chmWt2bLEqRAnJnS3DnAZsJsoaE= @@ -587,6 +597,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840= +github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v0.0.0-20170117200651-66bb6560562f/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -738,8 +750,10 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= diff --git a/pkg/cluster/preinstall/initOS.go b/pkg/cluster/preinstall/initOS.go index c20271b4..331781dc 100644 --- a/pkg/cluster/preinstall/initOS.go +++ b/pkg/cluster/preinstall/initOS.go @@ -27,6 +27,11 @@ import ( ) func InitOS(mgr *manager.Manager) error { + PrecheckConfirm(mgr) + if err := Prepare(mgr); err != nil { + return errors.Wrap(err, "Failed to load kube binaries") + } + mgr.Logger.Infoln("Configurating operating system ...") return mgr.RunTaskOnAllNodes(initOsOnNode, true) diff --git a/pkg/cluster/preinstall/precheck.go b/pkg/cluster/preinstall/precheck.go new file mode 100644 index 00000000..bd65de45 --- /dev/null +++ b/pkg/cluster/preinstall/precheck.go @@ -0,0 +1,95 @@ +package preinstall + +import ( + "bufio" + "fmt" + kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1" + "github.com/kubesphere/kubekey/pkg/util/manager" + "github.com/kubesphere/kubekey/pkg/util/ssh" + "github.com/mitchellh/mapstructure" + "github.com/modood/table" + "os" + "strings" +) + +type PrecheckResults struct { + Name string `table:"name"` + Sudo string `table:"sudo"` + Curl string `table:"curl"` + Openssl string `table:"openssl"` + Ebtables string `table:"ebtables"` + Socat string `table:"socat"` + Ipset string `table:"ipset"` + Conntrack string `table:"conntrack"` + Docker string `table:"docker"` + Nfs string `table:"nfs client"` + Ceph string `table:"ceph client"` + Glusterfs string `table:"glusterfs client"` + Date string `table:"date"` +} + +var ( + checkResults = make(map[string]interface{}) + baseSoftwares = []string{"sudo", "curl", "openssl", "ebtables", "socat", "ipset", "conntrack", "docker", "showmount", "rbd", "glusterfs"} +) + +func Precheck(mgr *manager.Manager) error { + return mgr.RunTaskOnAllNodes(precheck, true) +} + +func precheck(mgr *manager.Manager, node *kubekeyapi.HostCfg, conn ssh.Connection) error { + var results = make(map[string]interface{}) + results["name"] = node.Name + for _, software := range baseSoftwares { + _, err := mgr.Runner.RunCmd(fmt.Sprintf("which %s", software)) + if err != nil { + results[software] = "" + } else { + results[software] = "y" + } + } + output, err := mgr.Runner.RunCmd("date +\"%Z %H:%M:%S\"") + if err != nil { + results["date"] = "" + } else { + results["date"] = strings.TrimSpace(output) + } + + checkResults[node.Name] = results + return nil +} + +func PrecheckConfirm(mgr *manager.Manager) { + + results := []PrecheckResults{} + for node := range checkResults { + var result PrecheckResults + mapstructure.Decode(checkResults[node], &result) + results = append(results, result) + } + table.OutputA(results) + reader := bufio.NewReader(os.Stdin) + fmt.Println("") + fmt.Println("This is a simple check of your machines.") + fmt.Println("Before installation, you should ensure that your machines meet all requirements.") + fmt.Println("https://github.com/kubesphere/kubekey#requirements-and-recommendations") + fmt.Println("") +Loop: + for { + fmt.Printf("Whether to continue this installation? [yes/no]: ") + input, err := reader.ReadString('\n') + if err != nil { + mgr.Logger.Fatal(err) + } + input = strings.TrimSpace(input) + + switch input { + case "yes": + break Loop + case "no": + os.Exit(0) + default: + continue + } + } +} diff --git a/pkg/cluster/preinstall/preinstall.go b/pkg/cluster/preinstall/preinstall.go index 382e48e8..ff6d11e4 100644 --- a/pkg/cluster/preinstall/preinstall.go +++ b/pkg/cluster/preinstall/preinstall.go @@ -21,15 +21,15 @@ import ( kubekeyapi "github.com/kubesphere/kubekey/pkg/apis/kubekey/v1alpha1" "github.com/kubesphere/kubekey/pkg/files" "github.com/kubesphere/kubekey/pkg/util" + "github.com/kubesphere/kubekey/pkg/util/manager" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "os" "os/exec" "path/filepath" "strings" ) -func FilesDownloadHttp(cfg *kubekeyapi.ClusterSpec, filepath, version string, logger *log.Logger) error { +func FilesDownloadHttp(mgr *manager.Manager, filepath, version string) error { kubeadm := files.KubeBinary{Name: "kubeadm", Arch: kubekeyapi.DefaultArch, Version: version} kubelet := files.KubeBinary{Name: "kubelet", Arch: kubekeyapi.DefaultArch, Version: version} @@ -58,7 +58,7 @@ func FilesDownloadHttp(cfg *kubekeyapi.ClusterSpec, filepath, version string, lo binaries := []files.KubeBinary{kubeadm, kubelet, kubectl, kubecni, helm} for _, binary := range binaries { - logger.Info(fmt.Sprintf("Downloading %s ...", binary.Name)) + mgr.Logger.Infoln(fmt.Sprintf("Downloading %s ...", binary.Name)) if util.IsExist(binary.Path) == false { if output, err := exec.Command("/bin/sh", "-c", binary.GetCmd).CombinedOutput(); err != nil { fmt.Println(string(output)) @@ -83,9 +83,9 @@ func FilesDownloadHttp(cfg *kubekeyapi.ClusterSpec, filepath, version string, lo return nil } -func Prepare(cfg *kubekeyapi.ClusterSpec, logger *log.Logger) error { - logger.Info("Downloading Installation Files") - +func Prepare(mgr *manager.Manager) error { + mgr.Logger.Infoln("Downloading Installation Files") + cfg := mgr.Cluster currentDir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { return errors.Wrap(err, "Faild to get current dir") @@ -103,7 +103,7 @@ func Prepare(cfg *kubekeyapi.ClusterSpec, logger *log.Logger) error { return errors.Wrap(err, "Failed to create download target dir") } - if err := FilesDownloadHttp(cfg, filepath, kubeVersion, logger); err != nil { + if err := FilesDownloadHttp(mgr, filepath, kubeVersion); err != nil { return err } return nil diff --git a/pkg/install/install.go b/pkg/install/install.go index 4b843006..eeed161d 100644 --- a/pkg/install/install.go +++ b/pkg/install/install.go @@ -39,14 +39,12 @@ func CreateCluster(clusterCfgFile string, logger *log.Logger, all, verbose bool) return errors.Wrap(err, "Failed to download cluster config") } - if err := preinstall.Prepare(&cfg.Spec, logger); err != nil { - return errors.Wrap(err, "Failed to load kube binaries") - } return Execute(executor.NewExecutor(&cfg.Spec, logger, verbose)) } func ExecTasks(mgr *manager.Manager) error { createTasks := []manager.Task{ + {Task: preinstall.Precheck, ErrMsg: "Failed to precheck"}, {Task: preinstall.InitOS, ErrMsg: "Failed to download kube binaries"}, {Task: docker.InstallerDocker, ErrMsg: "Failed to install docker"}, {Task: images.PreDownloadImages, ErrMsg: "Failed to pre-download images"}, diff --git a/pkg/util/runner/runner.go b/pkg/util/runner/runner.go index 8c611143..58297e0f 100644 --- a/pkg/util/runner/runner.go +++ b/pkg/util/runner/runner.go @@ -50,7 +50,7 @@ func (r *Runner) RunCmd(cmd string) (string, error) { } if output != "" { - if strings.Contains(cmd, "base64") && strings.Contains(cmd, "--wrap=0") || strings.Contains(cmd, "make-ssl-etcd.sh") || strings.Contains(cmd, "docker-install.sh") || strings.Contains(cmd, "docker pull") { + if strings.Contains(cmd, "base64") && strings.Contains(cmd, "--wrap=0") || strings.Contains(cmd, "make-ssl-etcd.sh") || strings.Contains(cmd, "docker-install.sh") || strings.Contains(cmd, "docker pull") || strings.Contains(cmd, "which") || strings.Contains(cmd, "date") { } else { fmt.Printf("[%s %s] MSG:\n", r.Host.Name, r.Host.Address) fmt.Println(output)