diff --git a/.goreleaser.yml b/.goreleaser.yml index 8666d47..032ccee 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -3,6 +3,7 @@ before: hooks: - go get github.com/spf13/cobra - go get github.com/joho/godotenv + - go get github.com/sirupsen/logrus builds: - main: main.go binary: psu diff --git a/cmd/config.go b/cmd/config.go index 521a0b5..44ac982 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -2,12 +2,11 @@ package cmd import ( "fmt" - "log" "os" "github.com/greenled/portainer-stack-utils/common" - "github.com/greenled/portainer-stack-utils/util" "github.com/mitchellh/go-homedir" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -28,7 +27,9 @@ var configCmd = &cobra.Command{ } } if !keyExists { - log.Fatalf("Unkonwn configuration key \"%s\"", args[0]) + logrus.WithFields(logrus.Fields{ + "key": args[0], + }).Fatal("Unkonwn configuration key") } if len(args) == 1 { @@ -69,7 +70,9 @@ func loadCofig() (*viper.Viper, error) { // Read config from file if configReadingErr := newViper.ReadInConfig(); configReadingErr != nil { - util.PrintVerbose(fmt.Sprintf("Could not read configuration from \"%s\". Expect all configuration values to be unset.", configFile)) + logrus.WithFields(logrus.Fields{ + "file": configFile, + }).Warn("Could not read configuration from file. Expect all configuration values to be unset.") } return newViper, nil diff --git a/cmd/endpointList.go b/cmd/endpointList.go index 650bf90..0ae0f4f 100644 --- a/cmd/endpointList.go +++ b/cmd/endpointList.go @@ -21,9 +21,8 @@ import ( "os" "text/template" - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/common" + "github.com/sirupsen/logrus" "github.com/spf13/viper" "github.com/spf13/cobra" @@ -38,7 +37,7 @@ var endpointListCmd = &cobra.Command{ client, err := common.GetClient() common.CheckError(err) - util.PrintVerbose("Getting endpoints...") + logrus.Debug("Getting endpoints") endpoints, err := client.GetEndpoints() common.CheckError(err) diff --git a/cmd/login.go b/cmd/login.go index d42591f..d6a28ca 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -3,9 +3,8 @@ package cmd import ( "fmt" - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/common" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -19,7 +18,10 @@ var loginCmd = &cobra.Command{ client, err := common.GetDefaultClient() common.CheckError(err) - util.PrintVerbose("Getting auth token...") + user := viper.GetString("user") + logrus.WithFields(logrus.Fields{ + "user": user, + }).Debug("Getting auth token") authToken, err := client.Authenticate() common.CheckError(err) diff --git a/cmd/root.go b/cmd/root.go index 3bdd872..818ff0c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,8 +5,9 @@ import ( "os" "strings" + "github.com/sirupsen/logrus" + "github.com/greenled/portainer-stack-utils/common" - "github.com/greenled/portainer-stack-utils/util" "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -31,7 +32,7 @@ func Execute() { } func init() { - cobra.OnInitialize(initConfig) + cobra.OnInitialize(initConfig, initLogger) rootCmd.SetVersionTemplate("{{ version }}\n") cobra.AddTemplateFunc("version", common.BuildVersionString) @@ -40,8 +41,7 @@ func init() { // will be global for your application. rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.psu.yaml)") - rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose mode") - rootCmd.PersistentFlags().BoolP("debug", "d", false, "debug mode") + rootCmd.PersistentFlags().StringP("log-level", "v", "info", "log level") rootCmd.PersistentFlags().BoolP("insecure", "i", false, "skip Portainer SSL certificate verification") rootCmd.PersistentFlags().StringP("url", "l", "", "Portainer url") rootCmd.PersistentFlags().StringP("user", "u", "", "Portainer user") @@ -49,8 +49,7 @@ func init() { rootCmd.PersistentFlags().StringP("auth-token", "A", "", "Portainer auth token") rootCmd.PersistentFlags().DurationP("timeout", "t", 0, "waiting time before aborting (like 100ms, 30s, 1h20m)") viper.BindPFlag("config", rootCmd.PersistentFlags().Lookup("config")) - viper.BindPFlag("verbose", rootCmd.PersistentFlags().Lookup("verbose")) - viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug")) + viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level")) viper.BindPFlag("insecure", rootCmd.PersistentFlags().Lookup("insecure")) viper.BindPFlag("url", rootCmd.PersistentFlags().Lookup("url")) viper.BindPFlag("timeout", rootCmd.PersistentFlags().Lookup("timeout")) @@ -84,7 +83,17 @@ func initConfig() { viper.SetEnvKeyReplacer(replacer) // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - util.PrintVerbose("Using config file:", viper.ConfigFileUsed()) - } + viper.ReadInConfig() +} + +func initLogger() { + logLevelName := viper.GetString("log-level") + logLevel, err := logrus.ParseLevel(logLevelName) + if err != nil { + logrus.WithFields(logrus.Fields{ + "level": logLevelName, + }).Error("Unknown log level. Default \"info\" level will be used instead.") + logrus.SetLevel(logrus.InfoLevel) + } + logrus.SetLevel(logLevel) } diff --git a/cmd/stackDeploy.go b/cmd/stackDeploy.go index 4a62057..094fc56 100644 --- a/cmd/stackDeploy.go +++ b/cmd/stackDeploy.go @@ -1,13 +1,10 @@ package cmd import ( - "fmt" "io/ioutil" - "log" - - "github.com/greenled/portainer-stack-utils/util" "github.com/greenled/portainer-stack-utils/client" + "github.com/sirupsen/logrus" "github.com/greenled/portainer-stack-utils/common" "github.com/joho/godotenv" @@ -34,11 +31,16 @@ var stackDeployCmd = &cobra.Command{ common.CheckError(clientRetrievalErr) stackName := args[0] + logrus.WithFields(logrus.Fields{ + "stack": stackName, + }).Debug("Getting stack") retrievedStack, stackRetrievalErr := common.GetStackByName(stackName) switch stackRetrievalErr.(type) { case nil: // We are updating an existing stack - util.PrintVerbose(fmt.Sprintf("Stack %s found. Updating...", retrievedStack.Name)) + logrus.WithFields(logrus.Fields{ + "stack": retrievedStack.Name, + }).Debug("Stack found") var stackFileContent string if viper.GetString("stack.deploy.stack-file") != "" { @@ -47,7 +49,9 @@ var stackDeployCmd = &cobra.Command{ common.CheckError(loadingErr) } else { var stackFileContentRetrievalErr error - util.PrintVerbose("Getting stack file content...") + logrus.WithFields(logrus.Fields{ + "stack": retrievedStack.Name, + }).Debug("Getting stack file content") stackFileContent, stackFileContentRetrievalErr = portainerClient.GetStackFileContent(retrievedStack.Id) common.CheckError(stackFileContentRetrievalErr) } @@ -73,32 +77,44 @@ var stackDeployCmd = &cobra.Command{ } } - util.PrintVerbose("Updating stack...") + logrus.WithFields(logrus.Fields{ + "stack": retrievedStack.Name, + }).Info("Updating stack") err := portainerClient.UpdateStack(retrievedStack, newEnvironmentVariables, stackFileContent, viper.GetBool("stack.deploy.prune"), viper.GetString("stack.deploy.endpoint")) common.CheckError(err) case *common.StackNotFoundError: // We are deploying a new stack - util.PrintVerbose(fmt.Sprintf("Stack %s not found. Deploying...", stackName)) + logrus.WithFields(logrus.Fields{ + "stack": stackName, + }).Debug("Stack not found") if viper.GetString("stack.deploy.stack-file") == "" { - log.Fatalln("Specify a docker-compose file with --stack-file") + logrus.WithFields(logrus.Fields{ + "flag": "--stack-file", + }).Fatal("Provide required flag") } stackFileContent, loadingErr := loadStackFile(viper.GetString("stack.deploy.stack-file")) common.CheckError(loadingErr) swarmClusterId, selectionErr := getSwarmClusterId() + endpointId := viper.GetString("stack.deploy.endpoint") switch selectionErr.(type) { case nil: // It's a swarm cluster - util.PrintVerbose(fmt.Sprintf("Swarm cluster found with id %s", swarmClusterId)) - util.PrintVerbose("Deploying stack...") - deploymentErr := portainerClient.CreateSwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, swarmClusterId, viper.GetString("stack.deploy.endpoint")) + logrus.WithFields(logrus.Fields{ + "stack": stackName, + "endpoint": endpointId, + "cluster": swarmClusterId, + }).Info("Creating stack") + deploymentErr := portainerClient.CreateSwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, swarmClusterId, endpointId) common.CheckError(deploymentErr) case *valueNotFoundError: // It's not a swarm cluster - util.PrintVerbose("Swarm cluster not found") - util.PrintVerbose("Deploying stack...") - deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, viper.GetString("stack.deploy.endpoint")) + logrus.WithFields(logrus.Fields{ + "stack": stackName, + "endpoint": endpointId, + }).Info("Creating stack") + deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, endpointId) common.CheckError(deploymentErr) default: // Something else happened @@ -133,8 +149,11 @@ func getSwarmClusterId() (id string, err error) { return } - util.PrintVerbose("Getting endpoint Docker info...") - result, err := client.GetEndpointDockerInfo(viper.GetString("stack.deploy.endpoint")) + endpointId := viper.GetString("stack.deploy.endpoint") + logrus.WithFields(logrus.Fields{ + "endpoint": endpointId, + }).Debug("Getting endpoint's Docker info") + result, err := client.GetEndpointDockerInfo(endpointId) if err != nil { return } diff --git a/cmd/stackList.go b/cmd/stackList.go index f68c4ee..d2b9447 100644 --- a/cmd/stackList.go +++ b/cmd/stackList.go @@ -5,9 +5,8 @@ import ( "os" "text/template" - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/common" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -22,8 +21,13 @@ var stackListCmd = &cobra.Command{ client, err := common.GetClient() common.CheckError(err) - util.PrintVerbose("Getting stacks...") - stacks, err := client.GetStacks(viper.GetString("stack.list.swarm"), viper.GetUint32("stack.list.endpoint")) + swarmId := viper.GetString("stack.list.swarm") + endpointId := viper.GetUint32("stack.list.endpoint") + logrus.WithFields(logrus.Fields{ + "swarm": swarmId, + "endpoint": endpointId, + }).Debug("Getting stacks") + stacks, err := client.GetStacks(swarmId, endpointId) common.CheckError(err) if viper.GetBool("stack.list.quiet") { diff --git a/cmd/stackRemove.go b/cmd/stackRemove.go index 7a91e1e..6f445e2 100644 --- a/cmd/stackRemove.go +++ b/cmd/stackRemove.go @@ -1,12 +1,8 @@ package cmd import ( - "fmt" - "log" - - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/common" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -25,23 +21,25 @@ var stackRemoveCmd = &cobra.Command{ switch err.(type) { case nil: // The stack exists - util.PrintVerbose(fmt.Sprintf("Stack %s exists.", stackName)) - stackId := stack.Id - util.PrintVerbose(fmt.Sprintf("Removing stack %s...", stackName)) - client, err := common.GetClient() common.CheckError(err) - util.PrintVerbose("Deleting stack...") + logrus.WithFields(logrus.Fields{ + "stack": stackName, + }).Info("Removing stack") err = client.DeleteStack(stackId) common.CheckError(err) case *common.StackNotFoundError: // The stack does not exist - util.PrintVerbose(fmt.Sprintf("Stack %s does not exist.", stackName)) + logrus.WithFields(logrus.Fields{ + "stack": stackName, + }).Debug("Stack not found") if viper.GetBool("stack.remove.strict") { - log.Fatalln(fmt.Sprintf("Stack %s does not exist.", stackName)) + logrus.WithFields(logrus.Fields{ + "stack": stackName, + }).Fatal("Stack does not exist") } default: // Something else happened diff --git a/common/client.go b/common/client.go index 6040c5c..79873f6 100644 --- a/common/client.go +++ b/common/client.go @@ -3,13 +3,11 @@ package common import ( "bytes" "crypto/tls" - "fmt" "io/ioutil" "net/http" - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/client" + "github.com/sirupsen/logrus" "github.com/spf13/viper" ) @@ -46,13 +44,11 @@ func GetDefaultClient() (c client.PortainerClient, err error) { req.Body = ioutil.NopCloser(bytes.NewReader(bodyBytes)) } - util.PrintDebug(fmt.Sprintf(`Request ---- -Method: %s -URL: %s -Body: -%s ----`, req.Method, req.URL.String(), string(bodyString))) + logrus.WithFields(logrus.Fields{ + "method": req.Method, + "url": req.URL.String(), + "body": string(bodyString), + }).Trace("Request to Portainer") return }) @@ -69,12 +65,10 @@ Body: resp.Body = ioutil.NopCloser(bytes.NewReader(bodyBytes)) } - util.PrintDebug(fmt.Sprintf(`Response ---- -Status: %s -Body: -%s ----`, resp.Status, bodyString)) + logrus.WithFields(logrus.Fields{ + "status": resp.Status, + "body": string(bodyString), + }).Trace("Response from Portainer") return }) diff --git a/common/errors.go b/common/errors.go index 6cbc47d..da70076 100644 --- a/common/errors.go +++ b/common/errors.go @@ -1,13 +1,12 @@ package common import ( - "fmt" - "log" + "github.com/sirupsen/logrus" ) // CheckError checks if an error occurred (it's not nil) func CheckError(err error) { if err != nil { - log.Fatalln(fmt.Sprintf("Error: %s", err.Error())) + logrus.Fatal(err.Error()) } } diff --git a/common/utils.go b/common/utils.go index 1232cf9..856fd96 100644 --- a/common/utils.go +++ b/common/utils.go @@ -3,8 +3,6 @@ package common import ( "fmt" - "github.com/greenled/portainer-stack-utils/util" - "github.com/greenled/portainer-stack-utils/client" ) @@ -19,7 +17,6 @@ func GetStackByName(name string) (stack client.Stack, err error) { return } - util.PrintVerbose(fmt.Sprintf("Getting stack %s...", name)) for _, stack := range stacks { if stack.Name == name { return stack, nil diff --git a/util/errors.go b/util/errors.go index b2c9d96..d134c84 100644 --- a/util/errors.go +++ b/util/errors.go @@ -1,13 +1,12 @@ package util import ( - "fmt" - "log" + "github.com/sirupsen/logrus" ) // CheckError checks if an error occurred (it's not nil) func CheckError(err error) { if err != nil { - log.Fatalln(fmt.Sprintf("Error: %s", err.Error())) + logrus.Fatal(err.Error()) } } diff --git a/util/printing.go b/util/printing.go deleted file mode 100644 index 8a04187..0000000 --- a/util/printing.go +++ /dev/null @@ -1,19 +0,0 @@ -package util - -import ( - "log" - - "github.com/spf13/viper" -) - -func PrintVerbose(a ...interface{}) { - if viper.GetBool("verbose") { - log.Println(a) - } -} - -func PrintDebug(a ...interface{}) { - if viper.GetBool("debug") { - log.Println(a) - } -}