diff --git a/.gitignore b/.gitignore index ec4429a..0fba1d2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,7 @@ golint # Ignore personal configs config.yml -config.yaml \ No newline at end of file +config.yaml +.scannerwork +report.xml +coverage.xml \ No newline at end of file diff --git a/Makefile b/Makefile index c16e5b1..145f511 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ default: bin .PHONY: bin bin: + go get -u ./... go build ${BUILD_FLAGS} -o tk8 main.go .PHONY: install @@ -28,10 +29,21 @@ lint: vet: go vet $(PKGS) +.PHONY: test +test: + gocov test ./... | gocov-xml > coverage.xml + gometalinter.v1 --checkstyle > report.xml + sonar-scanner \ + -Dsonar.projectKey=mmmac \ + -Dsonar.host.url=http://localhost:9000 \ + -Dsonar.login=616782f26ee441b650bd709eff9f8acee0a0fd75 \ + -X + +.PHONY: release release: + go get -u ./... ./scripts/check-gofmt.sh - go build -o golint github.com/golang/lint/golint - ./golint $(PKGS) + golint $(PKGS) go vet $(PKGS) go build ${BUILD_FLAGS} -o tk8 main.go GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build ${BUILD_FLAGS} -o tk8-darwin-amd64 main.go diff --git a/README_old.md b/README_old.md deleted file mode 100644 index 4947167..0000000 --- a/README_old.md +++ /dev/null @@ -1,87 +0,0 @@ -![Logo](docs/images/tk8.png) - -# TK8: A multi-cloud, multi-cluster Kubernetes platform installation and integration tool based on Kubespray - -TK8 is a CLI written in Golang to deploy the upstream Vanilla Kubernetes fully automated based on [Kubespray](https://github.com/kubernetes-incubator/kubespray) on any environment. **We'll provide kubeadm support as soon kubeadm HA support is available through Kubespray project.** - -With TK8 you can also install additional add-ons such as a Jmeter Cluster for load testing, Prometheus for monitoring, Jaeger, Linkerd or Zippkin for tracing, Ambassador API Gateway with Envoy for ingress and load balancing, Istio for service mesh support , Jenkins-X for CI/CD and Helm or Kedge for packaging on Kubernetes. - -This release supports the Kubernetes installation on AWS and OpenStack / Bare-Metal with HA capabilities. - -N.B: MS Azure and GCP support will be added in the very near future. - -## Installation - -### Building from source - -```shell -go get -u github.com/kubernauts/tk8 -``` - - -## Usage - -You can either use the cli to install a supported addon in an existing Kubernetes cluster or to provision and install Kubernetes on the supported platforms. The basic usage instructions are as below: - -```shell -Usage: - tk8 [command] - -Available Commands: - addon Install kubernetes addon packages - cluster Used to create kubernetes cluster on cloud infrastructures - help Help about any command - -Flags: - --config string uses the config.yaml - -h, --help help for tk8 - -t, --toggle Help message for toggle - -Use "tk8 [command] --help" for more information about a command. -``` - -### Install a supported addon in an existing Kubernetes cluster - -#### Using installed binary - -```shell -Usage: - tk8 addon [flags] - -Flags: - -m, --heapster Deploy Heapster - -h, --help help for addon - -l, --ltaas Deploy Load Testing As A Service - -p, --prom Deploy prometheus - -Global Flags: - --config string Path to the config.yaml -``` - - -### Provision and install Kubernetes on the supported platforms - -#### Using installed binary - -```shell -Usage: - tk8 cluster [flags] - tk8 cluster [command] - -Available Commands: - aws Manages the infrastructure on AWS - baremetal Manages the infrastructure on Baremetal - init Initialise kubespray repository - openstack Manages the infrastructure on Openstack - -Flags: - -h, --help help for cluster - -Global Flags: - --config string Path to the config.yaml - -Use "tk8 cluster [command] --help" for more information about a command. -``` - -Specific platform instructions can be found in the [official documentation](https://kubernauts.gitbooks.io/tk8/content/) or in [docs](docs/) - diff --git a/cmd/addon.go b/cmd/cli/addon.go similarity index 88% rename from cmd/addon.go rename to cmd/cli/addon.go index a8abbee..1b7499f 100644 --- a/cmd/addon.go +++ b/cmd/cli/addon.go @@ -24,7 +24,7 @@ import ( "github.com/spf13/cobra" ) -var monitor, rancher bool +var Addon addon.Addon // addonCmd represents the addon command var addonCmd = &cobra.Command{ @@ -51,7 +51,7 @@ var addonInstallCmd = &cobra.Command{ cmd.Help() os.Exit(1) } - addon.InstallAddon(args[0]) + Addon.Install(args[0]) }, } @@ -66,7 +66,7 @@ var addonDestroyCmd = &cobra.Command{ cmd.Help() os.Exit(1) } - addon.DestroyAddon(args[0]) + Addon.Destroy(args[0]) }, } @@ -74,7 +74,7 @@ var addonDestroyCmd = &cobra.Command{ var addonCreateCmd = &cobra.Command{ Use: "create [addon name]", Short: "create a new kubernetes addon packages on your local machine for development", - Long: `Create your own addons for your kubernetes cluster. + Long: `Create your own addons for your kubernetes cluster. This command will prepare a example package in a folder with the addon name`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { @@ -82,7 +82,7 @@ This command will prepare a example package in a folder with the addon name`, cmd.Help() os.Exit(1) } - addon.PrepareExample(args[0]) + Addon.Create(args[0]) }, } @@ -97,15 +97,16 @@ var addonGetCmd = &cobra.Command{ cmd.Help() os.Exit(1) } - addon.GetAddon(args[0]) + Addon.Get(args[0]) }, } +/* + * This function gets the path to the kubeconfig, cluster details and auth + * for using with the kubectl. + * Then use this to install the addon on this cluster + */ func getKubeConfig() string { - /* This function gets the path to the kubeconfig, cluster details and auth - for using with the kubectl. - Then use this to install the addon on this cluster - */ fmt.Println("Please enter the path to your kubeconfig:") var kubeConfig string fmt.Scanln(&kubeConfig) @@ -117,10 +118,11 @@ func getKubeConfig() string { return kubeConfig } +/* + * This function is used to check the whether kubectl command is installed & + * it works with the kubeConfig provided + */ func checkKubectl(kubeConfig string) { - /*This function is used to check the whether kubectl command is installed & - it works with the kubeConfig provided - */ kerr, err := exec.LookPath("kubectl") if err != nil { log.Fatal("kubectl command not found, kindly check") diff --git a/cmd/cluster.go b/cmd/cli/cluster.go similarity index 100% rename from cmd/cluster.go rename to cmd/cli/cluster.go diff --git a/cmd/completion.go b/cmd/cli/completion.go similarity index 90% rename from cmd/completion.go rename to cmd/cli/completion.go index 00f003c..b3a9e68 100644 --- a/cmd/completion.go +++ b/cmd/cli/completion.go @@ -18,7 +18,7 @@ import ( "fmt" "os" - "github.com/kubernauts/tk8/internal/cluster" + "github.com/kubernauts/tk8/pkg/common" "github.com/spf13/cobra" ) @@ -47,11 +47,11 @@ var bashCompletion = &cobra.Command{ Long: `It will produce the bash completion script which can later be used for the autocompletion of commands in Bash.`, Run: func(cmd *cobra.Command, args []string) { script, err := os.OpenFile("tk8.sh", os.O_CREATE|os.O_WRONLY, 0600) - cluster.ErrorCheck("Error creating autocompletion script file.", err) + common.ErrorCheck("Error creating autocompletion script file.", err) defer script.Close() err = rootCmd.GenBashCompletion(script) - cluster.ErrorCheck("Error writing to Bash script file", err) + common.ErrorCheck("Error writing to Bash script file", err) fmt.Printf("Successfully created the Bash completion script. Move the 'tk8.sh' file under /etc/bash_completion.d/ folder and login again.") }, } @@ -63,12 +63,12 @@ var zshCompletion = &cobra.Command{ Long: `It will produce the bash completion script which can later be used for the autocompletion of commands in Zsh.`, Run: func(cmd *cobra.Command, args []string) { script, err := os.OpenFile("tk8.plugin.zsh", os.O_CREATE|os.O_WRONLY, 0600) - cluster.ErrorCheck("Error creating autocompletion script file.", err) + common.ErrorCheck("Error creating autocompletion script file.", err) defer script.Close() fmt.Fprintf(script, "__tk8_tool_complete() {\n") err = rootCmd.GenZshCompletion(script) - cluster.ErrorCheck("Error writing to Zsh plugin file", err) + common.ErrorCheck("Error writing to Zsh plugin file", err) fmt.Fprintf(script, "}\ncompdef __tk8_tool_complete tk8") fmt.Printf("Successfully created the Zsh plugin. Move the 'tk8.plugin.zsh' file under your plugins folder and login again.") }, diff --git a/cmd/provisioner.go b/cmd/cli/provisioner.go similarity index 83% rename from cmd/provisioner.go rename to cmd/cli/provisioner.go index 1c36034..4fcfcf6 100644 --- a/cmd/provisioner.go +++ b/cmd/cli/provisioner.go @@ -19,21 +19,20 @@ import ( "os" "strings" - "github.com/kubernauts/tk8/internal" - aws "github.com/kubernauts/tk8-provisioner-aws" azure "github.com/kubernauts/tk8-provisioner-azure" baremetal "github.com/kubernauts/tk8-provisioner-baremetal" eks "github.com/kubernauts/tk8-provisioner-eks" nutanix "github.com/kubernauts/tk8-provisioner-nutanix" openstack "github.com/kubernauts/tk8-provisioner-openstack" - "github.com/kubernauts/tk8/internal/cluster" + "github.com/kubernauts/tk8/pkg/common" + "github.com/kubernauts/tk8/pkg/provisioner" "github.com/spf13/cobra" ) var name string -var provisioners = map[string]cluster.Provisioner{ +var provisioners = map[string]provisioner.Provisioner{ "aws": aws.NewAWS(), "azure": azure.NewAzure(), "baremetal": baremetal.NewBaremetal(), @@ -52,7 +51,9 @@ var provisionerInstallCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { if val, ok := provisioners[args[0]]; ok { val.Init(args[1:]) - val.Setup(args[1:]) + if !provisioner.IOnly { + val.Setup(args[1:]) + } } }, } @@ -160,10 +161,11 @@ func init() { clusterCmd.AddCommand(provisionerUpgradeCmd) clusterCmd.AddCommand(provisionerDestroyCmd) - provisionerInstallCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") - provisionerScaleCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") - provisionerResetCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") - provisionerRemoveCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") - provisionerUpgradeCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") - provisionerDestroyCmd.Flags().StringVar(&cluster.Name, "name", cluster.Name, "name of the cluster workspace") + provisionerInstallCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") + provisionerInstallCmd.Flags().BoolVarP(&provisioner.IOnly, "ionly", "i", provisioner.IOnly, "setup only the infrastructure") + provisionerScaleCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") + provisionerResetCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") + provisionerRemoveCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") + provisionerUpgradeCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") + provisionerDestroyCmd.Flags().StringVar(&common.Name, "name", common.Name, "name of the cluster workspace") } diff --git a/cmd/root.go b/cmd/cli/root.go similarity index 100% rename from cmd/root.go rename to cmd/cli/root.go diff --git a/cmd/version.go b/cmd/cli/version.go similarity index 100% rename from cmd/version.go rename to cmd/cli/version.go diff --git a/docs/en/provisioner/aws/lifecycle.md b/docs/en/provisioner/aws/lifecycle.md index 9861c04..663af28 100644 --- a/docs/en/provisioner/aws/lifecycle.md +++ b/docs/en/provisioner/aws/lifecycle.md @@ -33,4 +33,18 @@ To reset the provisioned cluster run: tk8 cluster reset aws ``` -Once executed a confirmation would be needed to remove Kubernetes from your infrastructure.. +Once executed the current kubernetes installation get removed and a new setup will run. + +## Remove the cluster + +Make sure you are in the same directory where you executed `tk8 cluster install aws` with the inventory directory. +If you use a different workspace name with the --name flag please provide it on resetting too. + +To reset the provisioned cluster run: + +```shell +tk8 cluster remove aws +``` + +Once executed the current kubernetes installation get removed from the infrastructure. + diff --git a/internal/addon/common.go b/internal/addon/common.go deleted file mode 100644 index 1b42e0a..0000000 --- a/internal/addon/common.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright © 2018 The TK8 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 addon - -import ( - "fmt" - "os" - - "github.com/kubernauts/tk8/internal" -) - -// KubeConfig provide the path to the local kube config -var KubeConfig string - -func cloneExample(addonName string) { - if _, err := os.Stat("./addons/" + addonName); err == nil { - fmt.Println("Addon", addonName, "already exist") - os.Exit(0) - } - common.CloneGit("./addons", "https://github.com/kubernauts/tk8-addon-develop", addonName) -} diff --git a/internal/addon/create.go b/internal/addon/create.go deleted file mode 100644 index ba413c1..0000000 --- a/internal/addon/create.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright © 2018 The TK8 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 addon - -import ( - "github.com/kubernauts/tk8/internal" -) - -func PrepareExample(addonName string) { - cloneExample(addonName) - common.ReplaceGit("./addons/" + addonName) -} diff --git a/internal/addon/destory.go b/internal/addon/destory.go deleted file mode 100644 index 99040f8..0000000 --- a/internal/addon/destory.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2018 The TK8 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 addon - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -func DestroyAddon(addonNameOrGitPath string) { - addonName := GetAddon(addonNameOrGitPath) - fmt.Println("Destroying", strings.Replace(addonName, "tk8-addon-", "", 1)) - executeMainSh(addonName) - deleteMainYml(addonName, "yml") - deleteMainYml(addonName, "yaml") - fmt.Println(strings.Replace(addonName, "tk8-addon-", "", 1), "destroy complete") - -} - -func deleteMainYml(addonName string, fileType string) { - - var cEx *exec.Cmd - if _, err := os.Stat("./addons/" + addonName + "/main." + fileType); err == nil { - fmt.Println("delete", strings.Replace(addonName, "tk8-addon-", "", 1), "from cluster") - if len(KubeConfig) > 1 { - cEx = exec.Command("kubectl", "--kubeconfig="+KubeConfig, "delete", "-f", "main."+fileType) - } else { - cEx = exec.Command("kubectl", "delete", "-f", "main."+fileType) - } - cEx.Dir = "./addons/" + addonName - printTerminalLog(cEx) - cEx.Wait() - return - } -} diff --git a/internal/addon/get.go b/internal/addon/get.go deleted file mode 100644 index ac3175c..0000000 --- a/internal/addon/get.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright © 2018 The TK8 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 addon - -import ( - "fmt" - "strings" - - "github.com/kubernauts/tk8/internal" -) - -func GetAddon(addonNameOrGitPath string) string { - addonName := extractAddonName(addonNameOrGitPath) - fmt.Println("Search local for", addonName) - - if checkLocalPath(addonName) { - fmt.Println("Found", addonName, "local.") - return addonName - } - if checkLocalPath("tk8-addon-" + addonName) { - fmt.Println("Found", addonName, "local.") - return "tk8-addon-" + addonName - } - if !checkLocalPath(addonName) { - fmt.Println("check if provided a url") - if strings.Contains(addonNameOrGitPath, "http://") || strings.Contains(addonNameOrGitPath, "https://") { - fmt.Println("Load Addon from external path", addonNameOrGitPath) - common.CloneGit("./addons", addonNameOrGitPath, addonName) - return addonName - } - - fmt.Println("Search addon on kubernauts space.") - common.CloneGit("./addons", "https://github.com/kubernauts/tk8-addon-"+addonName, addonName) - return "tk8-addon-" + addonName - - } - return "tk8-addon-" + addonName - -} diff --git a/internal/addon/install.go b/internal/addon/install.go deleted file mode 100644 index 680ddd2..0000000 --- a/internal/addon/install.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright © 2018 The TK8 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 addon - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "strings" -) - -func InstallAddon(addonNameOrGitPath string) { - addonName := GetAddon(addonNameOrGitPath) - fmt.Println("Install", strings.Replace(addonName, "tk8-addon-", "", 1), addonName) - - executeMainSh(addonName) - applyMainYml(addonName, "yml") - applyMainYml(addonName, "yaml") - fmt.Println(addonName, "installation complete") - -} - -func applyMainYml(addonName string, fileType string) { - - var cEx *exec.Cmd - _, err := os.Stat("./addons/" + addonName + "/main." + fileType) - if err == nil { - fmt.Println("apply main." + fileType) - if len(KubeConfig) > 1 { - cEx = exec.Command("kubectl", "--kubeconfig", KubeConfig, "apply", "-f", "main."+fileType) - } else { - cEx = exec.Command("kubectl", "apply", "-f", "main."+fileType) - } - cEx.Dir = "./addons/" + addonName - printTerminalLog(cEx) - cEx.Wait() - return - } -} - -func executeMainSh(addonName string) { - if _, err := os.Stat("./addons/" + addonName + "/main.sh"); err == nil { - fmt.Println("execute main.sh") - cEx := exec.Command("/bin/sh", "./main.sh") - cEx.Dir = "./addons/" + addonName - printTerminalLog(cEx) - cEx.Wait() - return - } -} - -func printTerminalLog(cEx *exec.Cmd) { - cExOutput, _ := cEx.StdoutPipe() - cEx.Stderr = cEx.Stdout - cEx.Start() - scanner := bufio.NewScanner(cExOutput) - for scanner.Scan() { - m := scanner.Text() - fmt.Println(m) - } -} - -func extractAddonName(addonNameOrGitPath string) string { - if strings.Contains(addonNameOrGitPath, "/") { - stringParts := strings.Split(addonNameOrGitPath, "/") - return stringParts[len(stringParts)-1:][0] - } - return addonNameOrGitPath -} - -func checkLocalPath(addonName string) bool { - if _, err := os.Stat("./addons/" + addonName); err == nil { - fmt.Println("Addon", addonName, "already exist") - return true - } - return false -} diff --git a/internal/addon/main.go b/internal/addon/main.go new file mode 100644 index 0000000..9594680 --- /dev/null +++ b/internal/addon/main.go @@ -0,0 +1,155 @@ +package addon + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/kubernauts/tk8/pkg/common" +) + +type Addon struct { +} + +func (a *Addon) Create(addonName string) (error, string) { + cloneExample(addonName) + common.ReplaceGit("./addons/" + addonName) + return nil, addonName +} + +func (a *Addon) Destroy(addonNameOrGitPath string) (error, string) { + _, addonName := a.Get(addonNameOrGitPath) + fmt.Println("Destroying", strings.Replace(addonName, "tk8-addon-", "", 1)) + executeMainSh(addonName) + deleteMainYml(addonName, "yml") + deleteMainYml(addonName, "yaml") + fmt.Println(strings.Replace(addonName, "tk8-addon-", "", 1), "destroy complete") + + return nil, addonName +} + +func (a *Addon) Get(addonNameOrGitPath string) (error, string) { + addonName := extractAddonName(addonNameOrGitPath) + fmt.Println("Search local for", addonName) + + if checkLocalPath(addonName) { + fmt.Println("Found", addonName, "local.") + return nil, addonName + } + if checkLocalPath("tk8-addon-" + addonName) { + fmt.Println("Found", addonName, "local.") + return nil, "tk8-addon-" + addonName + } + if !checkLocalPath(addonName) { + fmt.Println("check if provided a url") + if strings.Contains(addonNameOrGitPath, "http://") || strings.Contains(addonNameOrGitPath, "https://") { + fmt.Println("Load Addon from external path", addonNameOrGitPath) + common.CloneGit("./addons", addonNameOrGitPath, addonName) + return nil, addonName + } + + fmt.Println("Search addon on kubernauts space.") + common.CloneGit("./addons", "https://github.com/kubernauts/tk8-addon-"+addonName, addonName) + return nil, "tk8-addon-" + addonName + + } + return nil, "tk8-addon-" + addonName + +} + +func (a *Addon) Install(addonNameOrGitPath string) { + _, addonName := a.Get(addonNameOrGitPath) + fmt.Println("Install", strings.Replace(addonName, "tk8-addon-", "", 1), addonName) + + executeMainSh(addonName) + applyMainYml(addonName, "yml") + applyMainYml(addonName, "yaml") + fmt.Println(addonName, "installation complete") + +} + +// KubeConfig provide the path to the local kube config +var KubeConfig string + +func applyMainYml(addonName string, fileType string) { + + var cEx *exec.Cmd + _, err := os.Stat("./addons/" + addonName + "/main." + fileType) + if err == nil { + fmt.Println("apply main." + fileType) + if len(KubeConfig) > 1 { + cEx = exec.Command("kubectl", "--kubeconfig", KubeConfig, "apply", "-f", "main."+fileType) + } else { + cEx = exec.Command("kubectl", "apply", "-f", "main."+fileType) + } + cEx.Dir = "./addons/" + addonName + printTerminalLog(cEx) + cEx.Wait() + return + } +} + +func executeMainSh(addonName string) { + if _, err := os.Stat("./addons/" + addonName + "/main.sh"); err == nil { + fmt.Println("execute main.sh") + cEx := exec.Command("/bin/sh", "./main.sh") + cEx.Dir = "./addons/" + addonName + printTerminalLog(cEx) + cEx.Wait() + return + } +} + +func printTerminalLog(cEx *exec.Cmd) { + cExOutput, _ := cEx.StdoutPipe() + cEx.Stderr = cEx.Stdout + cEx.Start() + scanner := bufio.NewScanner(cExOutput) + for scanner.Scan() { + m := scanner.Text() + fmt.Println(m) + } +} + +func extractAddonName(addonNameOrGitPath string) string { + if strings.Contains(addonNameOrGitPath, "/") { + stringParts := strings.Split(addonNameOrGitPath, "/") + return stringParts[len(stringParts)-1:][0] + } + return addonNameOrGitPath +} + +func checkLocalPath(addonName string) bool { + if _, err := os.Stat("./addons/" + addonName); err == nil { + fmt.Println("Addon", addonName, "already exist") + return true + } + return false +} + +func cloneExample(addonName string) { + if _, err := os.Stat("./addons/" + addonName); err == nil { + fmt.Println("Addon", addonName, "already exist") + os.Exit(0) + } + common.CloneGit("./addons", "https://github.com/kubernauts/tk8-addon-develop", addonName) +} + +func deleteMainYml(addonName string, fileType string) { + + var cEx *exec.Cmd + if _, err := os.Stat("./addons/" + addonName + "/main." + fileType); err == nil { + fmt.Println("delete", strings.Replace(addonName, "tk8-addon-", "", 1), "from cluster") + if len(KubeConfig) > 1 { + cEx = exec.Command("kubectl", "--kubeconfig="+KubeConfig, "delete", "-f", "main."+fileType) + } else { + cEx = exec.Command("kubectl", "delete", "-f", "main."+fileType) + } + cEx.Dir = "./addons/" + addonName + printTerminalLog(cEx) + cEx.Wait() + return + } +} diff --git a/internal/cluster/aws-sshKeyCreator.go b/internal/cluster/aws-sshKeyCreator.go deleted file mode 100644 index 9b02782..0000000 --- a/internal/cluster/aws-sshKeyCreator.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "fmt" - "os" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" -) - -// CreateSSHKey is used to create a new SSH key in AWS for the user. -// It is called when a default config needs to be generated. -func CreateSSHKey(pairName, region string) { - // Start a new AWS auth session. - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(region)}, - ) - - // Create an EC2 service client. - svc := ec2.New(sess) - - result, err := svc.CreateKeyPair(&ec2.CreateKeyPairInput{ - KeyName: aws.String(pairName), - }) - errorCheck(err) - - // Create the SSH Key on disk. - sshKey, err := os.OpenFile(pairName, os.O_CREATE|os.O_WRONLY, 0600) - errorCheck(err) - fmt.Fprintf(sshKey, *result.KeyMaterial) - fmt.Printf("\n" + "Successfully created config file and SSH key." + "\n" + - "You can use the newly created SSH key by adding it to the SSH agent. More info: " + - "https://www.ssh.com/ssh/add" + "\n\n") -} - -func errorCheck(err error) { - if err != nil { - if aerr, ok := err.(awserr.Error); ok && aerr.Code() == "InvalidKeyPair.Duplicate" { - ExitErrorf("Specified keypair already exists.") - } - ExitErrorf("Error while trying to create the specified key pair: %v.", err) - } -} diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go deleted file mode 100644 index e8b18a8..0000000 --- a/internal/cluster/aws.go +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "fmt" - "log" - "net" - "os" - "os/exec" - "strings" - "time" - - "github.com/kubernauts/tk8/internal/templates" -) - -var ec2IP string - -func distSelect() (string, string) { - //Read Configuration File - awsAmiID, awsInstanceOS, sshUser := GetDistConfig() - - if awsAmiID != "" && sshUser == "" { - log.Fatal("SSH Username is required when using custom AMI") - return "", "" - } - if awsAmiID == "" && awsInstanceOS == "" { - log.Fatal("Provide either of AMI ID or OS in the config file.") - return "", "" - } - - if awsAmiID != "" && sshUser != "" { - awsInstanceOS = "custom" - DistOSMap["custom"] = DistOS{ - User: sshUser, - AmiOwner: awsAmiID, - OS: "custom", - } - } - - return DistOSMap[awsInstanceOS].User, awsInstanceOS -} - -func prepareConfigFiles(awsInstanceOS string) { - if awsInstanceOS == "custom" { - ParseTemplate(templates.CustomInfrastructure, "./inventory/"+Name+"/provisioner/create-infrastructure.tf", DistOSMap[awsInstanceOS]) - } else { - ParseTemplate(templates.Infrastructure, "./inventory/"+Name+"/provisioner/create-infrastructure.tf", DistOSMap[awsInstanceOS]) - } - - ParseTemplate(templates.Credentials, "./inventory/"+Name+"/provisioner/credentials.tfvars", GetCredentials()) - ParseTemplate(templates.Variables, "./inventory/"+Name+"/provisioner/variables.tf", DistOSMap[awsInstanceOS]) - ParseTemplate(templates.Terraform, "./inventory/"+Name+"/provisioner/terraform.tfvars", GetClusterConfig()) -} - -func prepareInventoryGroupAllFile(fileName string) *os.File { - groupVars, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, 0600) - ErrorCheck("Error while trying to open "+fileName+": %v.", err) - return groupVars -} - -func prepareInventoryClusterFile(fileName string) *os.File { - k8sClusterFile, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, 0600) - defer k8sClusterFile.Close() - ErrorCheck("Error while trying to open "+fileName+": %v.", err) - fmt.Fprintf(k8sClusterFile, "kubeconfig_localhost: true\n") - return k8sClusterFile -} - -// AWSCreate is used to create a infrastructure on AWS. -func AWSCreate() { - - if _, err := os.Stat("./inventory/" + Name + "/provisioner/.terraform"); err == nil { - fmt.Println("Configuration folder already exists") - } else { - sshUser, osLabel := distSelect() - fmt.Printf("Prepairing Setup for user %s on %s\n", sshUser, osLabel) - os.MkdirAll("./inventory/"+Name+"/provisioner", 0755) - err := exec.Command("cp", "-rfp", "./kubespray/contrib/terraform/aws/.", "./inventory/"+Name+"/provisioner").Run() - ErrorCheck("provisioner could not provided: %v", err) - prepareConfigFiles(osLabel) - ExecuteTerraform("init", "./inventory/"+Name+"/provisioner/") - } - - ExecuteTerraform("apply", "./inventory/"+Name+"/provisioner/") - - // waiting for Loadbalancer and other not completed stuff - fmt.Println("Infrastructure is upcoming.") - time.Sleep(15 * time.Second) - return - -} - -// AWSInstall is used for installing Kubernetes on the available infrastructure. -func AWSInstall() { - // check if ansible is installed - DependencyCheck("ansible") - - // Copy the configuraton files as indicated in the kubespray docs - if _, err := os.Stat("./inventory/" + Name + "/installer"); err == nil { - fmt.Println("Configuration folder already exists") - } else { - os.MkdirAll("./inventory/"+Name+"/installer", 0755) - mvHost := exec.Command("mv", "./inventory/hosts", "./inventory/"+Name+"/hosts") - mvHost.Run() - mvHost.Wait() - mvShhBastion := exec.Command("cp", "./kubespray/ssh-bastion.conf", "./inventory/"+Name+"/ssh-bastion.conf") - mvShhBastion.Run() - mvShhBastion.Wait() - cpSample := exec.Command("cp", "-rfp", "./kubespray/inventory/sample/.", "./inventory/"+Name+"/installer/") - cpSample.Run() - cpSample.Wait() - - cpKube := exec.Command("cp", "-rfp", "./kubespray/.", "./inventory/"+Name+"/installer/") - cpKube.Run() - cpKube.Wait() - - mvInstallerHosts := exec.Command("cp", "./inventory/"+Name+"/hosts", "./inventory/"+Name+"/installer/hosts") - mvInstallerHosts.Run() - mvInstallerHosts.Wait() - mvProvisionerHosts := exec.Command("cp", "./inventory/"+Name+"/hosts", "./inventory/"+Name+"/installer/hosts") - mvProvisionerHosts.Run() - mvProvisionerHosts.Wait() - - // Check if Kubeadm is enabled - EnableKubeadm() - - //Start Kubernetes Installation - //Enable load balancer api access and copy the kubeconfig file locally - loadBalancerName, err := exec.Command("sh", "-c", "grep apiserver_loadbalancer_domain_name= ./inventory/"+Name+"/installer/hosts | cut -d'=' -f2").CombinedOutput() - - if err != nil { - fmt.Println("Problem getting the load balancer domain name", err) - } else { - var groupVars *os.File - //Make a copy of kubeconfig on Ansible host - if kubesprayVersion == "develop" { - // Set Kube Network Proxy - SetNetworkPlugin("./inventory/" + Name + "/installer/group_vars/k8s-cluster") - prepareInventoryClusterFile("./inventory/" + Name + "/installer/group_vars/k8s-cluster/k8s-cluster.yml") - groupVars = prepareInventoryGroupAllFile("./inventory/" + Name + "/installer/group_vars/all/all.yml") - } else { - // Set Kube Network Proxy - SetNetworkPlugin("./inventory/" + Name + "/installer/group_vars") - prepareInventoryClusterFile("./inventory/" + Name + "/installer/group_vars/k8s-cluster.yml") - groupVars = prepareInventoryGroupAllFile("./inventory/" + Name + "/installer/group_vars/all.yml") - } - defer groupVars.Close() - // Resolve Load Balancer Domain Name and pick the first IP - - elbNameRaw, _ := exec.Command("sh", "-c", "grep apiserver_loadbalancer_domain_name= ./inventory/"+Name+"/installer/hosts | cut -d'=' -f2 | sed 's/\"//g'").CombinedOutput() - - // Convert the Domain name to string, strip all spaces so that Lookup does not return errors - elbName := strings.TrimSpace(string(elbNameRaw)) - fmt.Println(elbName) - node, err := net.LookupHost(elbName) - ErrorCheck("Error resolving ELB name: %v", err) - elbIP := node[0] - fmt.Println(node) - - DomainName := strings.TrimSpace(string(loadBalancerName)) - loadBalancerDomainName := "apiserver_loadbalancer_domain_name: " + DomainName - - fmt.Fprintf(groupVars, "#Set cloud provider to AWS\n") - fmt.Fprintf(groupVars, "cloud_provider: 'aws'\n") - fmt.Fprintf(groupVars, "#Load Balancer Configuration\n") - fmt.Fprintf(groupVars, "loadbalancer_apiserver_localhost: false\n") - fmt.Fprintf(groupVars, "%s\n", loadBalancerDomainName) - fmt.Fprintf(groupVars, "loadbalancer_apiserver:\n") - fmt.Fprintf(groupVars, " address: %s\n", elbIP) - fmt.Fprintf(groupVars, " port: 6443\n") - } - } - - RunPlaybook("./inventory/"+Name+"/installer/", "cluster.yml") - - return -} - -// AWSDestroy is used to destroy the infrastructure created. -func AWSDestroy() { - // Check if credentials file exist, if it exists skip asking to input the AWS values - if _, err := os.Stat("./inventory/" + Name + "/provisioner/credentials.tfvars"); err == nil { - fmt.Println("Credentials file already exists, creation skipped") - } else { - - ParseTemplate(templates.Credentials, "./inventory/"+Name+"/provisioner/credentials.tfvars", GetCredentials()) - } - cpHost := exec.Command("cp", "./inventory/"+Name+"/hosts", "./inventory/hosts") - cpHost.Run() - cpHost.Wait() - - ExecuteTerraform("destroy", "./inventory/"+Name+"/provisioner/") - - exec.Command("rm", "./inventory/hosts").Run() - exec.Command("rm", "-rf", "./inventory/"+Name).Run() - - return -} - -// AWSScale is used to scale the AWS infrastructure and Kubernetes -func AWSScale() { - var confirmation string - // Scale the AWS infrastructure - fmt.Printf("\t\t===============Starting AWS Scaling====================\n\n") - ExecuteTerraform("apply", "./inventory/"+Name+"/provisioner/") - mvHost := exec.Command("mv", "./inventory/hosts", "./inventory/"+Name+"/hosts") - mvHost.Run() - mvHost.Wait() - - // Scale the Kubernetes cluster - fmt.Printf("\n\n\t\t===============Starting Kubernetes Scaling====================\n\n") - _, err := os.Stat("./inventory/" + Name + "/provisioner/hosts") - ErrorCheck("No host file found.", err) - fmt.Printf("\n\nThis will overwrite the previous host file with a new one. Type \"yes\" to confirm:\n") - fmt.Scanln(&confirmation) - if confirmation != "yes" { - fmt.Printf("Confirmation denied. Exiting...") - os.Exit(0) - } - RunPlaybook("./inventory/"+Name+"/installer/", "scale.yml") - - return -} - -// AWSReset is used to reset the AWS infrastructure and removing Kubernetes from it. -func AWSReset() { - RunPlaybook("./inventory/"+Name+"/installer/", "reset.yml") - return -} - -func AWSRemove() { - NotImplemented() -} diff --git a/internal/cluster/awsConfig.go b/internal/cluster/awsConfig.go deleted file mode 100644 index 5ff0e7b..0000000 --- a/internal/cluster/awsConfig.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "flag" - "fmt" - "math/rand" - "os" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" - petname "github.com/dustinkirkland/golang-petname" - "github.com/kubernauts/tk8/internal/templates" - "github.com/spf13/viper" -) - -// Config holds the variables to be used in the default configuration. -type Config struct { - AccessKey string - SecretKey string - ClusterName string - SSHName string -} - -func namer(name string) Config { - return Config{ - ClusterName: name, - SSHName: name, - } -} - -func generateName() string { - var ( - words = flag.Int("words", 2, "The number of words in generated name") - separator = flag.String("separator", "", "The separator between words in the name") - ) - flag.Parse() - rand.Seed(time.Now().UnixNano()) - generatedName := petname.Generate(*words, *separator) - return generatedName -} - -func getCreds() (string, string) { - var accessKey, secretKey string - fmt.Print("Enter AWS Access Key: ") - fmt.Scanln(&accessKey) - fmt.Print("Enter AWS Secret Key: ") - fmt.Scanln(&secretKey) - - err := os.Setenv("AWS_ACCESS_KEY_ID", accessKey) - err = os.Setenv("AWS_SECRET_ACCESS_KEY", secretKey) - ErrorCheck("Error setting the credentials environment variable: ", err) - - return accessKey, secretKey -} - -func checkCredentials() error { - sess, err := session.NewSession(&aws.Config{}) - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &credentials.SharedCredentialsProvider{}, - &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(sess), - }, - }) - _, err = creds.Get() - if err != nil { - return err - } - return nil -} - -// CreateConfig is responsible for creating a default config incase when none is provided. -func CreateConfig() { - generatedName := generateName() - fmt.Printf("\nNo default config was provided. Generating one for you...\n") - err := checkCredentials() - confStruct := Config{} - if err != nil { - accessKey, secretKey := getCreds() - confStruct = Config{AccessKey: accessKey, SecretKey: secretKey, ClusterName: generatedName, SSHName: generatedName} - } - ParseTemplate(templates.Config, "./config.yaml", confStruct) - ReadViperConfigFile("config") - region := viper.GetString("aws.aws_default_region") - CreateSSHKey(generatedName, region) - fmt.Printf("\nCluster Name:\t%s\nSSH Key name:\t%s\nAWS Region:\t%s\n", generatedName, generatedName, region) -} diff --git a/internal/cluster/aws_test.go b/internal/cluster/aws_test.go deleted file mode 100644 index 2a70c76..0000000 --- a/internal/cluster/aws_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright © 2018 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 cluster - -import ( - "testing" -) - -func Test_parseTemplate(t *testing.T) { - type args struct { - templateName string - outputFileName string - data interface{} - } - tests := []struct { - name string - args args - }{ - // TODO: Add test cases. - { - name: "test1", - args: args{ - templateName: "../../templates/create-infrastructure.tf", - outputFileName: "../../output/create-infrastructure.tf", - data: DistOSMap["ubuntu"], - }, - }, { - name: "test2", - args: args{ - templateName: "../../templates/credentials.tfvars", - outputFileName: "../../output/credentials.tfvars", - data: GetCredentials(), - }, - }, { - name: "test3", - args: args{ - templateName: "../../templates/terraform.tfvars", - outputFileName: "../../output/terraform.tfvars", - data: GetClusterConfig(), - }, - }, { - name: "test4", - args: args{ - templateName: "../../templates/variables.tf", - outputFileName: "../../output/variables.tf", - data: DistOSMap["ubuntu"], - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - parseTemplate(tt.args.templateName, tt.args.outputFileName, tt.args.data) - }) - } -} diff --git a/internal/cluster/common.go b/internal/cluster/common.go deleted file mode 100644 index 5bad984..0000000 --- a/internal/cluster/common.go +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "strings" - - "github.com/alecthomas/template" - "github.com/spf13/viper" -) - -// AwsCredentials defines the structure to hold AWS auth credentials. -type AwsCredentials struct { - AwsAccessKeyID string - AwsSecretKey string - AwsAccessSSHKey string - AwsDefaultRegion string -} - -var ( - kubesprayVersion = "version-0-4" - Name string -) - -// DistOS defines the structure to hold the dist OS informations. -// It is possible to easily extend the list of OS. -// Append new entry to cluster.DistOSMap and use the key(string) in the config. -type DistOS struct { - User string - AmiOwner string - OS string -} - -// DistOSMap holds the main OS distrubution mapping informations. -var DistOSMap = map[string]DistOS{ - "centos": DistOS{ - User: "centos", - AmiOwner: "688023202711", - OS: "dcos-centos7-*", - }, - "ubuntu": DistOS{ - User: "ubuntu", - AmiOwner: "099720109477", - OS: "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*", - }, - "coreos": DistOS{ - User: "core", - AmiOwner: "595879546273", - OS: "CoreOS-stable-*", - }, -} - -// ClusterConfig holds the info required to create a cluster. -// This value is read from the config.yaml file through viper. -type ClusterConfig struct { - AwsClusterName string - AwsVpcCidrBlock string - AwsCidrSubnetsPrivate string - AwsCidrSubnetsPublic string - AwsBastionSize string - AwsKubeMasterNum string - AwsKubeMasterSize string - AwsEtcdNum string - AwsEtcdSize string - AwsKubeWorkerNum string - AwsKubeWorkerSize string - AwsElbAPIPort string - K8sSecureAPIPort string - KubeInsecureApiserverAddress string -} - -// ReadViperConfigFile is define the config paths and read the configuration file. -func ReadViperConfigFile(configName string) { - viper.SetConfigName(configName) - viper.AddConfigPath(".") - viper.AddConfigPath("/tk8") - verr := viper.ReadInConfig() // Find and read the config file. - if verr != nil { // Handle errors reading the config file. - CreateConfig() - } -} - -// GetDistConfig is used to get config details specific to a particular distribution. -// Used to determine various details such as the SSH user about the distribution. -func GetDistConfig() (string, string, string) { - ReadViperConfigFile("config") - awsAmiID := viper.GetString("aws.ami_id") - awsInstanceOS := viper.GetString("aws.os") - sshUser := viper.GetString("aws.ssh_user") - return awsAmiID, awsInstanceOS, sshUser -} - -// GetCredentials get the aws credentials from the config file. -func GetCredentials() AwsCredentials { - ReadViperConfigFile("config") - return AwsCredentials{ - AwsAccessKeyID: viper.GetString("aws.aws_access_key_id"), - AwsSecretKey: viper.GetString("aws.aws_secret_access_key"), - AwsAccessSSHKey: viper.GetString("aws.aws_ssh_keypair"), - AwsDefaultRegion: viper.GetString("aws.aws_default_region"), - } -} - -type EKSConfig struct { - ClusterName string - AWSRegion string - NodeInstanceType string - DesiredCapacity int - AutoScallingMinSize int - AutoScallingMaxSize int - KeyPath string -} - -// GetCredentials get the aws credentials from the config file. -func GetEKSConfig() EKSConfig { - ReadViperConfigFile("config") - return EKSConfig{ - ClusterName: viper.GetString("eks.cluster-name"), - AWSRegion: viper.GetString("eks.aws_region"), - NodeInstanceType: viper.GetString("eks.node-instance-type"), - DesiredCapacity: viper.GetInt("eks.desired-capacity"), - AutoScallingMinSize: viper.GetInt("eks.autoscalling-min-size"), - AutoScallingMaxSize: viper.GetInt("eks.autoscalling-max-size"), - KeyPath: viper.GetString("eks.key-file-path"), - } -} - -// GetClusterConfig get the configuration from the config file. -func GetClusterConfig() ClusterConfig { - ReadViperConfigFile("config") - return ClusterConfig{ - AwsClusterName: viper.GetString("aws.clustername"), - AwsVpcCidrBlock: viper.GetString("aws.aws_vpc_cidr_block"), - AwsCidrSubnetsPrivate: viper.GetString("aws.aws_cidr_subnets_private"), - AwsCidrSubnetsPublic: viper.GetString("aws.aws_cidr_subnets_public"), - AwsBastionSize: viper.GetString("aws.aws_bastion_size"), - AwsKubeMasterNum: viper.GetString("aws.aws_kube_master_num"), - AwsKubeMasterSize: viper.GetString("aws.aws_kube_master_size"), - AwsEtcdNum: viper.GetString("aws.aws_etcd_num"), - AwsEtcdSize: viper.GetString("aws.aws_etcd_size"), - AwsKubeWorkerNum: viper.GetString("aws.aws_kube_worker_num"), - AwsKubeWorkerSize: viper.GetString("aws.aws_kube_worker_size"), - AwsElbAPIPort: viper.GetString("aws.aws_elb_api_port"), - K8sSecureAPIPort: viper.GetString("aws.k8s_secure_api_port"), - KubeInsecureApiserverAddress: viper.GetString("aws."), - } -} - -func ParseTemplate(templateString string, outputFileName string, data interface{}) { - // open template - template := template.New("template") - template, _ = template.Parse(templateString) - // open output file - outputFile, err := os.Create(GetFilePath(outputFileName)) - defer outputFile.Close() - if err != nil { - ExitErrorf("Error creating file %s: %v", outputFile, err) - } - err = template.Execute(outputFile, data) - ErrorCheck("Error executing template: %v", err) - -} - -// EnableKubeadm check for kubeadm_enable option and set the config respectively in playbook. -func EnableKubeadm() { - ReadViperConfigFile("config") - kubeadmEnabled := viper.GetString("aws.kubeadm_enabled") - if kubeadmEnabled == "true" { - viper.SetConfigName("main") - viper.AddConfigPath("./kubespray/roles/kubespray-defaults/defaults") - err := viper.ReadInConfig() - ErrorCheck("Error reading the main.yaml config file", err) - viper.Set("kubeadm_enabled", true) - err = viper.WriteConfig() - ErrorCheck("Error writing the main.yaml config file", err) - } -} - -func SetNetworkPlugin(clusterFolder string) { - - ReadViperConfigFile("config") - kubeNetworkPlugin := viper.GetString("aws.kube_network_plugin") - viper.SetConfigName("k8s-cluster") - viper.AddConfigPath(clusterFolder) - err := viper.ReadInConfig() - ErrorCheck("Error reading the main.yaml config file", err) - if len(kubeNetworkPlugin) > 3 { - viper.Set("kube_network_plugin", kubeNetworkPlugin) - err = viper.WriteConfig() - } - -} - -// ErrorCheck is responsbile to check if there is any error returned by a command. -func ErrorCheck(msg string, err error) { - if err != nil { - ExitErrorf(msg, err) - } -} - -// DependencyCheck check if the binary is installed -func DependencyCheck(bin string) { - _, err := exec.LookPath(bin) - ErrorCheck(bin+" not found.", err) - - _, err = exec.Command(bin, "--version").Output() - ErrorCheck("Error executing "+bin, err) -} - -// ExitErrorf exits the program with an error code of '1' and an error message. -func ExitErrorf(msg string, args ...interface{}) { - fmt.Fprintf(os.Stderr, msg+"\n", args...) - os.Exit(1) -} - -type Provisioner interface { - Init(args []string) - Setup(args []string) - Scale(args []string) - Remove(args []string) - Reset(args []string) - Upgrade(args []string) - Destroy(args []string) -} - -func NotImplemented() { - fmt.Println("Not implemented yet. Coming soon...") - os.Exit(0) -} - -func SetClusterName() { - if len(Name) < 1 { - config := GetClusterConfig() - Name = config.AwsClusterName - } -} - -func RunPlaybook(path string, file string) { - DependencyCheck("ansible") - sshUser, osLabel := distSelect() - fmt.Printf("\nStarting playbook for user %s with os %s\n", sshUser, osLabel) - ansiblePlaybook := exec.Command("ansible-playbook", "-i", "hosts", file, "--timeout=60", "-e ansible_user="+sshUser, "-e ansible_user="+sshUser, "-e bootstrap_os="+osLabel, "-b", "--become-user=root", "--flush-cache") - ansiblePlaybook.Dir = path - ansiblePlaybook.Stdout = os.Stdout - ansiblePlaybook.Stdin = os.Stdin - ansiblePlaybook.Stderr = os.Stderr - - ansiblePlaybook.Start() - ansiblePlaybook.Wait() -} - -func ExecuteTerraform(command string, path string) { - - DependencyCheck("terraform") - var terrSet *exec.Cmd - - if strings.Compare(strings.TrimRight(command, "\n"), "init") == 0 { - terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars") - } else if strings.Compare(command, "apply") == 0 { - terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars", "-auto-approve") - } else { - terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars", "-force") - } - - terrSet.Dir = path - stdout, _ := terrSet.StdoutPipe() - terrSet.Stderr = terrSet.Stdout - error := terrSet.Start() - if error != nil { - fmt.Println(error) - } - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - m := scanner.Text() - fmt.Println(m) - if strings.Contains(m, "Error: Error applying plan") { - fmt.Println("Terraform could not setup the infrastructure") - os.Exit(1) - } - } - - terrSet.Wait() -} diff --git a/internal/cluster/init.go b/internal/cluster/init.go deleted file mode 100644 index 20d3b32..0000000 --- a/internal/cluster/init.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "bufio" - "fmt" - "log" - "os" - "os/exec" -) - -// KubesprayInit is responsible for cloning the kubespray diretory in CWD. -func KubesprayInit() { - if _, err := os.Stat("./kubespray"); err == nil { - fmt.Println("Kubespray clone on this system already exists") - return - } - fmt.Println("Initialising kubespray git repo") - if _, err := exec.LookPath("git"); err != nil { - log.Fatal("either 'git' is not installed or not found in $PATH, kindly check and fix") - os.Exit(1) - } else { - // issue-23 kubespray upstream - gitClone := exec.Command("git", "clone", "-b", kubesprayVersion, "--single-branch", "https://github.com/kubernauts/kubespray") - stdout, err := gitClone.StdoutPipe() - gitClone.Stderr = gitClone.Stdout - gitClone.Start() - - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - m := scanner.Text() - fmt.Println(m) - } - gitClone.Wait() - if err != nil { - log.Fatalf("Seems there is a problem cloning the kubespray repo, %v", err) - os.Exit(1) - } - } - if _, err := exec.LookPath("pip"); err != nil { - log.Fatal("either 'pip' is not installed or not found in $PATH, kindly check and fix") - os.Exit(1) - } else { - // Ensure to have all the dependencies of Kubespray - err := exec.Command("pip", "install", "-r", "kubespray/requirements.txt").Run() - if err != nil { - log.Fatalf("Seems there is a problem installing the kubespray dependencies. " + - "Please run following command:" + - "\n\n\t" + - "pip install -r kubespray/requirements.txt" + - "\nNOTE: Elevated permission may require.") - os.Exit(1) - } - } -} diff --git a/internal/cluster/showPath.go b/internal/cluster/showPath.go deleted file mode 100644 index c1eb818..0000000 --- a/internal/cluster/showPath.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright © 2018 The TK8 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 cluster - -import ( - "os" - "path/filepath" -) - -// GetFilePath fetches and returns the current working directory. -func GetFilePath(fileName string) string { - cwd, _ := os.Getwd() - return filepath.Join(cwd, fileName) -} diff --git a/internal/common.go b/internal/common.go deleted file mode 100644 index 3f3acfe..0000000 --- a/internal/common.go +++ /dev/null @@ -1,35 +0,0 @@ -package common - -import ( - "bufio" - "fmt" - "os" - "os/exec" -) - -func CloneGit(executeDir string, gitUrl string, targetFolder string) error { - os.Mkdir(executeDir, 0755) - cEx := exec.Command("git", "clone", gitUrl, targetFolder) - cEx.Dir = executeDir - stdout, _ := cEx.StdoutPipe() - cEx.Stderr = cEx.Stdout - error := cEx.Start() - if error != nil { - fmt.Println(error) - } - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - m := scanner.Text() - fmt.Println(m) - } - - cEx.Wait() - return nil -} - -func ReplaceGit(executeDir string) { - cEx := exec.Command("rm", "-rf", ".git") - cEx.Dir = executeDir - cEx.Run() - cEx.Wait() -} diff --git a/main.go b/main.go index 7ed6da7..5ead6df 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ package main -import "github.com/kubernauts/tk8/cmd" +import "github.com/kubernauts/tk8/cmd/cli" func main() { cmd.Execute() diff --git a/md-test-result/0-5.md b/md-test-result/0-5.md deleted file mode 100644 index f3b75a8..0000000 --- a/md-test-result/0-5.md +++ /dev/null @@ -1,33 +0,0 @@ -# Test Result v0.5.0 - -## Test 1 - -### install aws - -| master | etcd | nodes | os | result | -| --- | --- | --- | --- | --- | -| 1 | 1 | 1 | ubuntu | / | -| 2 | 3 | 3 | ubuntu | / | -| 1 | 1 | 1 | centos | - | -| 2 | 3 | 3 | centos | - | -| 1 | 1 | 1 | coreos | - | -| 2 | 3 | 3 | coreos | - | - -| test | nodes | services | pods | -| --- |---|---|---| -| 1 | / | / | / | -| 2 | / | / | / | -| 3 | - | - | - | -| 4 | - | - | - | -| 5 | - | - | - | -| 6 | - | - | - | - -### install eks - -| master | etcd | nodes | os | result | -| --- | --- | --- | --- | --- | -| / | / | 1 | eks ami | - | - -| nodes | services | pods | -|---|---|---| -|- | - | - | \ No newline at end of file diff --git a/pkg/common/main.go b/pkg/common/main.go new file mode 100644 index 0000000..fe8cc5e --- /dev/null +++ b/pkg/common/main.go @@ -0,0 +1,66 @@ +package common + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "path/filepath" +) + +var Name string + +// ErrorCheck is responsbile to check if there is any error returned by a command. +func ErrorCheck(msg string, err error) { + if err != nil { + ExitErrorf(msg, err) + } +} + +// DependencyCheck check if the binary is installed +func DependencyCheck(bin string) { + _, err := exec.LookPath(bin) + ErrorCheck(bin+" not found.", err) + + _, err = exec.Command(bin, "--version").Output() + ErrorCheck("Error executing "+bin, err) +} + +// ExitErrorf exits the program with an error code of '1' and an error message. +func ExitErrorf(msg string, args ...interface{}) { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + os.Exit(1) +} + +func CloneGit(executeDir string, gitUrl string, targetFolder string) error { + os.Mkdir(executeDir, 0755) + cEx := exec.Command("git", "clone", gitUrl, targetFolder) + cEx.Dir = executeDir + stdout, _ := cEx.StdoutPipe() + cEx.Stderr = cEx.Stdout + error := cEx.Start() + if error != nil { + fmt.Println(error) + } + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + m := scanner.Text() + fmt.Println(m) + } + + cEx.Wait() + return nil +} + +func ReplaceGit(executeDir string) { + cEx := exec.Command("rm", "-rf", ".git") + cEx.Dir = executeDir + cEx.Run() + cEx.Wait() +} + +// GetFilePath fetches and returns the current working directory. +func GetFilePath(fileName string) string { + cwd, _ := os.Getwd() + return filepath.Join(cwd, fileName) +} diff --git a/pkg/installer/main.go b/pkg/installer/main.go new file mode 100644 index 0000000..fdda9d5 --- /dev/null +++ b/pkg/installer/main.go @@ -0,0 +1,22 @@ +package installer + +import ( + "fmt" + "os" + "os/exec" + + "github.com/kubernauts/tk8/pkg/common" +) + +func RunPlaybook(path string, file string, sshUser string, osLabel string) { + common.DependencyCheck("ansible") + fmt.Printf("\nStarting playbook for user %s with os %s\n", sshUser, osLabel) + ansiblePlaybook := exec.Command("ansible-playbook", "-i", "hosts", file, "--timeout=60", "-e ansible_user="+sshUser, "-e ansible_user="+sshUser, "-e bootstrap_os="+osLabel, "-b", "--become-user=root", "--flush-cache") + ansiblePlaybook.Dir = path + ansiblePlaybook.Stdout = os.Stdout + ansiblePlaybook.Stdin = os.Stdin + ansiblePlaybook.Stderr = os.Stderr + + ansiblePlaybook.Start() + ansiblePlaybook.Wait() +} diff --git a/pkg/provisioner/main.go b/pkg/provisioner/main.go new file mode 100644 index 0000000..e12f8ba --- /dev/null +++ b/pkg/provisioner/main.go @@ -0,0 +1,61 @@ +package provisioner + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/kubernauts/tk8/pkg/common" +) + +var IOnly bool = false + +type Provisioner interface { + Init(args []string) + Setup(args []string) + Scale(args []string) + Remove(args []string) + Reset(args []string) + Upgrade(args []string) + Destroy(args []string) +} + +func NotImplemented() { + fmt.Println("Not implemented yet. Coming soon...") + os.Exit(0) +} + +func ExecuteTerraform(command string, path string) { + + common.DependencyCheck("terraform") + var terrSet *exec.Cmd + + if strings.Compare(strings.TrimRight(command, "\n"), "init") == 0 { + terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars") + } else if strings.Compare(command, "apply") == 0 { + terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars", "-auto-approve") + } else { + terrSet = exec.Command("terraform", command, "-var-file=credentials.tfvars", "-force") + } + + terrSet.Dir = path + stdout, _ := terrSet.StdoutPipe() + terrSet.Stderr = terrSet.Stdout + error := terrSet.Start() + if error != nil { + fmt.Println(error) + } + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + m := scanner.Text() + fmt.Println(m) + if strings.Contains(m, "Error: Error applying plan") { + fmt.Println("Terraform could not setup the infrastructure") + os.Exit(1) + } + } + + terrSet.Wait() +} diff --git a/internal/templates/config.go b/pkg/templates/config.go similarity index 100% rename from internal/templates/config.go rename to pkg/templates/config.go diff --git a/internal/templates/create-custom-infrastructure.go b/pkg/templates/create-custom-infrastructure.go similarity index 100% rename from internal/templates/create-custom-infrastructure.go rename to pkg/templates/create-custom-infrastructure.go diff --git a/internal/templates/create-infrastructure.go b/pkg/templates/create-infrastructure.go similarity index 100% rename from internal/templates/create-infrastructure.go rename to pkg/templates/create-infrastructure.go diff --git a/internal/templates/credentials.go b/pkg/templates/credentials.go similarity index 100% rename from internal/templates/credentials.go rename to pkg/templates/credentials.go diff --git a/pkg/templates/main.go b/pkg/templates/main.go new file mode 100644 index 0000000..81354e3 --- /dev/null +++ b/pkg/templates/main.go @@ -0,0 +1,23 @@ +package templates + +import ( + "os" + + "github.com/alecthomas/template" + "github.com/kubernauts/tk8/pkg/common" +) + +func ParseTemplate(templateString string, outputFileName string, data interface{}) { + // open template + template := template.New("template") + template, _ = template.Parse(templateString) + // open output file + outputFile, err := os.Create(common.GetFilePath(outputFileName)) + defer outputFile.Close() + if err != nil { + common.ExitErrorf("Error creating file %s: %v", outputFile, err) + } + err = template.Execute(outputFile, data) + common.ErrorCheck("Error executing template: %v", err) + +} diff --git a/internal/templates/terraform.go b/pkg/templates/terraform.go similarity index 100% rename from internal/templates/terraform.go rename to pkg/templates/terraform.go diff --git a/internal/templates/variables.go b/pkg/templates/variables.go similarity index 100% rename from internal/templates/variables.go rename to pkg/templates/variables.go diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..c1cf0c8 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,15 @@ +sonar.projectKey=mmmac +sonar.projectName=tk8 +sonar.projectVersion=0.5.0 +# GoLint report path, default value is report.xml +sonar.golint.reportPath=report.xml +# Cobertura like coverage report path, default value is coverage.xml +sonar.coverage.reportPath=coverage.xml +# if you want disabled the DTD verification for a proxy problem for example, true by default +sonar.coverage.dtdVerification=true +# JUnit like test report, default value is test.xml +sonar.test.reportPath=test.xml +sonar.sources=./ +sonar.tests=./ +sonar.test.inclusions=**/**_test.go +sonar.sources.inclusions=**/**.go \ No newline at end of file diff --git a/test/scripts/check-gofmt.sh b/test/scripts/check-gofmt.sh deleted file mode 100755 index e72a0bf..0000000 --- a/test/scripts/check-gofmt.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Why we are wrapping gofmt? -# - ignore files in vendor direcotry -# - gofmt doesn't exit with error code when there are errors - -# Inspired from https://github.com/redhat-developer/odo/blob/master/scripts/check-gofmt.sh - -GO_FILES=$(find . -path ./vendor -prune -o -name '*.go' -print) - -for file in $GO_FILES; do - gofmtOutput=$(gofmt -l "$file") - if [ "$gofmtOutput" ]; then - errors+=("$gofmtOutput") - fi -done - - -if [ ${#errors[@]} -eq 0 ]; then - echo "gofmt OK" -else - echo "gofmt ERROR - These files are not formated by gofmt:" - for err in "${errors[@]}"; do - echo "$err" - done - exit 1 -fi diff --git a/test/version_test.go b/test/version_test.go deleted file mode 100644 index e8cae1f..0000000 --- a/test/version_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package test - -import ( - "testing" - - "github.com/kubernauts/tk8/cmd" -) - -func TestVersion(t *testing.T) { - - if cmd.VERSION != "dev-build" { - t.Errorf("Version was not passed correctly") - } else { - t.Log("Version passed correctly") - } -}