diff --git a/cmd/build.go b/cmd/build.go index 58331a9f8922ea0ccd7451a0b01d25f5972d08f5..d8dd4acbb843ce3976340c795e55c747e58210fc 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -33,20 +33,26 @@ var buildCmd = &cobra.Command{ Use: "build", Short: "build the application", Run: func(cmd *cobra.Command, args []string) { - environment.EvalDockerEnv() + checkLocalSetup() - err := environment.Run(true, "minikube", "status") + err := environment.Run(false, "minikube", "status") if err != nil { color.Red("Minikube is not started... run `devtool start` first.") return } + environment.EvalDockerEnv() + + fixKubectlContext() + conf, err := config.New(configFile) if err != nil { color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile) return } + checkEnvVars(conf) + err = build(conf) if err != nil { color.Red("Failed to build application.") @@ -130,6 +136,21 @@ func build(config config.Config) error { return nil } +func checkEnvVars(conf config.Config) { + for _, env := range conf.LocalEnvVars { + checkEnvVar(env) + } + for _, env := range conf.LocalSecrets { + checkEnvVar(env) + } +} +func checkEnvVar(env string) { + value := os.Getenv(env) + if value == "" { + color.New(color.FgRed).Printf("WARNING - %s is NOT set in the local environment\n", env) + } +} + func buildDockerAndDeploy(config config.Config) error { color.Blue("Building Docker Containers") diff --git a/cmd/config_add.go b/cmd/config_add.go index df71c6024264d0fb8da396730bb33b0259f73c66..19e3a6ff9933cb657bf24f403898f9070c5716a3 100644 --- a/cmd/config_add.go +++ b/cmd/config_add.go @@ -15,7 +15,12 @@ package cmd import ( + "fmt" + "strings" + + "git.psu.edu/k8s/devtool/config" "github.com/fatih/color" + "github.com/manifoldco/promptui" "github.com/spf13/cobra" ) @@ -24,7 +29,62 @@ var addCmd = &cobra.Command{ Use: "add", Short: "adds a deployable unit to the project configuration", Run: func(cmd *cobra.Command, args []string) { - color.Red("Not implemented yet!") + + conf, err := config.New(configFile) + if err != nil { + color.Red("Configuration doesn't exist, please run 'devtool config init' instead.") + return + } + + deployables := conf.Deployables + dockerfiles := findDockerfiles() + for _, file := range dockerfiles { + fmt.Printf("Found Dockerfile: %s\n", file) + + found := false + for _, deployable := range deployables { + if deployable.Dockerfile == file { + found = true + break + } + } + + if !found { + color.New(color.FgYellow).Printf("Found Dockerfile: %s\n", file) + + prompt := promptui.Prompt{ + Label: "Include in config", + Default: "Yes", + } + response, err := prompt.Run() + if err != nil { + return + } + + switch strings.ToLower(response) { + case "": + case "y": + case "yes": + default: + continue + } + + deployable, err := promptForDeployable(file, conf) + if err != nil { + return + } + + conf.Deployables = append(conf.Deployables, deployable) + color.Green("Adding Deployment") + + color.Yellow("Writing configuration") + + err = conf.Write(configFile) + if err != nil { + color.New(color.FgRed).Printf("Error writing configuration file: %s\n", configFile) + } + } + } }, } diff --git a/cmd/config_init.go b/cmd/config_init.go index 2bc91c47451d010179ae8e177f6d616c44cb4687..79e140c4e7d20e03af2796e98537fb6cd6c0aa69 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -89,11 +89,12 @@ var initCmd = &cobra.Command{ dockerfiles := findDockerfiles() for _, file := range dockerfiles { color.New(color.FgYellow).Printf("Found Dockerfile: %s\n", file) + prompt := promptui.Prompt{ Label: "Include in config", Default: "Yes", } - response, err = prompt.Run() + response, err := prompt.Run() if err != nil { return } @@ -106,69 +107,10 @@ var initCmd = &cobra.Command{ continue } - var deployable config.Deployable - deployable.Dockerfile = file - - defaultName := strings.TrimSuffix(file, "Dockerfile") - defaultName = strings.TrimSuffix(defaultName, "/") - if defaultName == "" { - defaultName = conf.Name - } - prompt = promptui.Prompt{ - Label: "Name", - Default: defaultName, - } - response, err = prompt.Run() + deployable, err := promptForDeployable(file, conf) if err != nil { return } - deployable.Name = response - - // Ask for Chart - selectPrompt := promptui.SelectWithAdd{ - Label: "Chart", - Items: []string{"cm/eio-swe-service", "cm/eio-swe-cronjob", "cm/angular-client", "cm/eio-swe-jms-processor"}, - AddLabel: "Other", - } - _, response, err = selectPrompt.Run() - if err != nil { - return - } - deployable.Chart = response - - // Ask for Chart Version - availableChartVersions := findChartVersions(response) - - selectPrompt = promptui.SelectWithAdd{ - Label: "Chart Version", - Items: availableChartVersions, - AddLabel: "Other", - } - _, response, err = selectPrompt.Run() - if err != nil { - return - } - deployable.ChartVersion = response - - // Ask for Local Config - availableLocalConfigFiles := findLocalConfigs() - - selectPrompt = promptui.SelectWithAdd{ - Label: "Local Config File", - Items: availableLocalConfigFiles, - AddLabel: "Other", - } - _, response, err = selectPrompt.Run() - if err != nil { - return - } - deployable.LocalConfig = response - - // Create the file if it doesn't exist already - _, err = os.OpenFile(response, os.O_RDONLY|os.O_CREATE, 0666) - if err != nil { - color.Yellow("Unable to create config file") - } conf.Deployables = append(conf.Deployables, deployable) color.Green("Adding Deployment") @@ -211,7 +153,7 @@ func findDockerfiles() []string { if info.IsDir() { return nil } - if info.Name() == "Dockerfile" { + if strings.HasPrefix(info.Name(), "Dockerfile") { dockerfiles = append(dockerfiles, path) } return nil @@ -222,6 +164,76 @@ func findDockerfiles() []string { return dockerfiles } +func promptForDeployable(file string, conf config.Config) (config.Deployable, error) { + var deployable config.Deployable + deployable.Dockerfile = file + + defaultName := strings.TrimSuffix(file, "Dockerfile") + defaultName = strings.TrimSuffix(defaultName, "/") + defaultName = strings.Replace(defaultName, "Dockerfile", conf.Name, 1) + + if defaultName == "" { + defaultName = conf.Name + } + prompt := promptui.Prompt{ + Label: "Name", + Default: defaultName, + } + response, err := prompt.Run() + if err != nil { + return deployable, err + } + deployable.Name = response + + // Ask for Chart + selectPrompt := promptui.SelectWithAdd{ + Label: "Chart", + Items: []string{"cm/eio-swe-service", "cm/eio-swe-cronjob", "cm/angular-client", "cm/eio-swe-jms-processor"}, + AddLabel: "Other", + } + _, response, err = selectPrompt.Run() + if err != nil { + return deployable, err + } + deployable.Chart = response + + // Ask for Chart Version + availableChartVersions := findChartVersions(response) + + selectPrompt = promptui.SelectWithAdd{ + Label: "Chart Version", + Items: availableChartVersions, + AddLabel: "Other", + } + _, response, err = selectPrompt.Run() + if err != nil { + return deployable, err + } + deployable.ChartVersion = response + + // Ask for Local Config + availableLocalConfigFiles := findLocalConfigs() + + selectPrompt = promptui.SelectWithAdd{ + Label: "Local Config File", + Items: availableLocalConfigFiles, + AddLabel: "Other", + } + _, response, err = selectPrompt.Run() + if err != nil { + return deployable, err + } + deployable.LocalConfig = response + + // Create the file if it doesn't exist already + _, err = os.OpenFile(response, os.O_RDONLY|os.O_CREATE, 0666) + if err != nil { + color.Yellow("Unable to create config file") + } + + return deployable, nil +} + func findChartVersions(chartName string) []string { var versions []string output := environment.RunAndGetOutputRequired("helm", "search", chartName, "--versions") diff --git a/cmd/config_list.go b/cmd/config_list.go index a538d9da0f7a8f8ef576c33c8f5979b7493d32a8..e59e2fc763d91c504bccd8460db88c2423ec2f44 100644 --- a/cmd/config_list.go +++ b/cmd/config_list.go @@ -16,6 +16,7 @@ package cmd import ( "fmt" + "os" "git.psu.edu/k8s/devtool/config" "github.com/fatih/color" @@ -35,9 +36,35 @@ var listCmd = &cobra.Command{ fmt.Println("Project Configuration") fmt.Printf("Name: %s\n", conf.Name) fmt.Printf("Language: %s\n", conf.Language) + + fmt.Println("Deployables:") + for _, d := range conf.Deployables { + fmt.Printf("* %s\n", d.Name) + fmt.Printf(" Dockerfile: %s\n", d.Dockerfile) + fmt.Printf(" Chart: %s\n", d.Chart) + fmt.Printf(" ChartVersion: %s\n", d.ChartVersion) + fmt.Printf(" LocalConfig: %s\n", d.LocalConfig) + } + + fmt.Println("Local Environment Variables:") + for _, env := range conf.LocalEnvVars { + printLocalEnv(env) + } + for _, env := range conf.LocalSecrets { + printLocalEnv(env) + } }, } +func printLocalEnv(env string) { + value := os.Getenv(env) + if value == "" { + color.New(color.FgRed).Printf(" %s (NOT SET)\n", env) + } else { + fmt.Printf(" %s (%s)\n", env, value) + } +} + func init() { configCmd.AddCommand(listCmd) diff --git a/cmd/start.go b/cmd/start.go index 2cdcf0799003b0f9a850d0067c2b9334e447ff85..b0707541fc7f587c2ccefae9623cecde265eb0f4 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -130,7 +130,7 @@ func checkInstalled(app string) error { } func fixKubectlContext() { - color.Blue("setting kubectl context.") + color.Blue("Setting kubectl context.") _, err := exec.LookPath("kubectx") if err != nil { @@ -150,34 +150,40 @@ func fixKubectlContext() { func checkInstallTiller() { color.Blue("Checking if Tiller is installed.") - clientVersionOutput := environment.RunAndGetOutputRequired("helm", "version", "--client", "--short") - serverVersionOutput, err := environment.RunAndGetOutput("helm", "version", "--server", "--short") - + err := environment.Run(true, "kubectl", "get", "deployments", "tiller-deploy", "--namespace", "kube-system", "-o", "name") if err != nil { color.Yellow("Installing Tiller into the cluster...") environment.RunRequired(true, "helm", "init") + } - yellow := color.New(color.FgYellow) - yellow.Print("Waiting for Tiller to start.") + yellow := color.New(color.FgYellow) + yellow.Print("Waiting for Tiller to start.") - for i := 0; i < 30; i++ { + for i := 0; i < 30; i++ { + err = environment.Run(false, "helm", "version", "--server", "--short") + if err != nil { + yellow.Print(".") time.Sleep(2 * time.Second) - - serverVersionOutput, err = environment.RunAndGetOutput("helm", "version", "--server", "--short") + } else { + err := environment.Run(false, "helm", "ls", "--all", "--short") if err != nil { yellow.Print(".") + time.Sleep(2 * time.Second) } else { fmt.Println() break } } - if err != nil { - color.Red("Could not install Tiller into the cluster.") - } + } + if err != nil { + color.Red("Could not install Tiller into the cluster.") } + clientVersionOutput := environment.RunAndGetOutputRequired("helm", "version", "--client", "--short") + serverVersionOutput := environment.RunAndGetOutputRequired("helm", "version", "--server", "--short") + clientVersion := strings.TrimPrefix(clientVersionOutput[0], "Client: ") serverVersion := strings.TrimPrefix(serverVersionOutput[0], "Server: ") diff --git a/environment/environment.go b/environment/environment.go index abb6d2b4f44c38830c409f36036e5015a2500110..5ef83b274ef741953db6810228f2e062120dd3de 100644 --- a/environment/environment.go +++ b/environment/environment.go @@ -9,10 +9,6 @@ import ( "github.com/fatih/color" ) -// type Environment struct { -// defaultMinikubeCluster bool -// } - func EvalDockerEnv() { color.Blue("Setting up Docker environment.") @@ -46,8 +42,8 @@ func RunRequired(viewOutput bool, name string, args ...string) { err := Run(viewOutput, name, args...) if err != nil { - color.Red("Command Failed with '%s'\n", err) - panic("exiting.") + color.Red("Command '%s' with args '%s' Failed with '%s'\n", name, args, err) + os.Exit(-1) } } @@ -68,8 +64,8 @@ func RunAndGetOutput(name string, args ...string) ([]string, error) { func RunAndGetOutputRequired(name string, args ...string) []string { output, err := RunAndGetOutput(name, args...) if err != nil { - color.Red("Command Failed with '%s'\n", err) - panic("exiting.") + color.Red("Command '%s' with args '%s' Failed with '%s'\n", name, args, err) + os.Exit(-1) } return output }