Commit 79619be3 authored by SWE CI's avatar SWE CI

Merge branch 'release/v0.1.4'

parents b40f81b5 7c1cc6b0
Pipeline #29450 passed with stage
in 23 seconds
...@@ -16,7 +16,9 @@ package cmd ...@@ -16,7 +16,9 @@ package cmd
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"strings"
"git.psu.edu/k8s/devtool/config" "git.psu.edu/k8s/devtool/config"
"git.psu.edu/k8s/devtool/environment" "git.psu.edu/k8s/devtool/environment"
...@@ -44,7 +46,7 @@ var buildCmd = &cobra.Command{ ...@@ -44,7 +46,7 @@ var buildCmd = &cobra.Command{
conf, err := config.New(configFile) conf, err := config.New(configFile)
if err != nil { if err != nil {
color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile) color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
return return
} }
...@@ -100,7 +102,7 @@ func build(config config.Config) error { ...@@ -100,7 +102,7 @@ func build(config config.Config) error {
case "go": case "go":
environment.RunRequired(true, "make", "build") environment.RunRequired(true, "make", "build")
default: default:
color.New(color.FgRed).PrintFunc()("devtool doesn't support the '%s' language yet.", lang) color.New(color.FgRed).Printf("devtool doesn't support the '%s' language yet.\n", lang)
return errors.New("Language not supported") return errors.New("Language not supported")
} }
return nil return nil
...@@ -120,8 +122,14 @@ func buildDockerAndDeploy(config config.Config) error { ...@@ -120,8 +122,14 @@ func buildDockerAndDeploy(config config.Config) error {
dockerTag := image + ":" + tag.String() dockerTag := image + ":" + tag.String()
color.New(color.FgGreen).PrintFunc()("Building ", dockerTag) dockerRootDir := "."
err = environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, ".") if idx := strings.LastIndex(dockerfile, "/"); idx != -1 {
dockerRootDir = dockerfile[:idx]
fmt.Println(dockerRootDir)
}
color.New(color.FgGreen).Printf("Building: %s\n", dockerTag)
err = environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, dockerRootDir)
if err != nil { if err != nil {
return err return err
} }
...@@ -146,12 +154,15 @@ func buildDockerAndDeploy(config config.Config) error { ...@@ -146,12 +154,15 @@ func buildDockerAndDeploy(config config.Config) error {
err = environment.Run(true, "helm", args...) err = environment.Run(true, "helm", args...)
if err != nil { if err != nil {
color.New(color.FgRed).PrintFunc()("helm error. try running 'helm del --purge %s'", releaseName) color.New(color.FgRed).Printf("helm error. try running 'helm del --purge %s'\n", releaseName)
return err return err
} }
if openServices { if openServices {
environment.Run(true, "minikube", "service", releaseName) err = environment.Run(true, "minikube", "service", releaseName)
if err != nil {
return err
}
} }
} }
return nil return nil
......
...@@ -41,7 +41,10 @@ func init() { ...@@ -41,7 +41,10 @@ func init() {
ciCmd.PersistentFlags().StringVarP(&imageTag, "image-tag", "i", "", "image tag for docker") ciCmd.PersistentFlags().StringVarP(&imageTag, "image-tag", "i", "", "image tag for docker")
ciCmd.PersistentFlags().StringVarP(&environmentSuffix, "environment", "e", "", "environment suffix to append to helm release name") ciCmd.PersistentFlags().StringVarP(&environmentSuffix, "environment", "e", "", "environment suffix to append to helm release name")
ciCmd.MarkPersistentFlagRequired("image-tag") err := ciCmd.MarkPersistentFlagRequired("image-tag")
if err != nil {
panic("invalid arg")
}
// Cobra supports local flags which will only run when this command // Cobra supports local flags which will only run when this command
// is called directly, e.g.: // is called directly, e.g.:
......
...@@ -31,7 +31,7 @@ var ciBuildCmd = &cobra.Command{ ...@@ -31,7 +31,7 @@ var ciBuildCmd = &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
conf, err := config.New(configFile) conf, err := config.New(configFile)
if err != nil { if err != nil {
color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile) color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
return err return err
} }
...@@ -59,8 +59,14 @@ func init() { ...@@ -59,8 +59,14 @@ func init() {
ciBuildCmd.Flags().StringVarP(&dockerRegistry, "registry", "r", "", "url of the docker registry") ciBuildCmd.Flags().StringVarP(&dockerRegistry, "registry", "r", "", "url of the docker registry")
ciBuildCmd.Flags().StringVarP(&dockerRegistryNamespace, "registry-namespace", "n", "", "namespace in the docker registry") ciBuildCmd.Flags().StringVarP(&dockerRegistryNamespace, "registry-namespace", "n", "", "namespace in the docker registry")
ciBuildCmd.MarkFlagRequired("registry") err := ciBuildCmd.MarkFlagRequired("registry")
ciBuildCmd.MarkFlagRequired("registry-namespace") if err != nil {
panic("invalid arg")
}
err = ciBuildCmd.MarkFlagRequired("registry-namespace")
if err != nil {
panic("invalid arg")
}
} }
func buildCiDocker(config config.Config) error { func buildCiDocker(config config.Config) error {
...@@ -73,13 +79,13 @@ func buildCiDocker(config config.Config) error { ...@@ -73,13 +79,13 @@ func buildCiDocker(config config.Config) error {
dockerImage := dockerRegistry + "/" + dockerRegistryNamespace + "/" + image dockerImage := dockerRegistry + "/" + dockerRegistryNamespace + "/" + image
dockerTag := dockerImage + ":" + imageTag dockerTag := dockerImage + ":" + imageTag
color.New(color.FgGreen).PrintFunc()("Building: ", dockerTag) color.New(color.FgGreen).Printf("Building: %s\n", dockerTag)
err := environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, ".") err := environment.Run(true, "docker", "build", "-t", dockerTag, "-f", dockerfile, ".")
if err != nil { if err != nil {
return err return err
} }
color.New(color.FgGreen).PrintFunc()("Pushing Docker image: ", dockerTag) color.New(color.FgGreen).Printf("Pushing Docker image: %s\n", dockerTag)
err = environment.Run(true, "docker", "push", dockerImage) err = environment.Run(true, "docker", "push", dockerImage)
if err != nil { if err != nil {
return err return err
......
...@@ -30,7 +30,7 @@ var ciDeployCmd = &cobra.Command{ ...@@ -30,7 +30,7 @@ var ciDeployCmd = &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
conf, err := config.New(configFile) conf, err := config.New(configFile)
if err != nil { if err != nil {
color.New(color.FgRed).PrintFunc()("Error reading configuration file: %s", configFile) color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
return err return err
} }
...@@ -69,14 +69,14 @@ func fluxDeployCi(config config.Config) error { ...@@ -69,14 +69,14 @@ func fluxDeployCi(config config.Config) error {
} else { } else {
releaseName = deployable.Name + "-" + environmentSuffix releaseName = deployable.Name + "-" + environmentSuffix
} }
color.Blue("Updating Flux Release:", releaseName) color.New(color.FgBlue).Printf("Updating Flux Release: %s\n", releaseName)
os.Setenv("KUBE_SERVICE_NAME", releaseName) os.Setenv("KUBE_SERVICE_NAME", releaseName)
os.Setenv("CI_PROJECT_NAME", image) os.Setenv("CI_PROJECT_NAME", image)
err := environment.Run(true, "fluxhelmrelease") err := environment.Run(true, "fluxhelmrelease")
if err != nil { if err != nil {
color.Red("fluxhelmrelease error.") color.Red("fluxhelmrelease error: %s", err)
return err return err
} }
} }
......
...@@ -16,11 +16,14 @@ package cmd ...@@ -16,11 +16,14 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"git.psu.edu/k8s/devtool/environment"
"git.psu.edu/k8s/devtool/config" "git.psu.edu/k8s/devtool/config"
"github.com/fatih/color" "github.com/fatih/color"
...@@ -85,7 +88,7 @@ var initCmd = &cobra.Command{ ...@@ -85,7 +88,7 @@ var initCmd = &cobra.Command{
dockerfiles := findDockerfiles() dockerfiles := findDockerfiles()
for _, file := range dockerfiles { for _, file := range dockerfiles {
color.Yellow("Found Dockerfile: %s", file) color.New(color.FgYellow).Printf("Found Dockerfile: %s\n", file)
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Include in config", Label: "Include in config",
Default: "Yes", Default: "Yes",
...@@ -121,6 +124,7 @@ var initCmd = &cobra.Command{ ...@@ -121,6 +124,7 @@ var initCmd = &cobra.Command{
} }
deployable.Name = response deployable.Name = response
// Ask for Chart
selectPrompt := promptui.SelectWithAdd{ selectPrompt := promptui.SelectWithAdd{
Label: "Chart", Label: "Chart",
Items: []string{"cm/eio-swe-service", "cm/eio-swe-cronjob", "cm/angular-client", "cm/eio-swe-jms-processor"}, Items: []string{"cm/eio-swe-service", "cm/eio-swe-cronjob", "cm/angular-client", "cm/eio-swe-jms-processor"},
...@@ -132,31 +136,53 @@ var initCmd = &cobra.Command{ ...@@ -132,31 +136,53 @@ var initCmd = &cobra.Command{
} }
deployable.Chart = response deployable.Chart = response
prompt = promptui.Prompt{ // Ask for Chart Version
Label: "Chart Version", availableChartVersions := findChartVersions(response)
selectPrompt = promptui.SelectWithAdd{
Label: "Chart Version",
Items: availableChartVersions,
AddLabel: "Other",
} }
response, err = prompt.Run() _, response, err = selectPrompt.Run()
if err != nil { if err != nil {
return return
} }
deployable.ChartVersion = response deployable.ChartVersion = response
prompt = promptui.Prompt{ // Ask for Local Config
Label: "Local Config File", availableLocalConfigFiles := findLocalConfigs()
selectPrompt = promptui.SelectWithAdd{
Label: "Local Config File",
Items: availableLocalConfigFiles,
AddLabel: "Other",
} }
response, err = prompt.Run() _, response, err = selectPrompt.Run()
if err != nil { if err != nil {
return return
} }
deployable.LocalConfig = response 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) conf.Deployables = append(conf.Deployables, deployable)
color.Green("Adding Deployment") color.Green("Adding Deployment")
} }
conf.LocalEnvVars = []string{"OAUTH_CLIENT_ID"}
conf.LocalEnvVars = []string{"OAUTH_CLIENT_SECRET", "OAUTH_JWK"}
color.Yellow("Writing configuration") color.Yellow("Writing configuration")
conf.Write(configFile) err = conf.Write(configFile)
if err != nil {
color.New(color.FgRed).Printf("Error writing configuration file: %s\n", configFile)
}
}, },
} }
...@@ -195,3 +221,32 @@ func findDockerfiles() []string { ...@@ -195,3 +221,32 @@ func findDockerfiles() []string {
} }
return dockerfiles return dockerfiles
} }
func findChartVersions(chartName string) []string {
var versions []string
output := environment.RunAndGetOutputRequired("helm", "search", chartName, "--versions")
for i, line := range output {
if i == 0 {
continue
}
fields := strings.Fields(line)
if len(fields) < 4 {
continue
}
versions = append(versions, fields[1])
}
return versions
}
func findLocalConfigs() []string {
files, err := ioutil.ReadDir("config/")
if err != nil {
log.Println(err)
}
var filenames []string
for _, f := range files {
filenames = append(filenames, "config/"+f.Name())
}
return filenames
}
...@@ -29,7 +29,7 @@ var listCmd = &cobra.Command{ ...@@ -29,7 +29,7 @@ var listCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
conf, err := config.New(configFile) conf, err := config.New(configFile)
if err != nil { if err != nil {
color.New(color.FgRed).PrintFunc()("Error reading configuration file: ", configFile, "\n") color.New(color.FgRed).Printf("Error reading configuration file: %s\n", configFile)
return return
} }
fmt.Println("Project Configuration") fmt.Println("Project Configuration")
......
// 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 (
"os"
"strings"
"git.psu.edu/k8s/devtool/environment"
"git.psu.edu/k8s/devtool/config"
"github.com/fatih/color"
"github.com/spf13/cobra"
)
var command string
// runCmd represents the run command
var runCmd = &cobra.Command{
Use: "run",
Short: "run the application",
Run: func(cmd *cobra.Command, args []string) {
color.Blue("Running your application")
conf, err := config.New(configFile)
if err != nil {
color.New(color.FgYellow).Printf("WARNING: no project configuration exists: %s\n", configFile)
}
localConfig := selectLocalConfig(conf.Deployables)
if localConfig != "" {
var helmValues config.HelmValues
helmValues, err = config.ReadHelmValues(localConfig)
if err != nil {
color.New(color.FgRed).Printf("Error reading local config file: %s\n", localConfig)
}
for k, v := range helmValues.EnvironmentVariables {
os.Setenv(k, v)
}
}
commandSplit := strings.Fields(command)
environment.RunRequired(true, commandSplit[0], commandSplit[1:]...)
},
}
func init() {
rootCmd.AddCommand(runCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// runCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
runCmd.Flags().StringVarP(&command, "command", "c", "", "The command to run")
err := runCmd.MarkFlagRequired("command")
if err != nil {
panic("invalid arg")
}
}
func selectLocalConfig(deployables []config.Deployable) string {
if len(deployables) == 0 {
return ""
}
//if len(deployables) == 1 {
return deployables[0].LocalConfig
//}
//TODO add support for multiple deployables (prompt user and add arg)
}
...@@ -16,7 +16,6 @@ package cmd ...@@ -16,7 +16,6 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"strings" "strings"
"time" "time"
...@@ -78,15 +77,9 @@ func start(memory, cpu string) { ...@@ -78,15 +77,9 @@ func start(memory, cpu string) {
environment.RunRequired(true, "minikube", "start", "--memory", memory, "--cpus", cpu) environment.RunRequired(true, "minikube", "start", "--memory", memory, "--cpus", cpu)
} }
checkInstallTiller() fixKubectlContext()
environment.EvalDockerEnv()
color.Blue("Environment Variables:") checkInstallTiller()
for _, e := range os.Environ() {
fmt.Println(e)
}
} }
...@@ -113,13 +106,31 @@ func checkLocalSetup() bool { ...@@ -113,13 +106,31 @@ func checkLocalSetup() bool {
func checkInstalled(app string) error { func checkInstalled(app string) error {
path, err := exec.LookPath(app) path, err := exec.LookPath(app)
if err != nil { if err != nil {
color.New(color.FgYellow).PrintfFunc()("%s is not installed\n", app) color.New(color.FgYellow).Printf("%s is not installed\n", app)
} else { } else {
fmt.Printf("%s: %s\n", app, path) fmt.Printf("%s: %s\n", app, path)
} }
return err return err
} }
func fixKubectlContext() {
color.Blue("setting kubectl context.")
_, err := exec.LookPath("kubectx")
if err != nil {
color.New(color.FgYellow).Printf("kubectx is not installed")
} else {
environment.RunRequired(true, "kubectx", "minikube")
}
_, err = exec.LookPath("kubens")
if err != nil {
color.New(color.FgYellow).Printf("kubens is not installed")
} else {
environment.RunRequired(true, "kubens", "default")
}
}
func checkInstallTiller() { func checkInstallTiller() {
color.Blue("Checking if Tiller is installed.") color.Blue("Checking if Tiller is installed.")
...@@ -133,15 +144,18 @@ func checkInstallTiller() { ...@@ -133,15 +144,18 @@ func checkInstallTiller() {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
serverVersionOutput, err = environment.RunAndGetOutput("helm", "version", "--server", "--short") serverVersionOutput, err = environment.RunAndGetOutput("helm", "version", "--server", "--short")
if err != nil {
color.Red("Cannot determin helm server version")
}
} }
clientVersion := strings.TrimPrefix(clientVersionOutput[0], "Client: ") clientVersion := strings.TrimPrefix(clientVersionOutput[0], "Client: ")
serverVersion := strings.TrimPrefix(serverVersionOutput[0], "Server: ") serverVersion := strings.TrimPrefix(serverVersionOutput[0], "Server: ")
if clientVersion != serverVersion { if clientVersion != serverVersion {
warn := color.New(color.FgYellow).PrintFunc() warn := color.New(color.FgYellow).PrintfFunc()
warn("Helm version mismatch between client and server") warn("Helm version mismatch between client and server\n")
warn("Client Version: %s\n", clientVersion) warn(" Client Version: %s\n", clientVersion)
warn("Server Version: %s\n", serverVersion) warn(" Server Version: %s\n", serverVersion)
} }
} }
...@@ -3,6 +3,8 @@ package config ...@@ -3,6 +3,8 @@ package config
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"gopkg.in/yaml.v2"
) )
type ( type (
...@@ -20,6 +22,9 @@ type ( ...@@ -20,6 +22,9 @@ type (
ChartVersion string `json:"chartVersion"` ChartVersion string `json:"chartVersion"`
LocalConfig string `json:"localConfig"` LocalConfig string `json:"localConfig"`
} }
HelmValues struct {
EnvironmentVariables map[string]string `yaml:"environmentVariables"`
}
) )
func (config Config) Write(filename string) error { func (config Config) Write(filename string) error {
...@@ -40,3 +45,14 @@ func New(filename string) (Config, error) { ...@@ -40,3 +45,14 @@ func New(filename string) (Config, error) {
err = json.Unmarshal(data, &config) err = json.Unmarshal(data, &config)
return config, err return config, err
} }
func ReadHelmValues(filename string) (HelmValues, error) {
data, err := ioutil.ReadFile(filename)
var helmValues HelmValues
if err != nil {
return helmValues, err
}
err = yaml.Unmarshal([]byte(data), &helmValues)
return helmValues, err
}