From: Abhijit Dasgupta Date: Thu, 21 Nov 2019 13:27:42 +0000 (+0000) Subject: ELIOT Command Line Interface Commit X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=commitdiff_plain;h=919863e50b28aefe1e939018826f64d10b17a0db;p=eliot.git ELIOT Command Line Interface Commit elcli GoLang Code Commit for operations 1. elcli init 2. elcli reset 3. elcli cleanup 4. elcli --help Signed-off-by: Abhijit Dasgupta Change-Id: If3637f312d2371ceac2b2546c4310bf6f9bfd6f4 --- diff --git a/blueprints/common/elcli/elcli/LICENSE b/blueprints/common/elcli/elcli/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/blueprints/common/elcli/elcli/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/blueprints/common/elcli/elcli/cmd/clean.go b/blueprints/common/elcli/elcli/cmd/clean.go new file mode 100644 index 0000000..57cf158 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/clean.go @@ -0,0 +1,65 @@ +/* +Package cmd +Copyright © 2019 NAME HERE + +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 cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "elcli/cmd/util" +) + +var ( + elcliCleanCmdLongDescription = + ` + +-------------------------------------------------+ + | To complete cleanup execute this command. The | + | command will remove all the configurations, | + | clear up ports used by ELIOT cluster & uninstall| + | all software. | + +-------------------------------------------------| + ` + elcliCleanExample = ` + +-------------------------------------------------+ + | elcli clean | + +-------------------------------------------------+ + ` +) + +// cleanCmd represents the clean command +var cleanCmd = &cobra.Command{ + Use: "clean", + Short: "ELIOT Cluster Uninstall", + Long: elcliCleanCmdLongDescription, + Example: elcliCleanExample, + RunE: func(cmd *cobra.Command, args []string) error{ + fmt.Println("clean called") + err := util.EliotClean() + str:= util.GetOSVersion() + fmt.Println("Print value of GetOSVersion %s", str) + + if(err != nil) { + return err + } + return nil + }, +} + +func init() { + rootCmd.AddCommand(cleanCmd) +} diff --git a/blueprints/common/elcli/elcli/cmd/common/constant.go b/blueprints/common/elcli/elcli/cmd/common/constant.go new file mode 100644 index 0000000..7f0d020 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/common/constant.go @@ -0,0 +1,46 @@ +/* +Copyright 2019 The ELIOT 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 common + +const ( + //DefaultDockerVersion is the current default version of Docker + DefaultDockerVersion = "18.06.0" + + //DefaultK8SVersion is the current default version of K8S + DefaultK8SVersion = "1.14.1" + + // K8SImageRepository sets the image repository of Kubernetes + K8SImageRepository = "image-repository" + + //K8SPodNetworkCidr sets pod network cidr of Kubernetes + K8SPodNetworkCidr = "pod-network-cidr" + + //DockerVersion sets the version of Docker to be used + DockerVersion = "docker-version" + + //KubernetesVersion sets the version of Kuberneted to be used + KubernetesVersion = "kubernetes-version" + + //K8SAPIServerIPPort sets the IP:Port of Kubernetes api-server + K8SAPIServerIPPort = "k8sserverip" + + //EliotCloudNodeIP sets the IP of KubeEdge cloud component + EliotCloudNodeIP = "eliotcloudnodeip" + + //EliotEdgeNodeID Node unique idenfitcation string + EliotEdgeNodeID = "eliotedgenodeid" +) \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/common/types.go b/blueprints/common/elcli/elcli/cmd/common/types.go new file mode 100644 index 0000000..b7b77de --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/common/types.go @@ -0,0 +1,88 @@ +/* Copyright 2019 The ELIOT 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 common + +var ( + //Setup having option. + Setup string + //Masters list + Masters []string + //Nodes list + Nodes []string +) + +// InitOptions Strucutre +type InitOptions struct { + KubernetesVersion string + DockerVersion string + K8SImageRepository string + K8SPodNetworkCidr string +} + +//JoinOptions has the kubeedge cloud init information filled by CLI +type JoinOptions struct { + InitOptions + CertPath string + CloudCoreIP string + K8SAPIServerIPPort string + EdgeNodeID string +} + +//InstallState enum set used for verifying a tool version is installed in host +type InstallState uint8 + +//Difference enum values for type InstallState +const ( + NewInstallRequired InstallState = iota + AlreadySameVersionExist + DefVerInstallRequired + VersionNAInRepo +) + +//ModuleRunning is defined to know the running status of KubeEdge components +type ModuleRunning uint8 + +//Different possible values for ModuleRunning type +const ( + NoneRunning ModuleRunning = iota + KubeEdgeCloudRunning + KubeEdgeEdgeRunning +) + +//ToolsInstaller interface for tools with install and teardown methods. +type ToolsInstaller interface { + InstallTools() error + TearDown() error +} + +//OSTypeInstaller interface for methods to be executed over a specified OS distribution type +type OSTypeInstaller interface { + IsToolVerInRepo(string, string) (bool, error) + IsDockerInstalled(string) (InstallState, error) + InstallDocker() error + IsK8SComponentInstalled(string, string) (InstallState, error) + InstallK8S() error + StartK8Scluster() error + SetDockerVersion(string) + SetK8SVersionAndIsNodeFlag(version string, flag bool) + SetK8SImageRepoAndPodNetworkCidr(string, string) + } + +//FlagData stores value and default value of the flags used in this command +type FlagData struct { + Val interface{} + DefVal interface{} +} diff --git a/blueprints/common/elcli/elcli/cmd/init.go b/blueprints/common/elcli/elcli/cmd/init.go new file mode 100644 index 0000000..9364b50 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/init.go @@ -0,0 +1,80 @@ +// +// Copyright © 2019 NAME HERE +// +// 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 cmd + +import ( + "fmt" + + + "github.com/spf13/cobra" + + "elcli/cmd/util" +) + +var ( +elcliSetupCmdDescription = +` +ELIOT init command is for setting up the ELIOT Cluster. +The command has options to setup the complete setup which includes +ELIOT Manager and ELIOT Edge Nodes and to setup only ELIOT Manager +or ELIOT Edge Node. The command invokes setup.sh script which handles +the complete setup. + +The Details of ELIOT Edge Nodes must be present in [nodelist] file. +` +) +// initCmd represents the init command +var initCmd = &cobra.Command{ + Use: "init", + Short: "Setup ELIOT Cluster !!", + Long: elcliSetupCmdDescription, + //It will check if the kubernetes process is already running on the node. + //Abort the operation if already running. + PreRunE: func(cmd *cobra.Command,args []string) error { + isELIOTClusterRunning, err := util.IsK8SClusterRunning() + if err != nil { + return err + } else if (isELIOTClusterRunning) { + return fmt.Errorf("Kubernetes Cluster is running in the Node. Clean up the environment and then setup the Cluster") + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error{ + fmt.Println("init called") + setupFlag := cmd.Flag("setup") + setupflagoption := setupFlag.Value.String() + + switch setupflagoption { + case "all": + err:= util.EliotSetupAll() + return err + fmt.Println("Inside all option for setup flag") + case "master": + fmt.Println("Its eliot setup Master") + err:= util.EliotSetupMaster() + return err + default: + fmt.Println("Provide option for flag [--setup :- all | master] or [-s :- all | master]") + } + return nil + }, +} + +func init() { + rootCmd.AddCommand(initCmd) + initCmd.Flags().StringP("setup","s","all","Eliot Topology setup options") + +} diff --git a/blueprints/common/elcli/elcli/cmd/join.go b/blueprints/common/elcli/elcli/cmd/join.go new file mode 100644 index 0000000..70733ee --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/join.go @@ -0,0 +1,144 @@ +/* +Package cmd +Copyright © 2019 NAME HERE + +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 cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + types "elcli/cmd/common" + "elcli/cmd/util" +) + +var joinOptions = &types.JoinOptions{} + +// joinCmd represents the join command +var joinCmd = &cobra.Command{ + Use: "join", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples + and usage of using your command. For example: + + Cobra is a CLI library for Go that empowers applications. + This application is a tool to generate the needed files + to quickly create a Cobra application.`, + + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("join called") + + tools := make(map[string]types.ToolsInstaller, 0) + flagVals := make(map[string]types.FlagData, 0) + + checkFlags := func(f *pflag.Flag) { + util.AddToolVals(f, flagVals) + } + cmd.Flags().VisitAll(checkFlags) + + //joinOptions := &types.JoinOptions{} + joinOptions = newJoinOptions() + + Add2ToolsList(tools, flagVals, joinOptions) + return ExecuteTool(tools) + + }, +} + +func init() { + + // Join Command added as sub-command for main command : elcli + rootCmd.AddCommand(joinCmd) + + joinCmd.Flags().StringVar(&joinOptions.DockerVersion, types.DockerVersion, joinOptions.DockerVersion, + "Use this key to download and use the required Docker version") + joinCmd.Flags().Lookup(types.DockerVersion).NoOptDefVal = joinOptions.DockerVersion + + joinCmd.Flags().StringVar(&joinOptions.KubernetesVersion, types.KubernetesVersion, joinOptions.KubernetesVersion, + "Use this key to download and use the required Kubernetes version") + joinCmd.Flags().Lookup(types.KubernetesVersion).NoOptDefVal = joinOptions.KubernetesVersion + + joinCmd.Flags().StringVar(&joinOptions.K8SImageRepository, types.K8SImageRepository, joinOptions.K8SImageRepository, + "Use this key to set the Kubernetes docker image repository") + joinCmd.Flags().Lookup(types.K8SImageRepository).NoOptDefVal = joinOptions.K8SImageRepository + +} + + +func newJoinOptions() *types.JoinOptions { + fmt.Println("Inside newJointOptions Method.....") + opts := &types.JoinOptions{} + opts.InitOptions = types.InitOptions{DockerVersion: types.DefaultDockerVersion, KubernetesVersion: types.DefaultK8SVersion} + //opts.CertPath = types.DefaultCertPath + return opts +} + + +//Add2ToolsList Reads the flagData (containing val and default val) and join options to fill the list of tools. +func Add2ToolsList(toolList map[string]types.ToolsInstaller, flagData map[string]types.FlagData, joinOptions *types.JoinOptions) { + + var k8sVer, dockerVer string + /*var k8sImageRepo string + + flgData, ok := flagData[types.K8SImageRepository] + if ok { + k8sImageRepo = util.CheckIfAvailable(flgData.Val.(string), flgData.DefVal.(string)) + } else { + k8sImageRepo = joinOptions.K8SImageRepository + } + + */ + + //toolList["EliotEdge"] = &util.KubeEdgeInstTool{Common: util.Common{ToolVersion: kubeVer}, K8SApiServerIP: joinOptions.K8SAPIServerIPPort, + // CloudCoreIP: joinOptions.CloudCoreIP, EdgeNodeID: joinOptions.EdgeNodeID} + + flgData, ok := flagData[types.DockerVersion] + if ok { + dockerVer = util.CheckIfAvailable(flgData.Val.(string), flgData.DefVal.(string)) + } else { + dockerVer = joinOptions.DockerVersion + } + toolList["Docker"] = &util.DockerInstTool{Common: util.Common{ToolVersion: dockerVer}, DefaultToolVer: flgData.DefVal.(string)} + + + flgData, ok = flagData[types.KubernetesVersion] + if ok { + k8sVer = util.CheckIfAvailable(flgData.Val.(string), flgData.DefVal.(string)) + } else { + k8sVer = joinOptions.KubernetesVersion + } + toolList["Kubernetes"] = &util.K8SInstTool{Common: util.Common{ToolVersion: k8sVer}, IsEdgeNode: false, DefaultToolVer: flgData.DefVal.(string)} + + +} + +//ExecuteTool the instalation for each tool and start edgecore +func ExecuteTool(toolList map[string]types.ToolsInstaller) error { + + //Install all the required pre-requisite tools + for name, tool := range toolList { + if name != "EliotEdge" { + err := tool.InstallTools() + if err != nil { + return err + } + } + } + + //Install and Start ElioteEdge Node + return toolList["ElioteEdge"].InstallTools() +} \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/reset.go b/blueprints/common/elcli/elcli/cmd/reset.go new file mode 100644 index 0000000..46f7269 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/reset.go @@ -0,0 +1,59 @@ +/* +Copyright © 2019 NAME HERE + +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 cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "elcli/cmd/util" +) + +var ( + + elcliResetCmdLongDescription = ` ++-----------------------------------------------------------+ +| To Reset the ELIOT Cluster. | +| | ++-----------------------------------------------------------+ +| RESET: It will reset the setting and the kubernetes | +| cluster, underying softwares of ELIOT platform will not be| +| still installed. | ++-----------------------------------------------------------+ +` +) + +// resetCmd represents the reset command +var resetCmd = &cobra.Command{ + Use: "reset", + Short: "Reset ELIOT Cluster!!", + Long: elcliResetCmdLongDescription, + RunE: func(cmd *cobra.Command, args []string) error{ + fmt.Println("reset called") + err := util.EliotReset() + str:= util.GetOSVersion() + if (err != nil){ + return err + } + fmt.Println("Print value of GetOSVersion", str) + return nil + }, +} + +func init() { + rootCmd.AddCommand(resetCmd) +} diff --git a/blueprints/common/elcli/elcli/cmd/root.go b/blueprints/common/elcli/elcli/cmd/root.go new file mode 100644 index 0000000..f868ef4 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/root.go @@ -0,0 +1,107 @@ +/* +Copyright © 2019 NAME HERE + +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 cmd + +import ( + "fmt" + "os" + "github.com/spf13/cobra" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/viper" + +) + + +var cfgFile string + +var ( + elcliLongDescription = ` + +----------------------------------------------------------+ + | ELCLI | + | Command Line Interface to Bootsrap ELIOT Cluster | + +----------------------------------------------------------+ + + ELCLI Command is use to setup the ELIOT Cluster. + It installs the ELIOT Manager and the ELIOT Nodes. + ELIOT Manager is the core-controller and the ELIOT Nodes are + the edge nodes which acts as IOT Gateway or uCPE, where the + application PODS will be running. + ` + elcliExample = ` + +-----------------------------------------------------------+ + |To setup up the ELIOT Cluster the elcli init command has to| + |be executed in the ELIOT Manager Node. | + | | + |Example : | + |elcli init | + | | + +-----------------------------------------------------------+ + + ` +) + + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "elcli", + Short: "elcli : Bootstarp ELIOT Cluster", + Long: elcliLongDescription, + Example: elcliExample, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + +} + + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".elcli" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".elcli") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} + diff --git a/blueprints/common/elcli/elcli/cmd/util/centosinstaller.go b/blueprints/common/elcli/elcli/cmd/util/centosinstaller.go new file mode 100644 index 0000000..95b04d5 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/centosinstaller.go @@ -0,0 +1,162 @@ +/* +Copyright 2019 The Kubeedge 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 util + +import ( + "fmt" + "os/exec" + + types "elcli/cmd/common" + +) + +//CentOS struct objects shall have information of the tools version to be installed +//on Hosts having Ubuntu OS. +//It implements OSTypeInstaller interface +type CentOS struct { + DockerVersion string + KubernetesVersion string + IsEdgeNode bool //True - Edgenode False - Cloudnode + K8SImageRepository string + K8SPodNetworkCidr string +} + +//SetDockerVersion sets the Docker version for the objects instance +func (c *CentOS) SetDockerVersion(version string) { + c.DockerVersion = version +} + +//SetK8SVersionAndIsNodeFlag sets the K8S version for the objects instance +//It also sets if this host shall act as edge node or not +func (c *CentOS) SetK8SVersionAndIsNodeFlag(version string, flag bool) { + c.KubernetesVersion = version + c.IsEdgeNode = flag +} + +//SetK8SImageRepoAndPodNetworkCidr sets the K8S image Repository and pod network +// cidr. +func (c *CentOS) SetK8SImageRepoAndPodNetworkCidr(repo, cidr string) { + c.K8SImageRepository = repo + c.K8SPodNetworkCidr = cidr +} + +//IsDockerInstalled checks if docker is installed in the host or not +func (c *CentOS) IsDockerInstalled(string) (types.InstallState, error) { + //yum list installed | grep docker-ce | awk '{print $2}' | cut -d'-' -f 1 + //18.06.1.ce + + return types.VersionNAInRepo, nil + +} + +//InstallDocker will install the specified docker in the host +func (c *CentOS) InstallDocker() error { + fmt.Println("InstallDocker called") + // yum install -y yum-utils + // yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + // yum makecache + // yum list --showduplicates 'docker-ce' | grep '17.06.0' | head -1 | awk '{print $2}' + // yum install -y docker-ce-17.06.0.ce-1.el7.centos + // [root@localhost ~]# systemctl start docker + // [root@localhost ~]# ---> Always restart systemctl restart docker + // [root@localhost ~]# + // IF downgrade yum downgrade -y docker-ce-17.06.0.ce-1.el7.centos + // Check always for version, if it is a downgrade or upgrade + + return nil +} + +//IsToolVerInRepo checks if the tool mentioned in available in OS repo or not +func (c *CentOS) IsToolVerInRepo(toolName, version string) (bool, error) { + //yum --cacheonly list | grep openssl + //For K8S, dont check in repo, just install + fmt.Println("IsToolVerInRepo called") + return false, nil +} + +//InstallMQTT checks if MQTT is already installed and running, if not then install it from OS repo +//Information is used from https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-the-mosquitto-mqtt-messaging-broker-on-centos-7 +func (c *CentOS) InstallMQTT() error { + + //yum -y install epel-release + cmd := &Command{Cmd: exec.Command("sh", "-c", "yum -y install epel-release")} + err := cmd.ExecuteCmdShowOutput() + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + if err != nil || errout != "" { + return fmt.Errorf("%s", errout) + } + fmt.Println(stdout) + + //yum -y install mosquitto + cmd = &Command{Cmd: exec.Command("sh", "-c", "yum -y install mosquitto")} + err = cmd.ExecuteCmdShowOutput() + stdout = cmd.GetStdOutput() + errout = cmd.GetStdErr() + if err != nil || errout != "" { + return fmt.Errorf("%s", errout) + } + fmt.Println(stdout) + + + //systemctl start mosquitto + cmd = &Command{Cmd: exec.Command("sh", "-c", "systemctl start mosquitto")} + cmd.ExecuteCommand() + stdout = cmd.GetStdOutput() + errout = cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("%s", errout) + } + fmt.Println(stdout) + + //systemctl enable mosquitto + cmd = &Command{Cmd: exec.Command("sh", "-c", "systemctl enable mosquitto")} + cmd.ExecuteCommand() + stdout = cmd.GetStdOutput() + errout = cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("%s", errout) + } + fmt.Println(stdout) + + + return nil +} + +//IsK8SComponentInstalled checks if said K8S version is already installed in the host +func (c *CentOS) IsK8SComponentInstalled(component, defVersion string) (types.InstallState, error) { + // [root@localhost ~]# yum list installed | grep kubeadm | awk '{print $2}' | cut -d'-' -f 1 + // 1.14.1 + // [root@localhost ~]# + // [root@localhost ~]# yum list installed | grep kubeadm + // kubeadm.x86_64 1.14.1-0 @kubernetes + // [root@localhost ~]# + + return types.VersionNAInRepo, nil +} + +//InstallK8S will install kubeadm, kudectl and kubelet for the cloud node +func (c *CentOS) InstallK8S() error { + fmt.Println("InstallK8S called") + //Follow https://kubernetes.io/docs/setup/independent/install-kubeadm/ + return nil +} + +//StartK8Scluster will do "kubeadm init" and cluster will be started +func (c *CentOS) StartK8Scluster() error { + return nil +} \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/util/cleanup.go b/blueprints/common/elcli/elcli/cmd/util/cleanup.go new file mode 100644 index 0000000..4c4d739 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/cleanup.go @@ -0,0 +1,59 @@ +package util + + +import ( + "fmt" + "os/exec" +) +// EliotClean function to reset the ELiot Topology +func EliotClean() error { + fmt.Println("Inside EliotClean Function") + + cdEliotScripts := fmt.Sprintf("cd ~/eliot/scripts/ && ls -l") + shCleanEliotTopology := fmt.Sprintf("cd ~/eliot/scripts/ && bash kubernetes_cleanup.sh") + cmd := &Command{Cmd: exec.Command("bash", "-c", cdEliotScripts)} + cmd.ExecuteCommand() + + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + + if errout != "" { + return fmt.Errorf("Error Output .. %s", errout) + } + fmt.Println("Output is .... ", stdout) + + stdout, err := runCommandWithShell(shCleanEliotTopology) + if err != nil { + return err + } + fmt.Println(stdout) + + return nil +} + +// EliotReset function to Reset the ELIOT Cluster. +func EliotReset() error { + fmt.Println("Inside EliotReset Function") + + cdEliotScripts := fmt.Sprintf("cd ~/eliot/scripts/ && ls -l") + shResetEliotTopology := fmt.Sprintf("cd ~/eliot/scripts/ && bash kubernetes_reset.sh") + cmd := &Command{Cmd: exec.Command("sh", "-c", cdEliotScripts)} + cmd.ExecuteCommand() + + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + + if errout != "" { + return fmt.Errorf("Error Output .. %s", errout) + } + fmt.Println("Output is .... \n ", stdout) + return nil + + stdout, err := runCommandWithShell(shResetEliotTopology) + if err != nil { + return err + } + fmt.Println(stdout) + + return nil +} \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/util/common.go b/blueprints/common/elcli/elcli/cmd/util/common.go new file mode 100644 index 0000000..7cf3dda --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/common.go @@ -0,0 +1,206 @@ +/* +Copyright 2019 The ELIOT Team . + +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 util + +import ( + "bytes" + "fmt" + "io" + "os" + "os/exec" + "strings" + "sync" + + + "github.com/spf13/pflag" + types "elcli/cmd/common" +) + +//Constants used by installers +const ( + UbuntuOSType = "ubuntu" + CentOSType = "centos" + + DefaultDownloadURL = "https://download.docker.com" + DockerPreqReqList = "apt-transport-https ca-certificates curl gnupg-agent software-properties-common" + + KubernetesDownloadURL = "https://apt.kubernetes.io/" + KubernetesGPGURL = "https://packages.cloud.google.com/apt/doc/apt-key.gpg" + + KubeAPIServerName = "kube-apiserver" +) + +//AddToolVals gets the value and default values of each flags and collects them in temporary cache +func AddToolVals(f *pflag.Flag, flagData map[string]types.FlagData) { + flagData[f.Name] = types.FlagData{Val: f.Value.String(), DefVal: f.DefValue} +} + +//CheckIfAvailable checks is val of a flag is empty then return the default value +func CheckIfAvailable(val, defval string) string { + if val == "" { + return defval + } + return val +} + +//Common struct contains OS and Tool version properties and also embeds OS interface +type Common struct { + types.OSTypeInstaller + OSVersion string + ToolVersion string + KubeConfig string +} + +//SetOSInterface defines a method to set the implemtation of the OS interface +func (co *Common) SetOSInterface(intf types.OSTypeInstaller) { + co.OSTypeInstaller = intf +} + +//Command defines commands to be executed and captures std out and std error +type Command struct { + Cmd *exec.Cmd + StdOut []byte + StdErr []byte +} + +//ExecuteCommand executes the command and captures the output in stdOut +func (cm *Command) ExecuteCommand() { + var err error + cm.StdOut, err = cm.Cmd.Output() + if err != nil { + fmt.Println("Output failed: ", err) + cm.StdErr = []byte(err.Error()) + } +} + +//GetStdOutput gets StdOut field +func (cm Command) GetStdOutput() string { + if len(cm.StdOut) != 0 { + return strings.TrimRight(string(cm.StdOut), "\n") + } + return "" +} + +//GetStdErr gets StdErr field +func (cm Command) GetStdErr() string { + if len(cm.StdErr) != 0 { + return strings.TrimRight(string(cm.StdErr), "\n") + } + return "" +} + +//ExecuteCmdShowOutput captures both StdOut and StdErr after exec.cmd(). +//It helps in the commands where it takes some time for execution. +func (cm Command) ExecuteCmdShowOutput() error { + var stdoutBuf, stderrBuf bytes.Buffer + stdoutIn, _ := cm.Cmd.StdoutPipe() + stderrIn, _ := cm.Cmd.StderrPipe() + + var errStdout, errStderr error + stdout := io.MultiWriter(os.Stdout, &stdoutBuf) + stderr := io.MultiWriter(os.Stderr, &stderrBuf) + err := cm.Cmd.Start() + if err != nil { + return fmt.Errorf("failed to start '%s' because of error : %s", strings.Join(cm.Cmd.Args, " "), err.Error()) + } + + var wg sync.WaitGroup + wg.Add(1) + + go func() { + _, errStdout = io.Copy(stdout, stdoutIn) + wg.Done() + }() + + _, errStderr = io.Copy(stderr, stderrIn) + wg.Wait() + + err = cm.Cmd.Wait() + if err != nil { + return fmt.Errorf("failed to run '%s' because of error : %s", strings.Join(cm.Cmd.Args, " "), err.Error()) + } + if errStdout != nil || errStderr != nil { + return fmt.Errorf("failed to capture stdout or stderr") + } + + cm.StdOut, cm.StdErr = stdoutBuf.Bytes(), stderrBuf.Bytes() + return nil +} + +//GetOSVersion gets the OS name +func GetOSVersion() string { + c := &Command{Cmd: exec.Command("sh", "-c", ". /etc/os-release && echo $ID")} + c.ExecuteCommand() + return c.GetStdOutput() +} + +//GetOSInterface helps in returning OS specific object which implements OSTypeInstaller interface. +func GetOSInterface() types.OSTypeInstaller { + + switch GetOSVersion() { + case UbuntuOSType: + return &UbuntuOS{} + case CentOSType: + return &CentOS{} + default: + panic("This OS version is currently un-supported by keadm") + } +} + +// IsCloudCore identifies if the node is having cloudcore and kube-apiserver already running. +// If so, then return true, else it can used as edge node and initialise it. +func IsCloudCore() (types.ModuleRunning, error) { + //osType := GetOSInterface() + + //If any of cloudcore or K8S API server is running, then we believe the node is cloud node + + return types.NoneRunning, nil +} + +//IsK8SClusterRunning check whether Kubernetes Master is running already on the server in which ELIOT Setup command is executed +//Currently there is no check on the ELIOT Edge Nodes. +func IsK8SClusterRunning() (bool, error) { + shK8SClusterRunning := fmt.Sprintf("ps aux | grep kube- | grep -v grep | wc -l") + cmd := &Command {Cmd : exec.Command ("sh" , "-c" ,shK8SClusterRunning)} + cmd.ExecuteCommand() + stdOut:= cmd.GetStdOutput() + errOut:= cmd.GetStdErr() + + if errOut != "" { + return false, fmt.Errorf("%s", errOut) + } + if stdOut != "" { + return true, nil + } + return false,nil + +} + +// runCommandWithShell executes the given command with "sh -c". +// It returns an error if the command outputs anything on the stderr. +func runCommandWithShell(command string) (string, error) { + cmd := &Command{Cmd: exec.Command("sh", "-c", command)} + err := cmd.ExecuteCmdShowOutput() + if err != nil { + return "", err + } + errout := cmd.GetStdErr() + if errout != "" { + return "", fmt.Errorf("%s", errout) + } + return cmd.GetStdOutput(), nil +} diff --git a/blueprints/common/elcli/elcli/cmd/util/dockerinstaller.go b/blueprints/common/elcli/elcli/cmd/util/dockerinstaller.go new file mode 100644 index 0000000..809cb85 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/dockerinstaller.go @@ -0,0 +1,67 @@ +/* +Copyright 2019 The Kubeedge 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 util + +import ( + "fmt" + + types "elcli/cmd/common" +) + +//DockerInstTool embedes Common struct and contains the default docker version +//It implements ToolsInstaller interface +type DockerInstTool struct { + Common + DefaultToolVer string +} + +//InstallTools sets the OS interface, checks if docker installation is required or not. +//If required then install the said version. +func (d *DockerInstTool) InstallTools() error { + d.SetOSInterface(GetOSInterface()) + d.SetDockerVersion(d.ToolVersion) + + action, err := d.IsDockerInstalled(d.DefaultToolVer) + if err != nil { + return err + } + switch action { + case types.VersionNAInRepo: + return fmt.Errorf("Expected Docker version is not available in OS repo") + case types.AlreadySameVersionExist: + fmt.Println("Same version of docker already installed in this host") + return nil + case types.DefVerInstallRequired: + d.SetDockerVersion(d.DefaultToolVer) + fallthrough + case types.NewInstallRequired: + err := d.InstallDocker() + if err != nil { + return err + } + default: + return fmt.Errorf("Error in getting the docker version from host") + } + + return nil +} + +//TearDown shoud uninstall docker, but it is not required either for cloud or edge node. +//It is defined so that DockerInstTool implements ToolsInstaller interface +func (d *DockerInstTool) TearDown() error { + return nil +} diff --git a/blueprints/common/elcli/elcli/cmd/util/k8sinstaller.go b/blueprints/common/elcli/elcli/cmd/util/k8sinstaller.go new file mode 100644 index 0000000..239ed4b --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/k8sinstaller.go @@ -0,0 +1,74 @@ +/* +Copyright 2019 The Eliot Team. + +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 util + +import ( + "fmt" + + types "elcli/cmd/common" +) + + +//K8SInstTool embedes Common struct and contains the default K8S version and +//a flag depicting if host is an edge or cloud node +//It implements ToolsInstaller interface +type K8SInstTool struct { + Common + IsEdgeNode bool //True - Edgenode False - Cloudnode + DefaultToolVer string +} + + +//InstallTools sets the OS interface, checks if K8S installation is required or not. +//If required then install the said version. +func (ks *K8SInstTool) InstallTools() error { + ks.SetOSInterface(GetOSInterface()) + ks.SetK8SVersionAndIsNodeFlag(ks.ToolVersion, ks.IsEdgeNode) + + component := "kubeadm" + if ks.IsEdgeNode == true { + component = "kubectl" + } + action, err := ks.IsK8SComponentInstalled(component, ks.DefaultToolVer) + if err != nil { + return err + } + switch action { + case types.VersionNAInRepo: + return fmt.Errorf("Expected %s version is not available in OS repo", component) + case types.AlreadySameVersionExist: + fmt.Printf("Same version of %s already installed in this host", component) + return nil + case types.DefVerInstallRequired: + ks.SetK8SVersionAndIsNodeFlag(ks.DefaultToolVer, ks.IsEdgeNode) + fallthrough + case types.NewInstallRequired: + err := ks.InstallK8S() + if err != nil { + return err + } + default: + return fmt.Errorf("Error in getting the %s version from host", component) + } + return nil +} + +//TearDown shoud uninstall K8S, but it is not required either for cloud or edge node. +//It is defined so that K8SInstTool implements ToolsInstaller interface +func (ks *K8SInstTool) TearDown() error { + return nil +} \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/util/setup.go b/blueprints/common/elcli/elcli/cmd/util/setup.go new file mode 100644 index 0000000..cd7e202 --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/setup.go @@ -0,0 +1,67 @@ +package util + +import ( + "fmt" + "os/exec" + //"github.com/spf13/elcli/cmd/common" +) + +// EliotSetupAll function to reset the ELiot Topology +func EliotSetupAll() error { + fmt.Println("Inside EliotSetupAll Function") + + + strCdEliotScripts := fmt.Sprintf("cd ~/eliot/scripts/ && ls -l") + strSetupAll := fmt.Sprintf("cd ~/eliot/scripts/ && bash setup.sh") + cmd := &Command{Cmd: exec.Command("bash", "-c", strCdEliotScripts)} + cmd.ExecuteCommand() + + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("Error Output .. %s", errout) + } + + fmt.Println("Output is .... ", stdout) + + stdout, err := runCommandWithShell(strSetupAll) + if err != nil { + return err + } + fmt.Println(stdout) + return nil +} + +//EliotSetupMaster Setup Method. +func EliotSetupMaster() error { + fmt.Println("Inside EliotSetupMaster Function") + + strCdEliotScripts := fmt.Sprintf("cd ~/eliot/scripts/ && ls -l") + + cmd := &Command{Cmd: exec.Command("bash", "-c", strCdEliotScripts)} + cmd.ExecuteCommand() + + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("Error Output .. %s", errout) + } + fmt.Println("Output is .... ", stdout) + + strSetupCommon := fmt.Sprintf("cd ~/eliot/scripts/ && bash common.sh") + stdout, err := runCommandWithShell(strSetupCommon) + if err != nil { + return err + } + fmt.Println(stdout) + fmt.Println("Output is .... ", stdout) + + strSetupk8sMaster := fmt.Sprintf("cd ~/eliot/scripts/ && bash k8smaster.sh") + stdout, err = runCommandWithShell(strSetupk8sMaster) + if err != nil { + return err + } + fmt.Println(stdout) + + return nil +} \ No newline at end of file diff --git a/blueprints/common/elcli/elcli/cmd/util/ubuntuinstaller.go b/blueprints/common/elcli/elcli/cmd/util/ubuntuinstaller.go new file mode 100644 index 0000000..4d3690e --- /dev/null +++ b/blueprints/common/elcli/elcli/cmd/util/ubuntuinstaller.go @@ -0,0 +1,396 @@ +/* +Copyright 2019 The Kubeedge 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 util + +import ( + "fmt" + //"os" + "os/exec" + "strings" + + //types "github.com/kubeedge/kubeedge/keadm/app/cmd/common" + types "elcli/cmd/common" +) + +const downloadRetryTimes int = 3 + +// Ubuntu releases +const ( + UbuntuXenial = "xenial" + UbuntuBionic = "bionic" +) + +//UbuntuOS struct objects shall have information of the tools version to be installed +//on Hosts having Ubuntu OS. +//It implements OSTypeInstaller interface +type UbuntuOS struct { + DockerVersion string + KubernetesVersion string + KubeEdgeVersion string + IsEdgeNode bool //True - Edgenode False - EliotCloudnode + K8SImageRepository string + K8SPodNetworkCidr string +} + +//SetDockerVersion sets the Docker version for the objects instance +func (u *UbuntuOS) SetDockerVersion(version string) { + u.DockerVersion = version +} + +//SetK8SVersionAndIsNodeFlag sets the K8S version for the objects instance +//It also sets if this host shall act as edge node or not +func (u *UbuntuOS) SetK8SVersionAndIsNodeFlag(version string, flag bool) { + u.KubernetesVersion = version + u.IsEdgeNode = flag +} + +//SetK8SImageRepoAndPodNetworkCidr sets the K8S image Repository and pod network +// cidr. +func (u *UbuntuOS) SetK8SImageRepoAndPodNetworkCidr(repo, cidr string) { + u.K8SImageRepository = repo + u.K8SPodNetworkCidr = cidr +} + +//SetKubeEdgeVersion sets the KubeEdge version for the objects instance +func (u *UbuntuOS) SetKubeEdgeVersion(version string) { + u.KubeEdgeVersion = version +} + +//IsToolVerInRepo checks if the tool mentioned in available in OS repo or not +func (u *UbuntuOS) IsToolVerInRepo(toolName, version string) (bool, error) { + //Check if requested Docker or K8S components said version is available in OS repo or not + + chkToolVer := fmt.Sprintf("apt-cache madison '%s' | grep -w %s | head -1 | awk '{$1=$1};1' | cut -d' ' -f 3", toolName, version) + cmd := &Command{Cmd: exec.Command("sh", "-c", chkToolVer)} + cmd.ExecuteCommand() + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + + if errout != "" { + return false, fmt.Errorf("%s", errout) + } + + if stdout != "" { + fmt.Println(toolName, stdout, "is available in OS repo") + return true, nil + } + + fmt.Println(toolName, "version", version, "not found in OS repo") + return false, nil +} + +func (u *UbuntuOS) addDockerRepositoryAndUpdate() error { + //lsb_release -cs + cmd := &Command{Cmd: exec.Command("sh", "-c", "lsb_release -cs")} + cmd.ExecuteCommand() + distVersion := cmd.GetStdOutput() + if distVersion == "" { + return fmt.Errorf("ubuntu dist version not available") + } + fmt.Println("Ubuntu distribution version is", distVersion) + + //'apt-get update' + stdout, err := runCommandWithShell("apt-get update") + if err != nil { + return err + } + fmt.Println(stdout) + + //"curl -fsSL \"$DOWNLOAD_URL/linux/$lsb_dist/gpg\" | apt-key add" + //Get the GPG key + curl := fmt.Sprintf("curl -fsSL \"%s/linux/%s/gpg\" | apt-key add", DefaultDownloadURL, UbuntuOSType) + cmd = &Command{Cmd: exec.Command("sh", "-c", curl)} + cmd.ExecuteCommand() + curlOutput := cmd.GetStdOutput() + if curlOutput == "" { + return fmt.Errorf("not able add the apt key") + } + fmt.Println(curlOutput) + + //Add the repo in OS source.list + aptRepo := fmt.Sprintf("deb [arch=$(dpkg --print-architecture)] %s/linux/%s %s stable", DefaultDownloadURL, UbuntuOSType, distVersion) + updtRepo := fmt.Sprintf("echo \"%s\" > /etc/apt/sources.list.d/docker.list", aptRepo) + cmd = &Command{Cmd: exec.Command("sh", "-c", updtRepo)} + cmd.ExecuteCommand() + updtRepoErr := cmd.GetStdErr() + if updtRepoErr != "" { + return fmt.Errorf("not able add update repo due to error : %s", updtRepoErr) + } + + //Do an apt-get update + stdout, err = runCommandWithShell("apt-get update") + if err != nil { + return err + } + fmt.Println(stdout) + + return nil +} + +//IsDockerInstalled checks if docker is installed in the host or not +func (u *UbuntuOS) IsDockerInstalled(defVersion string) (types.InstallState, error) { + cmd := &Command{Cmd: exec.Command("sh", "-c", "docker -v | cut -d ' ' -f3 | cut -d ',' -f1")} + cmd.ExecuteCommand() + str := cmd.GetStdOutput() + + if strings.Contains(str, u.DockerVersion) { + return types.AlreadySameVersionExist, nil + } + + if err := u.addDockerRepositoryAndUpdate(); err != nil { + return types.VersionNAInRepo, err + } + + if str == "" { + return types.NewInstallRequired, nil + } + + isReqVerAvail, err := u.IsToolVerInRepo("docker-ce", u.DockerVersion) + if err != nil { + return types.VersionNAInRepo, err + } + + var isDefVerAvail bool + if u.DockerVersion != defVersion { + isDefVerAvail, err = u.IsToolVerInRepo("docker-ce", defVersion) + if err != nil { + return types.VersionNAInRepo, err + } + } + + if isReqVerAvail { + return types.NewInstallRequired, nil + } + + if isDefVerAvail { + return types.DefVerInstallRequired, nil + } + + return types.VersionNAInRepo, nil +} + +//InstallDocker will install the specified docker in the host +func (u *UbuntuOS) InstallDocker() error { + fmt.Println("Installing ", u.DockerVersion, "version of docker") + + //Do an apt-get install + instPreReq := fmt.Sprintf("apt-get install -y %s", DockerPreqReqList) + stdout, err := runCommandWithShell(instPreReq) + if err != nil { + return err + } + fmt.Println(stdout) + + //Get the exact version string from OS repo, so that it can search and install. + chkDockerVer := fmt.Sprintf("apt-cache madison 'docker-ce' | grep %s | head -1 | awk '{$1=$1};1' | cut -d' ' -f 3", u.DockerVersion) + cmd := &Command{Cmd: exec.Command("sh", "-c", chkDockerVer)} + cmd.ExecuteCommand() + stdout = cmd.GetStdOutput() + errout := cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("%s", errout) + } + + fmt.Println("Expected docker version to install is", stdout) + + //Install docker-ce + dockerInst := fmt.Sprintf("apt-get install -y --allow-change-held-packages --allow-downgrades docker-ce=%s", stdout) + stdout, err = runCommandWithShell(dockerInst) + if err != nil { + return err + } + fmt.Println(stdout) + + fmt.Println("Docker", u.DockerVersion, "version is installed in this Host") + + return nil +} + +//IsK8SComponentInstalled checks if said K8S version is already installed in the host +func (u *UbuntuOS) IsK8SComponentInstalled(component, defVersion string) (types.InstallState, error) { + + find := fmt.Sprintf("dpkg -l | grep %s | awk '{print $3}'", component) + cmd := &Command{Cmd: exec.Command("sh", "-c", find)} + cmd.ExecuteCommand() + str := cmd.GetStdOutput() + + if strings.Contains(str, u.KubernetesVersion) { + return types.AlreadySameVersionExist, nil + } + + if err := u.addK8SRepositoryAndUpdate(); err != nil { + return types.VersionNAInRepo, err + } + + if str == "" { + return types.NewInstallRequired, nil + } + + isReqVerAvail, err := u.IsToolVerInRepo(component, u.KubernetesVersion) + if err != nil { + return types.VersionNAInRepo, err + } + + var isDefVerAvail bool + if u.KubernetesVersion != defVersion { + isDefVerAvail, _ = u.IsToolVerInRepo(component, defVersion) + if err != nil { + return types.VersionNAInRepo, err + } + } + + if isReqVerAvail { + return types.NewInstallRequired, nil + } + + if isDefVerAvail { + return types.DefVerInstallRequired, nil + } + + return types.VersionNAInRepo, nil +} + +func (u *UbuntuOS) addK8SRepositoryAndUpdate() error { + //Get the distribution version + cmd := &Command{Cmd: exec.Command("sh", "-c", "lsb_release -cs")} + cmd.ExecuteCommand() + distVersion := cmd.GetStdOutput() + if distVersion == "" { + return fmt.Errorf("ubuntu dist version not available") + } + fmt.Println("Ubuntu distribution version is", distVersion) + distVersionForSuite := distVersion + if distVersion == UbuntuBionic { + // No bionic-specific version is available on apt.kubernetes.io. + // Use xenial version instead. + distVersionForSuite = UbuntuXenial + } + suite := fmt.Sprintf("kubernetes-%s", distVersionForSuite) + fmt.Println("Deb suite to use:", suite) + + //Do an apt-get update + stdout, err := runCommandWithShell("apt-get update") + if err != nil { + return err + } + fmt.Println(stdout) + + //curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - + //Get the GPG key + curl := fmt.Sprintf("curl -s %s | apt-key add -", KubernetesGPGURL) + cmd = &Command{Cmd: exec.Command("sh", "-c", curl)} + cmd.ExecuteCommand() + curlOutput := cmd.GetStdOutput() + curlErr := cmd.GetStdErr() + if curlOutput == "" || curlErr != "" { + return fmt.Errorf("not able add the apt key due to error : %s", curlErr) + } + fmt.Println(curlOutput) + + //Add K8S repo to local apt-get source.list + aptRepo := fmt.Sprintf("deb %s %s main", KubernetesDownloadURL, suite) + updtRepo := fmt.Sprintf("echo \"%s\" > /etc/apt/sources.list.d/kubernetes.list", aptRepo) + cmd = &Command{Cmd: exec.Command("sh", "-c", updtRepo)} + cmd.ExecuteCommand() + updtRepoErr := cmd.GetStdErr() + if updtRepoErr != "" { + return fmt.Errorf("not able add update repo due to error : %s", updtRepoErr) + } + + //Do an apt-get update + stdout, err = runCommandWithShell("apt-get update") + if err != nil { + return err + } + fmt.Println(stdout) + return nil +} + +//InstallK8S will install kubeadm, kudectl and kubelet for the cloud node +func (u *UbuntuOS) InstallK8S() error { + k8sComponent := "kubeadm" + fmt.Println("Installing", k8sComponent, u.KubernetesVersion, "version") + + //Get the exact version string from OS repo, so that it can search and install. + chkKubeadmVer := fmt.Sprintf("apt-cache madison '%s' | grep %s | head -1 | awk '{$1=$1};1' | cut -d' ' -f 3", k8sComponent, u.KubernetesVersion) + cmd := &Command{Cmd: exec.Command("sh", "-c", chkKubeadmVer)} + cmd.ExecuteCommand() + stdout := cmd.GetStdOutput() + errout := cmd.GetStdErr() + if errout != "" { + return fmt.Errorf("%s", errout) + } + + fmt.Println("Expected K8S('", k8sComponent, "') version to install is", stdout) + + //Install respective K8S components based on where it is being installed + k8sInst := fmt.Sprintf("apt-get install -y --allow-change-held-packages --allow-downgrades kubeadm=%s kubelet=%s kubectl=%s", stdout, stdout, stdout) + stdout, err := runCommandWithShell(k8sInst) + if err != nil { + return err + } + fmt.Println(stdout) + + fmt.Println(k8sComponent, "version", u.KubernetesVersion, "is installed in this Host") + + return nil +} + +//StartK8Scluster will do "kubeadm init" and cluster will be started +func (u *UbuntuOS) StartK8Scluster() error { + var install bool + cmd := &Command{Cmd: exec.Command("sh", "-c", "kubeadm version")} + cmd.ExecuteCommand() + str := cmd.GetStdOutput() + if str != "" { + install = true + } else { + install = false + } + if install == true { + k8sInit := fmt.Sprintf("swapoff -a && kubeadm init --image-repository \"%s\" --pod-network-cidr=%s", u.K8SImageRepository, u.K8SPodNetworkCidr) + stdout, err := runCommandWithShell(k8sInit) + if err != nil { + return err + } + fmt.Println(stdout) + + stdout, err = runCommandWithShell("mkdir -p $HOME/.kube && cp -r /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config") + if err != nil { + return err + } + fmt.Println(stdout) + } else { + return fmt.Errorf("kubeadm not installed in this host") + } + fmt.Println("Kubeadm init successfully executed") + return nil +} +// // runCommandWithShell executes the given command with "sh -c". +// // It returns an error if the command outputs anything on the stderr. +// func runCommandWithShell(command string) (string, error) { +// cmd := &Command{Cmd: exec.Command("sh", "-c", command)} +// err := cmd.ExecuteCmdShowOutput() +// if err != nil { +// return "", err +// } +// errout := cmd.GetStdErr() +// if errout != "" { +// return "", fmt.Errorf("%s", errout) +// } +// return cmd.GetStdOutput(), nil +// } diff --git a/blueprints/common/elcli/elcli/main.go b/blueprints/common/elcli/elcli/main.go new file mode 100644 index 0000000..189e9a1 --- /dev/null +++ b/blueprints/common/elcli/elcli/main.go @@ -0,0 +1,22 @@ +/* +Copyright © 2019 NAME HERE + +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 main + +import "elcli/cmd" + +func main() { + cmd.Execute() +} diff --git a/blueprints/common/elcli/github.com/fsnotify/fsnotify b/blueprints/common/elcli/github.com/fsnotify/fsnotify new file mode 160000 index 0000000..1485a34 --- /dev/null +++ b/blueprints/common/elcli/github.com/fsnotify/fsnotify @@ -0,0 +1 @@ +Subproject commit 1485a34d5d5723fea214f5710708e19a831720e4 diff --git a/blueprints/common/elcli/github.com/hashicorp/hcl b/blueprints/common/elcli/github.com/hashicorp/hcl new file mode 160000 index 0000000..cf7d376 --- /dev/null +++ b/blueprints/common/elcli/github.com/hashicorp/hcl @@ -0,0 +1 @@ +Subproject commit cf7d376da96d9cecec7c7483cec2735efe54a410 diff --git a/blueprints/common/elcli/github.com/magiconair/properties b/blueprints/common/elcli/github.com/magiconair/properties new file mode 160000 index 0000000..de8848e --- /dev/null +++ b/blueprints/common/elcli/github.com/magiconair/properties @@ -0,0 +1 @@ +Subproject commit de8848e004dd33dc07a2947b3d76f618a7fc7ef1 diff --git a/blueprints/common/elcli/github.com/mitchellh/go-homedir b/blueprints/common/elcli/github.com/mitchellh/go-homedir new file mode 160000 index 0000000..af06845 --- /dev/null +++ b/blueprints/common/elcli/github.com/mitchellh/go-homedir @@ -0,0 +1 @@ +Subproject commit af06845cf3004701891bf4fdb884bfe4920b3727 diff --git a/blueprints/common/elcli/github.com/mitchellh/mapstructure b/blueprints/common/elcli/github.com/mitchellh/mapstructure new file mode 160000 index 0000000..3536a92 --- /dev/null +++ b/blueprints/common/elcli/github.com/mitchellh/mapstructure @@ -0,0 +1 @@ +Subproject commit 3536a929edddb9a5b34bd6861dc4a9647cb459fe diff --git a/blueprints/common/elcli/github.com/pelletier/go-toml b/blueprints/common/elcli/github.com/pelletier/go-toml new file mode 160000 index 0000000..dba45d4 --- /dev/null +++ b/blueprints/common/elcli/github.com/pelletier/go-toml @@ -0,0 +1 @@ +Subproject commit dba45d427ff48cfb9bcf633db3a8e43b7364e261 diff --git a/blueprints/common/elcli/github.com/spf13/afero b/blueprints/common/elcli/github.com/spf13/afero new file mode 160000 index 0000000..588a75e --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/afero @@ -0,0 +1 @@ +Subproject commit 588a75ec4f32903aa5e39a2619ba6a4631e28424 diff --git a/blueprints/common/elcli/github.com/spf13/cast b/blueprints/common/elcli/github.com/spf13/cast new file mode 160000 index 0000000..c01685b --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/cast @@ -0,0 +1 @@ +Subproject commit c01685bb8421cecb276fa517e91f757215f980b3 diff --git a/blueprints/common/elcli/github.com/spf13/cobra b/blueprints/common/elcli/github.com/spf13/cobra new file mode 160000 index 0000000..1c9c46d --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/cobra @@ -0,0 +1 @@ +Subproject commit 1c9c46d5c1cc2aaebdd1898c0680e85e8a44b36d diff --git a/blueprints/common/elcli/github.com/spf13/elcli.tar b/blueprints/common/elcli/github.com/spf13/elcli.tar new file mode 100644 index 0000000..1ab3da2 Binary files /dev/null and b/blueprints/common/elcli/github.com/spf13/elcli.tar differ diff --git a/blueprints/common/elcli/github.com/spf13/jwalterweatherman b/blueprints/common/elcli/github.com/spf13/jwalterweatherman new file mode 160000 index 0000000..94f6ae3 --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/jwalterweatherman @@ -0,0 +1 @@ +Subproject commit 94f6ae3ed3bceceafa716478c5fbf8d29ca601a1 diff --git a/blueprints/common/elcli/github.com/spf13/pflag b/blueprints/common/elcli/github.com/spf13/pflag new file mode 160000 index 0000000..24fa697 --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/pflag @@ -0,0 +1 @@ +Subproject commit 24fa6976df40757dce6aea913e7b81ade90530e1 diff --git a/blueprints/common/elcli/github.com/spf13/viper b/blueprints/common/elcli/github.com/spf13/viper new file mode 160000 index 0000000..e02bc9e --- /dev/null +++ b/blueprints/common/elcli/github.com/spf13/viper @@ -0,0 +1 @@ +Subproject commit e02bc9eca55d5fc66221bc0aeeaaa77410603914 diff --git a/blueprints/common/elcli/github.com/subosito/gotenv b/blueprints/common/elcli/github.com/subosito/gotenv new file mode 160000 index 0000000..69b5b61 --- /dev/null +++ b/blueprints/common/elcli/github.com/subosito/gotenv @@ -0,0 +1 @@ +Subproject commit 69b5b6104433beb2cb9c3ce00bdadf3c7c2d3f34 diff --git a/blueprints/common/elcli/github.com/trial/app/trialroot.go b/blueprints/common/elcli/github.com/trial/app/trialroot.go new file mode 100644 index 0000000..413faff --- /dev/null +++ b/blueprints/common/elcli/github.com/trial/app/trialroot.go @@ -0,0 +1,19 @@ +/* + +*/ + +package app + +import ( + "flag" + "os" + "fmt" + + "github.com/spf13/pflag" + "github.com/trial/app/cmd" +) + +//Run executes commands +func Run() error { + return "Hello World" +} diff --git a/blueprints/common/elcli/golang.org/x/lint b/blueprints/common/elcli/golang.org/x/lint new file mode 160000 index 0000000..959b441 --- /dev/null +++ b/blueprints/common/elcli/golang.org/x/lint @@ -0,0 +1 @@ +Subproject commit 959b441ac422379a43da2230f62be024250818b0 diff --git a/blueprints/common/elcli/golang.org/x/sys b/blueprints/common/elcli/golang.org/x/sys new file mode 160000 index 0000000..fae7ac5 --- /dev/null +++ b/blueprints/common/elcli/golang.org/x/sys @@ -0,0 +1 @@ +Subproject commit fae7ac547cb717d141c433a2a173315e216b64c4 diff --git a/blueprints/common/elcli/golang.org/x/text b/blueprints/common/elcli/golang.org/x/text new file mode 160000 index 0000000..342b2e1 --- /dev/null +++ b/blueprints/common/elcli/golang.org/x/text @@ -0,0 +1 @@ +Subproject commit 342b2e1fbaa52c93f31447ad2c6abc048c63e475 diff --git a/blueprints/common/elcli/golang.org/x/tools b/blueprints/common/elcli/golang.org/x/tools new file mode 160000 index 0000000..f8d1dee --- /dev/null +++ b/blueprints/common/elcli/golang.org/x/tools @@ -0,0 +1 @@ +Subproject commit f8d1dee965f76837e891ded19dd59ee264db8ddc diff --git a/blueprints/common/elcli/gopkg.in/yaml.v2 b/blueprints/common/elcli/gopkg.in/yaml.v2 new file mode 160000 index 0000000..51d6538 --- /dev/null +++ b/blueprints/common/elcli/gopkg.in/yaml.v2 @@ -0,0 +1 @@ +Subproject commit 51d6538a90f86fe93ac480b35f37b2be17fef232