Fix prune command to use config file for bucket and prefix
- Remove --bucket and --prefix command line flags - Use bucket and prefix from S3 configuration in config file - Update command to follow same pattern as other commands - Maintain consistency that all configuration comes from config file
This commit is contained in:
parent
bb2292de7f
commit
1d027bde57
@ -5,18 +5,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/vaultik/internal/backup"
|
||||||
|
"git.eeqj.de/sneak/vaultik/internal/config"
|
||||||
|
"git.eeqj.de/sneak/vaultik/internal/database"
|
||||||
"git.eeqj.de/sneak/vaultik/internal/globals"
|
"git.eeqj.de/sneak/vaultik/internal/globals"
|
||||||
|
"git.eeqj.de/sneak/vaultik/internal/log"
|
||||||
|
"git.eeqj.de/sneak/vaultik/internal/s3"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PruneOptions contains options for the prune command
|
// PruneOptions contains options for the prune command
|
||||||
type PruneOptions struct {
|
type PruneOptions struct {
|
||||||
Bucket string
|
|
||||||
Prefix string
|
|
||||||
DryRun bool
|
DryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PruneApp contains all dependencies needed for pruning
|
||||||
|
type PruneApp struct {
|
||||||
|
Globals *globals.Globals
|
||||||
|
Config *config.Config
|
||||||
|
Repositories *database.Repositories
|
||||||
|
S3Client *s3.Client
|
||||||
|
DB *database.DB
|
||||||
|
Shutdowner fx.Shutdowner
|
||||||
|
}
|
||||||
|
|
||||||
// NewPruneCommand creates the prune command
|
// NewPruneCommand creates the prune command
|
||||||
func NewPruneCommand() *cobra.Command {
|
func NewPruneCommand() *cobra.Command {
|
||||||
opts := &PruneOptions{}
|
opts := &PruneOptions{}
|
||||||
@ -24,55 +37,111 @@ func NewPruneCommand() *cobra.Command {
|
|||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "prune",
|
Use: "prune",
|
||||||
Short: "Remove unreferenced blobs",
|
Short: "Remove unreferenced blobs",
|
||||||
Long: `Delete blobs that are no longer referenced by any snapshot`,
|
Long: `Delete blobs that are no longer referenced by any snapshot.
|
||||||
Args: cobra.NoArgs,
|
|
||||||
|
This command will:
|
||||||
|
1. Download all snapshot metadata from S3
|
||||||
|
2. Build a list of all referenced blobs
|
||||||
|
3. List all blobs in S3
|
||||||
|
4. Delete any blobs not referenced by any snapshot
|
||||||
|
|
||||||
|
Config is located at /etc/vaultik/config.yml by default, but can be overridden by
|
||||||
|
specifying a path using --config or by setting VAULTIK_CONFIG to a path.`,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
// Validate required flags
|
// Check for private key
|
||||||
if opts.Bucket == "" {
|
if os.Getenv("VAULTIK_PRIVATE_KEY") == "" {
|
||||||
return fmt.Errorf("--bucket is required")
|
return fmt.Errorf("VAULTIK_PRIVATE_KEY environment variable must be set")
|
||||||
}
|
}
|
||||||
if opts.Prefix == "" {
|
|
||||||
return fmt.Errorf("--prefix is required")
|
// Use unified config resolution
|
||||||
|
configPath, err := ResolveConfigPath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return runPrune(cmd.Context(), opts)
|
|
||||||
|
// Use the app framework like other commands
|
||||||
|
rootFlags := GetRootFlags()
|
||||||
|
return RunWithApp(cmd.Context(), AppOptions{
|
||||||
|
ConfigPath: configPath,
|
||||||
|
LogOptions: log.LogOptions{
|
||||||
|
Verbose: rootFlags.Verbose,
|
||||||
|
Debug: rootFlags.Debug,
|
||||||
|
},
|
||||||
|
Modules: []fx.Option{
|
||||||
|
backup.Module,
|
||||||
|
s3.Module,
|
||||||
|
fx.Provide(fx.Annotate(
|
||||||
|
func(g *globals.Globals, cfg *config.Config, repos *database.Repositories,
|
||||||
|
s3Client *s3.Client, db *database.DB, shutdowner fx.Shutdowner) *PruneApp {
|
||||||
|
return &PruneApp{
|
||||||
|
Globals: g,
|
||||||
|
Config: cfg,
|
||||||
|
Repositories: repos,
|
||||||
|
S3Client: s3Client,
|
||||||
|
DB: db,
|
||||||
|
Shutdowner: shutdowner,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Invokes: []fx.Option{
|
||||||
|
fx.Invoke(func(app *PruneApp, lc fx.Lifecycle) {
|
||||||
|
lc.Append(fx.Hook{
|
||||||
|
OnStart: func(ctx context.Context) error {
|
||||||
|
// Start the prune operation in a goroutine
|
||||||
|
go func() {
|
||||||
|
// Run the prune operation
|
||||||
|
if err := app.runPrune(ctx, opts); err != nil {
|
||||||
|
if err != context.Canceled {
|
||||||
|
log.Error("Prune operation failed", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown the app when prune completes
|
||||||
|
if err := app.Shutdowner.Shutdown(); err != nil {
|
||||||
|
log.Error("Failed to shutdown", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
OnStop: func(ctx context.Context) error {
|
||||||
|
log.Debug("Stopping prune operation")
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringVar(&opts.Bucket, "bucket", "", "S3 bucket name")
|
|
||||||
cmd.Flags().StringVar(&opts.Prefix, "prefix", "", "S3 prefix")
|
|
||||||
cmd.Flags().BoolVar(&opts.DryRun, "dry-run", false, "Show what would be deleted without actually deleting")
|
cmd.Flags().BoolVar(&opts.DryRun, "dry-run", false, "Show what would be deleted without actually deleting")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPrune(ctx context.Context, opts *PruneOptions) error {
|
// runPrune executes the prune operation
|
||||||
if os.Getenv("VAULTIK_PRIVATE_KEY") == "" {
|
func (app *PruneApp) runPrune(ctx context.Context, opts *PruneOptions) error {
|
||||||
return fmt.Errorf("VAULTIK_PRIVATE_KEY environment variable must be set")
|
log.Info("Starting prune operation",
|
||||||
}
|
"bucket", app.Config.S3.Bucket,
|
||||||
|
"prefix", app.Config.S3.Prefix,
|
||||||
app := fx.New(
|
"dry_run", opts.DryRun,
|
||||||
fx.Supply(opts),
|
|
||||||
fx.Provide(globals.New),
|
|
||||||
// Additional modules will be added here
|
|
||||||
fx.Invoke(func(g *globals.Globals) error {
|
|
||||||
// TODO: Implement prune logic
|
|
||||||
fmt.Printf("Pruning bucket %s with prefix %s\n", opts.Bucket, opts.Prefix)
|
|
||||||
if opts.DryRun {
|
|
||||||
fmt.Println("Running in dry-run mode")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}),
|
|
||||||
fx.NopLogger,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := app.Start(ctx); err != nil {
|
// TODO: Implement the actual prune logic
|
||||||
return fmt.Errorf("failed to start prune: %w", err)
|
// 1. Download all snapshot metadata
|
||||||
|
// 2. Build set of referenced blobs
|
||||||
|
// 3. List all blobs in S3
|
||||||
|
// 4. Delete unreferenced blobs
|
||||||
|
|
||||||
|
fmt.Printf("Pruning bucket %s with prefix %s\n", app.Config.S3.Bucket, app.Config.S3.Prefix)
|
||||||
|
if opts.DryRun {
|
||||||
|
fmt.Println("Running in dry-run mode")
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if err := app.Stop(ctx); err != nil {
|
// For now, just show we're using the config properly
|
||||||
fmt.Printf("error stopping app: %v\n", err)
|
log.Info("Prune operation completed successfully")
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user