diff --git a/src/cmd/common/setup.go b/src/cmd/common/setup.go index 6fab6e134b..602c6228a5 100644 --- a/src/cmd/common/setup.go +++ b/src/cmd/common/setup.go @@ -5,43 +5,38 @@ package common import ( + "errors" "fmt" "io" "os" "time" - "github.com/defenseunicorns/zarf/src/config" - "github.com/defenseunicorns/zarf/src/config/lang" - "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/pterm/pterm" -) -// LogLevelCLI holds the log level as input from a command -var LogLevelCLI string + "github.com/defenseunicorns/zarf/src/pkg/message" +) // SetupCLI sets up the CLI logging, interrupt functions, and more -func SetupCLI() { - match := map[string]message.LogLevel{ - "warn": message.WarnLevel, - "info": message.InfoLevel, - "debug": message.DebugLevel, - "trace": message.TraceLevel, - } - - if config.NoColor { +func SetupCLI(logLevel string, skipLogFile, noColor bool) error { + if noColor { message.DisableColor() } printViperConfigUsed() - // No log level set, so use the default - if LogLevelCLI != "" { - if lvl, ok := match[LogLevelCLI]; ok { - message.SetLogLevel(lvl) - message.Debug("Log level set to " + LogLevelCLI) - } else { - message.Warn(lang.RootCmdErrInvalidLogLevel) + if logLevel != "" { + match := map[string]message.LogLevel{ + "warn": message.WarnLevel, + "info": message.InfoLevel, + "debug": message.DebugLevel, + "trace": message.TraceLevel, + } + lvl, ok := match[logLevel] + if !ok { + return errors.New("invalid log level, valid options are warn, info, debug, and trace") } + message.SetLogLevel(lvl) + message.Debug("Log level set to " + logLevel) } // Disable progress bars for CI envs @@ -50,21 +45,18 @@ func SetupCLI() { message.NoProgress = true } - if !config.SkipLogFile { + if !skipLogFile { ts := time.Now().Format("2006-01-02-15-04-05") - f, err := os.CreateTemp("", fmt.Sprintf("zarf-%s-*.log", ts)) if err != nil { - message.WarnErr(err, "Error creating a log file in a temporary directory") - return + return fmt.Errorf("could not create a log file in a the temporary directory: %w", err) } logFile, err := message.UseLogFile(f) if err != nil { - message.WarnErr(err, "Error saving a log file to a temporary directory") - return + return fmt.Errorf("could not save a log file to the temporary directory: %w", err) } - pterm.SetDefaultOutput(io.MultiWriter(os.Stderr, logFile)) message.Notef("Saving log file to %s", f.Name()) } + return nil } diff --git a/src/cmd/root.go b/src/cmd/root.go index ee40254fe0..b8d68028ed 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -26,20 +26,40 @@ import ( var ( // Default global config for the packager pkgConfig = types.PackagerConfig{} + // LogLevelCLI holds the log level as input from a command + LogLevelCLI string + // SkipLogFile is a flag to skip logging to a file + SkipLogFile bool + // NoColor is a flag to disable colors in output + NoColor bool ) var rootCmd = &cobra.Command{ Use: "zarf COMMAND", - PersistentPreRun: func(cmd *cobra.Command, _ []string) { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // Skip for vendor-only commands if common.CheckVendorOnlyFromPath(cmd) { - return + return nil } - // Don't log the help command + + skipLogFile := SkipLogFile + + // Dont write tool commands to file. + comps := strings.Split(cmd.CommandPath(), " ") + if len(comps) > 1 && comps[1] == "tools" { + skipLogFile = true + } + + // Dont write help command to file. if cmd.Parent() == nil { - config.SkipLogFile = true + skipLogFile = true + } + + err := common.SetupCLI(LogLevelCLI, skipLogFile, NoColor) + if err != nil { + return err } - common.SetupCLI() + return nil }, Short: lang.RootCmdShort, Long: lang.RootCmdLong, @@ -89,11 +109,11 @@ func init() { v := common.InitViper() - rootCmd.PersistentFlags().StringVarP(&common.LogLevelCLI, "log-level", "l", v.GetString(common.VLogLevel), lang.RootCmdFlagLogLevel) + rootCmd.PersistentFlags().StringVarP(&LogLevelCLI, "log-level", "l", v.GetString(common.VLogLevel), lang.RootCmdFlagLogLevel) rootCmd.PersistentFlags().StringVarP(&config.CLIArch, "architecture", "a", v.GetString(common.VArchitecture), lang.RootCmdFlagArch) - rootCmd.PersistentFlags().BoolVar(&config.SkipLogFile, "no-log-file", v.GetBool(common.VNoLogFile), lang.RootCmdFlagSkipLogFile) + rootCmd.PersistentFlags().BoolVar(&SkipLogFile, "no-log-file", v.GetBool(common.VNoLogFile), lang.RootCmdFlagSkipLogFile) rootCmd.PersistentFlags().BoolVar(&message.NoProgress, "no-progress", v.GetBool(common.VNoProgress), lang.RootCmdFlagNoProgress) - rootCmd.PersistentFlags().BoolVar(&config.NoColor, "no-color", v.GetBool(common.VNoColor), lang.RootCmdFlagNoColor) + rootCmd.PersistentFlags().BoolVar(&NoColor, "no-color", v.GetBool(common.VNoColor), lang.RootCmdFlagNoColor) rootCmd.PersistentFlags().StringVar(&config.CommonOptions.CachePath, "zarf-cache", v.GetString(common.VZarfCache), lang.RootCmdFlagCachePath) rootCmd.PersistentFlags().StringVar(&config.CommonOptions.TempDirectory, "tmpdir", v.GetString(common.VTmpDir), lang.RootCmdFlagTempDir) rootCmd.PersistentFlags().BoolVar(&config.CommonOptions.Insecure, "insecure", v.GetBool(common.VInsecure), lang.RootCmdFlagInsecure) diff --git a/src/cmd/tools/common.go b/src/cmd/tools/common.go index 0844df9801..015d766d69 100644 --- a/src/cmd/tools/common.go +++ b/src/cmd/tools/common.go @@ -7,26 +7,15 @@ package tools import ( "fmt" - "github.com/defenseunicorns/zarf/src/cmd/common" - "github.com/defenseunicorns/zarf/src/config" - "github.com/defenseunicorns/zarf/src/config/lang" "github.com/spf13/cobra" + + "github.com/defenseunicorns/zarf/src/config/lang" ) var toolsCmd = &cobra.Command{ Use: "tools", Aliases: []string{"t"}, - PersistentPreRun: func(cmd *cobra.Command, _ []string) { - config.SkipLogFile = true - - // Skip for vendor-only commands - if common.CheckVendorOnlyFromPath(cmd) { - return - } - - common.SetupCLI() - }, - Short: lang.CmdToolsShort, + Short: lang.CmdToolsShort, } // Include adds the tools command to the root command. diff --git a/src/cmd/version.go b/src/cmd/version.go index 589cab9929..4c5ae94bdc 100644 --- a/src/cmd/version.go +++ b/src/cmd/version.go @@ -24,11 +24,8 @@ var outputFormat string var versionCmd = &cobra.Command{ Use: "version", Aliases: []string{"v"}, - PersistentPreRun: func(_ *cobra.Command, _ []string) { - config.SkipLogFile = true - }, - Short: lang.CmdVersionShort, - Long: lang.CmdVersionLong, + Short: lang.CmdVersionShort, + Long: lang.CmdVersionLong, RunE: func(_ *cobra.Command, _ []string) error { if outputFormat == "" { fmt.Println(config.CLIVersion) diff --git a/src/config/config.go b/src/config/config.go index f9dfc580ab..0c650419cc 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -60,12 +60,6 @@ var ( // ZarfSeedPort is the NodePort Zarf uses for the 'seed registry' ZarfSeedPort string - // SkipLogFile is a flag to skip logging to a file - SkipLogFile bool - - // NoColor is a flag to disable colors in output - NoColor bool - CosignPublicKey string // Timestamp of when the CLI was started diff --git a/src/config/lang/english.go b/src/config/lang/english.go index df39428f48..9b90c23b22 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -58,8 +58,6 @@ const ( RootCmdDeprecatedDeploy = "Deprecated: Please use \"zarf package deploy %s\" to deploy this package. This warning will be removed in Zarf v1.0.0." RootCmdDeprecatedCreate = "Deprecated: Please use \"zarf package create\" to create this package. This warning will be removed in Zarf v1.0.0." - RootCmdErrInvalidLogLevel = "Invalid log level. Valid options are: warn, info, debug, trace." - // zarf connect CmdConnectShort = "Accesses services or pods deployed in the cluster" CmdConnectLong = "Uses a k8s port-forward to connect to resources within the cluster referenced by your kube-context.\n" + diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go index 0ead8b0e01..e271cbf9d4 100644 --- a/src/pkg/message/message.go +++ b/src/pkg/message/message.go @@ -12,7 +12,6 @@ import ( "time" "github.com/defenseunicorns/pkg/helpers/v2" - "github.com/defenseunicorns/zarf/src/config" "github.com/fatih/color" "github.com/pterm/pterm" ) @@ -99,6 +98,11 @@ func DisableColor() { pterm.DisableColor() } +// ColorEnabled returns true if color printing is enabled. +func ColorEnabled() bool { + return pterm.PrintColor +} + // ZarfCommand prints a zarf terminal command. func ZarfCommand(format string, a ...any) { Command("zarf "+format, a...) @@ -276,7 +280,7 @@ func Table(header []string, data [][]string) { // preventing future characters from taking on the given color // returns string as normal if color is disabled func ColorWrap(str string, attr color.Attribute) string { - if config.NoColor || str == "" { + if !ColorEnabled() || str == "" { return str } return fmt.Sprintf("\x1b[%dm%s\x1b[0m", attr, str) diff --git a/src/pkg/utils/yaml.go b/src/pkg/utils/yaml.go index bc49d46502..1d33c4dc4e 100644 --- a/src/pkg/utils/yaml.go +++ b/src/pkg/utils/yaml.go @@ -15,7 +15,6 @@ import ( "regexp" "strings" - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/fatih/color" goyaml "github.com/goccy/go-yaml" @@ -93,7 +92,7 @@ func ColorPrintYAML(data any, hints map[string]string, spaceRootLists bool) { outputYAML = strings.Replace(outputYAML, key, value, 1) } - if config.NoColor { + if !message.ColorEnabled() { // If no color is specified strip any color codes from the output - https://regex101.com/r/YFyIwC/2 ansiRegex := regexp.MustCompile(`\x1b\[(.*?)m`) outputYAML = ansiRegex.ReplaceAllString(outputYAML, "")