check / check (push) Waiting to run
snapshot verify --help now says --deep needs the age private key, from VAULTIK_AGE_SECRET_KEY or age_secret_key, as snapshot restore does. Both now name the config key as well as the environment variable. The help of snapshot create, list, purge, remove, prune, remote info and remote nuke says which access to the destination it needs. config.example.yml gains age_secret_key, and no longer tells the reader to pipe age-keygen into grep, which discards the private key. Only help strings and comments change. Model: fable-5-1
116 lines
3.3 KiB
Go
116 lines
3.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/spf13/cobra"
|
|
"sneak.berlin/go/vaultik/internal/log"
|
|
"sneak.berlin/go/vaultik/internal/vaultik"
|
|
)
|
|
|
|
// errNukeNeedsForce guards the destructive 'remote nuke' subcommand.
|
|
var errNukeNeedsForce = errors.New(
|
|
"remote nuke requires --force (this deletes ALL remote snapshots and blobs)")
|
|
|
|
// NewRemoteCommand creates the remote command and subcommands
|
|
func NewRemoteCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "remote",
|
|
Short: "Remote storage management commands",
|
|
Long: "Commands for inspecting and managing remote storage",
|
|
// cobra checks Args only on a command that has a Run: without
|
|
// one, a mistyped subcommand printed help and exited 0.
|
|
Args: cobra.NoArgs,
|
|
Run: func(cmd *cobra.Command, _ []string) {
|
|
_ = cmd.Help()
|
|
},
|
|
}
|
|
|
|
// Add subcommands
|
|
cmd.AddCommand(newRemoteInfoCommand())
|
|
cmd.AddCommand(newRemoteNukeCommand())
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newRemoteNukeCommand creates the 'remote nuke' subcommand.
|
|
func newRemoteNukeCommand() *cobra.Command {
|
|
var force bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "nuke",
|
|
Short: "Delete ALL snapshot metadata and blobs from the backup destination store",
|
|
Long: `Removes every snapshot's metadata, every blob and the destination
|
|
marker from remote storage, and each removed snapshot from the local
|
|
index. After this command completes successfully the bucket prefix is
|
|
empty and the next backup starts from scratch.
|
|
|
|
This is destructive and irreversible. Requires --force, and permission
|
|
to list and delete objects on the destination store.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
if !force {
|
|
return errNukeNeedsForce
|
|
}
|
|
|
|
return runVaultikApp(cmd, mutating, false, "Remote nuke failed",
|
|
func(v *vaultik.Vaultik) error {
|
|
return v.NukeRemote(true)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&force, "force", false,
|
|
"Required: confirm destruction of ALL remote data")
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newRemoteInfoCommand creates the 'remote info' subcommand
|
|
func newRemoteInfoCommand() *cobra.Command {
|
|
var jsonOutput bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "info",
|
|
Short: "Display remote storage information",
|
|
Long: `Shows detailed information about remote storage, including:
|
|
- Size of all snapshot metadata (per snapshot and total)
|
|
- Count and total size of all blobs
|
|
- Count and size of referenced blobs (from all manifests)
|
|
- Count and size of orphaned blobs (not referenced by any manifest)
|
|
|
|
Needs permission to list and read the destination store. It does not
|
|
need the age private key.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
// Use unified config resolution
|
|
configPath, err := ResolveConfigPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rootFlags := GetRootFlags()
|
|
|
|
return RunOperation(cmd.Context(), AppOptions{
|
|
ConfigPath: configPath,
|
|
LogOptions: log.Options{
|
|
Verbose: rootFlags.Verbose,
|
|
Debug: rootFlags.Debug,
|
|
Quiet: rootFlags.Quiet,
|
|
JSON: jsonOutput,
|
|
},
|
|
Mode: readOnly,
|
|
}, func(v *vaultik.Vaultik) error {
|
|
return v.RemoteInfo(jsonOutput)
|
|
}, func(err error) {
|
|
log.Error("Failed to get remote info", "error", err)
|
|
ReportErrorf("Failed to get remote info: %v", err)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output in JSON format")
|
|
|
|
return cmd
|
|
}
|