ELIOT Command Line Interface Commit 34/2034/1
authorAbhijit Dasgupta <abhijit.das.gupta@huawei.com>
Thu, 21 Nov 2019 13:27:42 +0000 (13:27 +0000)
committerAbhijit Dasgupta <abhijit.das.gupta@huawei.com>
Thu, 21 Nov 2019 13:27:42 +0000 (13:27 +0000)
elcli GoLang Code Commit for operations

1. elcli init
2. elcli reset
3. elcli cleanup
4. elcli --help

Signed-off-by: Abhijit Dasgupta <abhijit.das.gupta@huawei.com>
Change-Id: If3637f312d2371ceac2b2546c4310bf6f9bfd6f4

36 files changed:
blueprints/common/elcli/elcli/LICENSE [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/clean.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/common/constant.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/common/types.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/init.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/join.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/reset.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/root.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/centosinstaller.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/cleanup.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/common.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/dockerinstaller.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/k8sinstaller.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/setup.go [new file with mode: 0644]
blueprints/common/elcli/elcli/cmd/util/ubuntuinstaller.go [new file with mode: 0644]
blueprints/common/elcli/elcli/main.go [new file with mode: 0644]
blueprints/common/elcli/github.com/fsnotify/fsnotify [new submodule]
blueprints/common/elcli/github.com/hashicorp/hcl [new submodule]
blueprints/common/elcli/github.com/magiconair/properties [new submodule]
blueprints/common/elcli/github.com/mitchellh/go-homedir [new submodule]
blueprints/common/elcli/github.com/mitchellh/mapstructure [new submodule]
blueprints/common/elcli/github.com/pelletier/go-toml [new submodule]
blueprints/common/elcli/github.com/spf13/afero [new submodule]
blueprints/common/elcli/github.com/spf13/cast [new submodule]
blueprints/common/elcli/github.com/spf13/cobra [new submodule]
blueprints/common/elcli/github.com/spf13/elcli.tar [new file with mode: 0644]
blueprints/common/elcli/github.com/spf13/jwalterweatherman [new submodule]
blueprints/common/elcli/github.com/spf13/pflag [new submodule]
blueprints/common/elcli/github.com/spf13/viper [new submodule]
blueprints/common/elcli/github.com/subosito/gotenv [new submodule]
blueprints/common/elcli/github.com/trial/app/trialroot.go [new file with mode: 0644]
blueprints/common/elcli/golang.org/x/lint [new submodule]
blueprints/common/elcli/golang.org/x/sys [new submodule]
blueprints/common/elcli/golang.org/x/text [new submodule]
blueprints/common/elcli/golang.org/x/tools [new submodule]
blueprints/common/elcli/gopkg.in/yaml.v2 [new submodule]

diff --git a/blueprints/common/elcli/elcli/LICENSE b/blueprints/common/elcli/elcli/LICENSE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -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 (file)
index 0000000..57cf158
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Package cmd
+Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+
+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 (file)
index 0000000..7f0d020
--- /dev/null
@@ -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 (file)
index 0000000..b7b77de
--- /dev/null
@@ -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 (file)
index 0000000..9364b50
--- /dev/null
@@ -0,0 +1,80 @@
+// 
+// Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+//
+// 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 (file)
index 0000000..70733ee
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+Package cmd
+Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+
+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 (file)
index 0000000..46f7269
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+
+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 (file)
index 0000000..f868ef4
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+
+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 (file)
index 0000000..95b04d5
--- /dev/null
@@ -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 (file)
index 0000000..4c4d739
--- /dev/null
@@ -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 (file)
index 0000000..7cf3dda
--- /dev/null
@@ -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 (file)
index 0000000..809cb85
--- /dev/null
@@ -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 (file)
index 0000000..239ed4b
--- /dev/null
@@ -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 (file)
index 0000000..cd7e202
--- /dev/null
@@ -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 (file)
index 0000000..4d3690e
--- /dev/null
@@ -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 (file)
index 0000000..189e9a1
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+Copyright © 2019 NAME HERE <EMAIL ADDRESS>
+
+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 (submodule)
index 0000000..1485a34
--- /dev/null
@@ -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 (submodule)
index 0000000..cf7d376
--- /dev/null
@@ -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 (submodule)
index 0000000..de8848e
--- /dev/null
@@ -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 (submodule)
index 0000000..af06845
--- /dev/null
@@ -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 (submodule)
index 0000000..3536a92
--- /dev/null
@@ -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 (submodule)
index 0000000..dba45d4
--- /dev/null
@@ -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 (submodule)
index 0000000..588a75e
--- /dev/null
@@ -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 (submodule)
index 0000000..c01685b
--- /dev/null
@@ -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 (submodule)
index 0000000..1c9c46d
--- /dev/null
@@ -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 (file)
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 (submodule)
index 0000000..94f6ae3
--- /dev/null
@@ -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 (submodule)
index 0000000..24fa697
--- /dev/null
@@ -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 (submodule)
index 0000000..e02bc9e
--- /dev/null
@@ -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 (submodule)
index 0000000..69b5b61
--- /dev/null
@@ -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 (file)
index 0000000..413faff
--- /dev/null
@@ -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 (submodule)
index 0000000..959b441
--- /dev/null
@@ -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 (submodule)
index 0000000..fae7ac5
--- /dev/null
@@ -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 (submodule)
index 0000000..342b2e1
--- /dev/null
@@ -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 (submodule)
index 0000000..f8d1dee
--- /dev/null
@@ -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 (submodule)
index 0000000..51d6538
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 51d6538a90f86fe93ac480b35f37b2be17fef232