From a3feacf5f8fdd785aee2e29eac7b6630586c73b6 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Wed, 26 Nov 2025 13:48:58 -0800 Subject: [PATCH 1/2] move output dir creation decision to commands Signed-off-by: Harper, Jason M --- cmd/metrics/metrics.go | 16 ++++++++++ cmd/root.go | 61 --------------------------------------- internal/common/common.go | 11 ++++++- 3 files changed, 26 insertions(+), 62 deletions(-) diff --git a/cmd/metrics/metrics.go b/cmd/metrics/metrics.go index f1ef1c6e..06afdb47 100644 --- a/cmd/metrics/metrics.go +++ b/cmd/metrics/metrics.go @@ -833,6 +833,11 @@ func processRawData(localOutputDir string) error { printOutputFileNames([][]string{filesWritten}) return nil } + +func needsOutputDir(cmd *cobra.Command) bool { + return !flagLive && !flagPrometheusServer && !cmd.Flags().Changed("prometheus-server-addr") && !flagShowMetricNames +} + func runCmd(cmd *cobra.Command, args []string) error { // appContext is the application context that holds common data and resources. appContext := cmd.Parent().Context().Value(common.AppContext{}).(common.AppContext) @@ -840,6 +845,17 @@ func runCmd(cmd *cobra.Command, args []string) error { localOutputDir := appContext.OutputDir // Setup signal manager for coordinated shutdown signalMgr := newSignalManager() + // create output directory if needed + if needsOutputDir(cmd) { + err := util.CreateDirectoryIfNotExists(localOutputDir, 0755) // #nosec G301 + if err != nil { + err := fmt.Errorf("failed to create output directory: %w", err) + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + slog.Error(err.Error()) + cmd.SilenceUsage = true + return err + } + } // short circuit when --input flag is set if flagInput != "" { // skip data collection and use raw data for reports diff --git a/cmd/root.go b/cmd/root.go index a2606e05..584ed825 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -211,43 +211,6 @@ func initializeApplication(cmd *cobra.Command, args []string) error { if gLogFile != nil { logFilePath = gLogFile.Name() } - // create the output directory now to fail fast if there are permission or disk space issues - // this validates write access before any data collection begins - // skip creating output directory for config command since it doesn't generate output files - // also skip for metrics command with --live, --prometheus-server, or --list flags since they don't write files - // also skip for update command since it doesn't generate output files - needsOutputDir := true - if cmd.Name() == "config" || cmd.Name() == "update" { - needsOutputDir = false - } else if cmd.Name() == "metrics" { - // check if --live flag is set - if liveFlag, err := cmd.Flags().GetBool("live"); err == nil && liveFlag { - needsOutputDir = false - } - // check if --prometheus-server flag is set - if prometheusFlag, err := cmd.Flags().GetBool("prometheus-server"); err == nil && prometheusFlag { - needsOutputDir = false - } - // check if --prometheus-server-addr flag has been changed (which implies prometheus server mode) - if cmd.Flags().Changed("prometheus-server-addr") { - needsOutputDir = false - } - // check if --list flag is set (just lists metrics and exits) - if listFlag, err := cmd.Flags().GetBool("list"); err == nil && listFlag { - needsOutputDir = false - } - } - if needsOutputDir { - created, err := createOutputDir(outputDir) - if err != nil { - slog.Error("failed to create output directory", slog.String("path", outputDir), slog.String("error", err.Error())) - fmt.Printf("Error: failed to create output directory: %v\n", err) - os.Exit(1) - } - if created { - slog.Debug("output directory created", slog.String("path", outputDir)) - } - } // set app context cmd.Parent().SetContext( context.WithValue( @@ -350,30 +313,6 @@ func onIntelNetwork() bool { return true } -// createOutputDir creates the output directory if it does not exist. -// Returns true if the directory was created, false if it already existed. -func createOutputDir(outputDir string) (bool, error) { - // Check if directory already exists - info, err := os.Stat(outputDir) - if err == nil { - // Path exists, verify it's a directory - if !info.IsDir() { - return false, fmt.Errorf("output path exists but is not a directory: %s", outputDir) - } - return false, nil // Already exists - } - // If error is not "not exists", something else is wrong - if !os.IsNotExist(err) { - return false, fmt.Errorf("failed to check output directory: %w", err) - } - // Directory doesn't exist, create it - err = os.MkdirAll(outputDir, 0755) // #nosec G301 - if err != nil { - return false, fmt.Errorf("failed to create output directory: %w", err) - } - return true, nil // Created successfully -} - func checkForUpdates(version string) (bool, manifest, error) { latestManifest, err := getLatestManifest() if err != nil { diff --git a/internal/common/common.go b/internal/common/common.go index 2c5db882..bc8f1fe7 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -125,6 +125,15 @@ func (rc *ReportingCommand) Run() error { slog.Error("error sending signal to children", slog.String("error", err.Error())) } }() + // create output directory + err := util.CreateDirectoryIfNotExists(outputDir, 0755) // #nosec G301 + if err != nil { + err := fmt.Errorf("failed to create output directory: %w", err) + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + slog.Error(err.Error()) + rc.Cmd.SilenceUsage = true + return err + } var orderedTargetScriptOutputs []TargetScriptOutputs var myTargets []target.Target @@ -206,7 +215,7 @@ func (rc *ReportingCommand) Run() error { } // create the raw report before processing the data, so that we can save the raw data even if there is an error while processing var rawReports []string - rawReports, err := rc.createRawReports(appContext, orderedTargetScriptOutputs) + rawReports, err = rc.createRawReports(appContext, orderedTargetScriptOutputs) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) slog.Error(err.Error()) From bda1836ce4689ebc2d6292956cffc5c4dce3608d Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Wed, 26 Nov 2025 14:06:39 -0800 Subject: [PATCH 2/2] don't shaddow err Signed-off-by: Harper, Jason M --- cmd/metrics/metrics.go | 2 +- internal/common/common.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/metrics/metrics.go b/cmd/metrics/metrics.go index 06afdb47..1cdcbc74 100644 --- a/cmd/metrics/metrics.go +++ b/cmd/metrics/metrics.go @@ -849,7 +849,7 @@ func runCmd(cmd *cobra.Command, args []string) error { if needsOutputDir(cmd) { err := util.CreateDirectoryIfNotExists(localOutputDir, 0755) // #nosec G301 if err != nil { - err := fmt.Errorf("failed to create output directory: %w", err) + err = fmt.Errorf("failed to create output directory: %w", err) fmt.Fprintf(os.Stderr, "Error: %v\n", err) slog.Error(err.Error()) cmd.SilenceUsage = true diff --git a/internal/common/common.go b/internal/common/common.go index bc8f1fe7..91ef5dbe 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -128,7 +128,7 @@ func (rc *ReportingCommand) Run() error { // create output directory err := util.CreateDirectoryIfNotExists(outputDir, 0755) // #nosec G301 if err != nil { - err := fmt.Errorf("failed to create output directory: %w", err) + err = fmt.Errorf("failed to create output directory: %w", err) fmt.Fprintf(os.Stderr, "Error: %v\n", err) slog.Error(err.Error()) rc.Cmd.SilenceUsage = true