diff --git a/cmd/completion.go b/cmd/completion.go index c29d4cb..729f3d4 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -19,7 +19,6 @@ package cmd import ( "os" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cmd/credential_process.go b/cmd/credential_process.go index feea6b3..339c4f7 100644 --- a/cmd/credential_process.go +++ b/cmd/credential_process.go @@ -25,7 +25,6 @@ import ( "gopkg.in/ini.v1" "github.com/netflix/weep/creds" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cmd/docs.go b/cmd/docs.go index 8954b65..9ada021 100644 --- a/cmd/docs.go +++ b/cmd/docs.go @@ -17,7 +17,6 @@ package cmd import ( - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) diff --git a/cmd/ecs_credential_provider.go b/cmd/ecs_credential_provider.go index c71f65b..6715bb0 100644 --- a/cmd/ecs_credential_provider.go +++ b/cmd/ecs_credential_provider.go @@ -25,7 +25,6 @@ import ( "github.com/gorilla/mux" "github.com/netflix/weep/handlers" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cmd/file.go b/cmd/file.go index 54f8c04..7e38141 100644 --- a/cmd/file.go +++ b/cmd/file.go @@ -27,7 +27,6 @@ import ( "github.com/mitchellh/go-homedir" "github.com/netflix/weep/creds" "github.com/netflix/weep/util" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cmd/metadata.go b/cmd/metadata.go index 2d8aec8..a85bafd 100644 --- a/cmd/metadata.go +++ b/cmd/metadata.go @@ -28,7 +28,6 @@ import ( "github.com/gorilla/mux" "github.com/netflix/weep/creds" "github.com/netflix/weep/handlers" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cmd/root.go b/cmd/root.go index ef0ec19..d854605 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,17 +17,13 @@ package cmd import ( - "io" "os" "os/signal" - "path/filepath" "syscall" "github.com/netflix/weep/config" + "github.com/netflix/weep/logging" - "github.com/kardianos/service" - - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -39,11 +35,12 @@ var ( Long: "Weep is a CLI tool that manages AWS access via ConsoleMe for local development.", DisableAutoGenTag: true, } + log = logging.GetLogger() ) func init() { cobra.OnInitialize(initConfig) - cobra.OnInitialize(initLogging) + cobra.OnInitialize(updateLoggingConfig) rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.weep.yaml)") rootCmd.PersistentFlags().StringSliceVarP(&assumeRole, "assume-role", "A", make([]string, 0), "one or more roles to assume after retrieving credentials") @@ -52,6 +49,11 @@ func init() { rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "", "log level (debug, info, warn)") } +func Run(initFunctions ...func()) { + cobra.OnInitialize(initFunctions...) + Execute() +} + func Execute() { shutdown = make(chan os.Signal, 1) done = make(chan int, 1) @@ -68,46 +70,10 @@ func initConfig() { } } -func initLogging() { - // Set the log level and default to INFO - switch logLevel { - case "error": - log.SetLevel(log.ErrorLevel) - case "warn": - log.SetLevel(log.WarnLevel) - case "debug": - log.SetLevel(log.DebugLevel) - default: - log.SetLevel(log.InfoLevel) - } - - // Set the log format. Default to Text - if logFormat == "json" { - log.SetFormatter(&log.JSONFormatter{}) - } else { - log.SetFormatter(&log.TextFormatter{}) - } - - logDir := filepath.Dir(logFile) - if _, err := os.Stat(logDir); os.IsNotExist(err) { - log.Debugf("attempting to create log directory %s", logDir) - err := os.MkdirAll(logDir, os.ModePerm) - if err != nil { - log.Errorf("could not create log directory") - } - } - - var w io.Writer - file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) +// updateLoggingConfig overrides the default logging settings based on the config and CLI args +func updateLoggingConfig() { + err := logging.UpdateConfig(logLevel, logFormat, logFile) if err != nil { - log.Errorf("could not open %s for logging, defaulting to stderr: %v", logFile, err) - log.SetOutput(os.Stderr) - w = os.Stderr - } else if service.Interactive() { - w = io.MultiWriter(os.Stderr, file) - } else { - w = file + log.Errorf("failed to configure logger: %v", err) } - log.SetOutput(w) - log.Debug("logging configured") } diff --git a/cmd/service.go b/cmd/service.go index b27a9dd..dbb5d6c 100644 --- a/cmd/service.go +++ b/cmd/service.go @@ -6,7 +6,6 @@ import ( "github.com/spf13/viper" "github.com/kardianos/service" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/config/config.go b/config/config.go index 1c42068..36de930 100644 --- a/config/config.go +++ b/config/config.go @@ -21,13 +21,16 @@ import ( "path/filepath" "runtime" + "github.com/netflix/weep/logging" + "github.com/mitchellh/go-homedir" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "github.com/spf13/viper" ) +var log = logging.GetLogger() + func init() { // Set default configuration values here viper.SetTypeByDefaultValue(true) diff --git a/creds/aws.go b/creds/aws.go index c0f41d9..c616922 100644 --- a/creds/aws.go +++ b/creds/aws.go @@ -24,7 +24,6 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sts" - log "github.com/sirupsen/logrus" ) // getAwsCredentials uses the provided Client to request credentials from ConsoleMe. diff --git a/creds/consoleme.go b/creds/consoleme.go index cf37c14..2c105ef 100644 --- a/creds/consoleme.go +++ b/creds/consoleme.go @@ -29,18 +29,20 @@ import ( "syscall" "time" + "github.com/netflix/weep/logging" + werrors "github.com/netflix/weep/errors" "github.com/spf13/viper" "github.com/netflix/weep/challenge" "github.com/netflix/weep/mtls" - log "github.com/sirupsen/logrus" "github.com/pkg/errors" "github.com/netflix/weep/version" ) +var log = logging.GetLogger() var clientVersion = fmt.Sprintf("%s", version.Version) var userAgent = "weep/" + clientVersion + " Go-http-client/1.1" diff --git a/creds/refreshable.go b/creds/refreshable.go index 281db11..d27eb0c 100644 --- a/creds/refreshable.go +++ b/creds/refreshable.go @@ -22,7 +22,6 @@ import ( "github.com/netflix/weep/errors" "github.com/aws/aws-sdk-go/aws/credentials" - log "github.com/sirupsen/logrus" ) // NewRefreshableProvider creates an AWS credential provider that will automatically refresh credentials diff --git a/handlers/baseHandler.go b/handlers/baseHandler.go index 555bdcd..49d137c 100644 --- a/handlers/baseHandler.go +++ b/handlers/baseHandler.go @@ -19,8 +19,12 @@ package handlers import ( "fmt" "net/http" + + "github.com/netflix/weep/logging" ) +var log = logging.GetLogger() + func BaseHandler(w http.ResponseWriter, r *http.Request) { baseMetadata := `ami-id diff --git a/handlers/credentialsHandler.go b/handlers/credentialsHandler.go index d536389..08399f4 100644 --- a/handlers/credentialsHandler.go +++ b/handlers/credentialsHandler.go @@ -23,7 +23,6 @@ import ( "net/http" "github.com/netflix/weep/cache" - log "github.com/sirupsen/logrus" "github.com/netflix/weep/metadata" ) diff --git a/handlers/ecsCredentialsHandler.go b/handlers/ecsCredentialsHandler.go index ebc38f3..d2d94cc 100644 --- a/handlers/ecsCredentialsHandler.go +++ b/handlers/ecsCredentialsHandler.go @@ -29,7 +29,6 @@ import ( "github.com/gorilla/mux" "github.com/netflix/weep/creds" "github.com/netflix/weep/metadata" - log "github.com/sirupsen/logrus" ) // parseAssumeRoleQuery extracts the assume query string argument, splits it on commas, validates that each element diff --git a/handlers/healthcheckHandler.go b/handlers/healthcheckHandler.go index 65b77ef..fbbafa4 100644 --- a/handlers/healthcheckHandler.go +++ b/handlers/healthcheckHandler.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/netflix/weep/health" - log "github.com/sirupsen/logrus" ) type healthcheckResponse struct { diff --git a/handlers/iamInfoHandler.go b/handlers/iamInfoHandler.go index 00dffc8..9bab763 100644 --- a/handlers/iamInfoHandler.go +++ b/handlers/iamInfoHandler.go @@ -22,8 +22,6 @@ import ( "fmt" "net/http" - log "github.com/sirupsen/logrus" - "github.com/netflix/weep/metadata" "github.com/netflix/weep/util" ) diff --git a/handlers/instanceIdentityDocument.go b/handlers/instanceIdentityDocument.go index 7f2484f..33ae9ae 100644 --- a/handlers/instanceIdentityDocument.go +++ b/handlers/instanceIdentityDocument.go @@ -24,8 +24,6 @@ import ( "github.com/netflix/weep/creds" - log "github.com/sirupsen/logrus" - "github.com/netflix/weep/metadata" "github.com/netflix/weep/util" ) diff --git a/handlers/middleware.go b/handlers/middleware.go index e07f8d7..25b14ea 100644 --- a/handlers/middleware.go +++ b/handlers/middleware.go @@ -22,10 +22,11 @@ import ( "strconv" "strings" + "github.com/sirupsen/logrus" + "github.com/netflix/weep/util" "github.com/netflix/weep/metadata" - log "github.com/sirupsen/logrus" ) // CredentialServiceMiddleware is a convenience wrapper that chains BrowserFilterMiddleware and AWSHeaderMiddleware @@ -53,7 +54,7 @@ func AWSHeaderMiddleware(next http.HandlerFunc) http.HandlerFunc { metadataVersion = 2 } - log.WithFields(log.Fields{ + log.WithFields(logrus.Fields{ "user-agent": ua, "path": r.URL.Path, "metadata_version": metadataVersion, diff --git a/logging/logger.go b/logging/logger.go new file mode 100644 index 0000000..1dd012a --- /dev/null +++ b/logging/logger.go @@ -0,0 +1,79 @@ +package logging + +import ( + "io" + "os" + "path/filepath" + + "github.com/kardianos/service" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var log *logrus.Logger + +func init() { + log = &logrus.Logger{ + Out: os.Stderr, + Formatter: new(logrus.TextFormatter), + Level: logrus.InfoLevel, + } +} + +// GetLogger returns the configured logger for use by the rest of the application. +func GetLogger() *logrus.Logger { + return log +} + +// UpdateConfig overrides the default logging settings. This function is meant to be +// used during CLI initialization to update the logger based on config file and CLI args. +func UpdateConfig(logLevel string, logFormat string, logFile string) error { + // Set the log level and default to INFO + switch logLevel { + case "error": + log.SetLevel(logrus.ErrorLevel) + case "warn": + log.SetLevel(logrus.WarnLevel) + case "debug": + log.SetLevel(logrus.DebugLevel) + default: + log.SetLevel(logrus.InfoLevel) + } + + // Set the log format. Default to Text + if logFormat == "json" { + log.SetFormatter(&logrus.JSONFormatter{}) + } else { + log.SetFormatter(&logrus.TextFormatter{}) + } + + var w io.Writer + if logFile != "" { + logDir := filepath.Dir(logFile) + if _, err := os.Stat(logDir); os.IsNotExist(err) { + // Log directory doesn't exist. Try to make it exist. + log.Debugf("attempting to create log directory %s", logDir) + err := os.MkdirAll(logDir, os.ModePerm) + if err != nil { + return errors.Wrap(err, "could not create log directory") + } + } + // Since we hopefully have the directory, try to open the file + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + // No go. Bail out to stderr. + log.SetOutput(os.Stderr) + return errors.Wrapf(err, "could not open %s for logging, defaulting to stderr", logFile) + } else if service.Interactive() { + // No error opening the file, and we know that this is an interactive session. + // Write to stderr and the file. + w = io.MultiWriter(os.Stderr, file) + } else { + // No error on file, not interactive, so just write to the file. + w = file + } + } + log.SetOutput(w) + log.Debug("logging configured") + return nil +} diff --git a/mtls/mtls.go b/mtls/mtls.go index a1f13b7..ebf7292 100644 --- a/mtls/mtls.go +++ b/mtls/mtls.go @@ -23,6 +23,8 @@ import ( "io/ioutil" "net/http" + "github.com/netflix/weep/logging" + "github.com/spf13/viper" "path/filepath" @@ -32,9 +34,10 @@ import ( "github.com/mitchellh/go-homedir" "github.com/netflix/weep/config" "github.com/netflix/weep/util" - log "github.com/sirupsen/logrus" ) +var log = logging.GetLogger() + // getTLSConfig makes and returns a pointer to a tls.Config func getTLSConfig() (*tls.Config, error) { dirs, err := getTLSDirs() diff --git a/util/util.go b/util/util.go index d7c1983..b13ab4a 100644 --- a/util/util.go +++ b/util/util.go @@ -23,9 +23,11 @@ import ( "os" "strings" - log "github.com/sirupsen/logrus" + "github.com/netflix/weep/logging" ) +var log = logging.GetLogger() + type AwsArn struct { Arn string Partition string