All checks were successful
check / check (push) Successful in 2m38s
Scanner now writes all user-facing output to an io.Writer (os.Stdout when progress is enabled, io.Discard in --cron mode). This fixes the long-standing issue where --cron still printed progress lines. S3 HeadObject now properly distinguishes not-found from other errors instead of swallowing all errors as not-found. Config/CLI error messages include actionable hints (where to find the config, how to generate keys, what storage options exist).
84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// RootFlags holds global flags that apply to all commands.
|
|
// These flags are defined on the root command and inherited by all subcommands.
|
|
type RootFlags struct {
|
|
ConfigPath string
|
|
Verbose bool
|
|
Debug bool
|
|
Quiet bool
|
|
}
|
|
|
|
var rootFlags RootFlags
|
|
|
|
// NewRootCommand creates the root cobra command for the vaultik CLI.
|
|
// It sets up the command structure, global flags, and adds all subcommands.
|
|
// This is the main entry point for the CLI command hierarchy.
|
|
func NewRootCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "vaultik",
|
|
Short: "Secure incremental backup tool with asymmetric encryption",
|
|
Long: `vaultik is a secure incremental backup tool that encrypts data using age
|
|
public keys and uploads to S3-compatible storage. No private keys are needed
|
|
on the source system.`,
|
|
SilenceUsage: true,
|
|
}
|
|
|
|
// Add global flags
|
|
cmd.PersistentFlags().StringVar(&rootFlags.ConfigPath, "config", "", "Path to config file (default: $VAULTIK_CONFIG or /etc/vaultik/config.yml)")
|
|
cmd.PersistentFlags().BoolVarP(&rootFlags.Verbose, "verbose", "v", false, "Enable verbose output")
|
|
cmd.PersistentFlags().BoolVar(&rootFlags.Debug, "debug", false, "Enable debug output")
|
|
cmd.PersistentFlags().BoolVarP(&rootFlags.Quiet, "quiet", "q", false, "Suppress non-error output")
|
|
|
|
// Add subcommands
|
|
cmd.AddCommand(
|
|
NewRestoreCommand(),
|
|
NewPruneCommand(),
|
|
NewStoreCommand(),
|
|
NewSnapshotCommand(),
|
|
NewInfoCommand(),
|
|
NewVersionCommand(),
|
|
NewRemoteCommand(),
|
|
NewDatabaseCommand(),
|
|
)
|
|
|
|
return cmd
|
|
}
|
|
|
|
// GetRootFlags returns the global flags that were parsed from the command line.
|
|
// This allows subcommands to access global flag values like verbosity and config path.
|
|
func GetRootFlags() RootFlags {
|
|
return rootFlags
|
|
}
|
|
|
|
// ResolveConfigPath resolves the config file path from flags, environment, or default.
|
|
// It checks in order: 1) --config flag, 2) VAULTIK_CONFIG environment variable,
|
|
// 3) default location /etc/vaultik/config.yml. Returns an error if no valid
|
|
// config file can be found through any of these methods.
|
|
func ResolveConfigPath() (string, error) {
|
|
// First check global flag
|
|
if rootFlags.ConfigPath != "" {
|
|
return rootFlags.ConfigPath, nil
|
|
}
|
|
|
|
// Then check environment variable
|
|
if envPath := os.Getenv("VAULTIK_CONFIG"); envPath != "" {
|
|
return envPath, nil
|
|
}
|
|
|
|
// Finally check default location
|
|
defaultPath := "/etc/vaultik/config.yml"
|
|
if _, err := os.Stat(defaultPath); err == nil {
|
|
return defaultPath, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("no config file found; specify one with --config, set VAULTIK_CONFIG, or create %s", defaultPath)
|
|
}
|