cli: ensure advanced commands are not accidentally used (#611)

* cli: ensure advanced commands are not accidentally used

This prints an error when a dangerous command is used without
first setting KOPIA_ADVANCED_COMMANDS=enabled environment variable.

Co-authored-by: Julio López <julio+gh@kasten.io>
This commit is contained in:
Jarek Kowalski
2020-09-12 20:31:25 -07:00
committed by GitHub
parent 5784d68766
commit 6a14ac8a2a
10 changed files with 38 additions and 7 deletions

View File

@@ -184,6 +184,20 @@ func maybeRunMaintenance(ctx context.Context, rep repo.Repository) error {
return err
}
func advancedCommand() {
if os.Getenv("KOPIA_ADVANCED_COMMANDS") != "enabled" {
//nolint:errcheck
errorColor.Printf(`
This command could be dangerous or lead to repository corruption when used improperly.
Running this command is not needed for using Kopia. Instead, most users should rely on periodic repository maintenance. See https://kopia.io/docs/maintenance/ for more information.
To run this command despite the warning, set KOPIA_ADVANCED_COMMANDS=enabled
`)
os.Exit(1)
}
}
// App returns an instance of command-line application object.
func App() *kingpin.Application {
return app

View File

@@ -15,6 +15,8 @@
)
func runDeleteBlobs(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
for _, b := range *blobDeleteBlobIDs {
err := rep.Blobs.DeleteBlob(ctx, blob.ID(b))
if err != nil {

View File

@@ -17,6 +17,8 @@
)
func runBlobGarbageCollectCommand(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
opts := maintenance.DeleteUnreferencedBlobsOptions{
DryRun: *blobGarbageCollectCommandDelete != "yes",
MinAge: *blobGarbageCollectMinAge,

View File

@@ -22,6 +22,8 @@
)
func runContentRewriteCommand(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
return maintenance.RewriteContents(ctx, rep, &maintenance.RewriteContentsOptions{
ContentIDRange: contentIDRange(),
ContentIDs: toContentIDs(*contentRewriteIDs),

View File

@@ -13,6 +13,8 @@
)
func runContentRemoveCommand(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
for _, contentID := range toContentIDs(*contentRemoveIDs) {
if err := rep.Content.DeleteContent(ctx, contentID); err != nil {
return err

View File

@@ -17,6 +17,8 @@
)
func runOptimizeCommand(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
opt := content.CompactOptions{
MaxSmallBlobs: *optimizeMaxSmallBlobs,
AllIndexes: *optimizeAllIndexes,

View File

@@ -17,6 +17,8 @@
)
func runRecoverBlockIndexesAction(ctx context.Context, rep *repo.DirectRepository) error {
advancedCommand()
var totalCount int
defer func() {

View File

@@ -12,6 +12,8 @@
)
func runManifestRemoveCommand(ctx context.Context, rep repo.Repository) error {
advancedCommand()
for _, it := range toManifestIDs(*manifestRemoveItems) {
if err := rep.DeleteManifest(ctx, it); err != nil {
return err

View File

@@ -10,7 +10,7 @@
)
var (
snapshotGCCommand = snapshotCommands.Command("gc", "Remove contents not used by any snapshot")
snapshotGCCommand = snapshotCommands.Command("gc", "Mark contents as deleted which are not used by any snapshot").Hidden()
snapshotGCMinContentAge = snapshotGCCommand.Flag("min-age", "Minimum content age to allow deletion").Default("24h").Duration()
snapshotGCDelete = snapshotGCCommand.Flag("delete", "Delete unreferenced contents").Bool()
)

View File

@@ -92,12 +92,15 @@ func NewCLITest(t *testing.T) *CLITest {
}
return &CLITest{
startTime: clock.Now(),
RepoDir: RepoDir,
ConfigDir: ConfigDir,
Exe: filepath.FromSlash(exe),
fixedArgs: fixedArgs,
Environment: []string{"KOPIA_PASSWORD=" + repoPassword},
startTime: clock.Now(),
RepoDir: RepoDir,
ConfigDir: ConfigDir,
Exe: filepath.FromSlash(exe),
fixedArgs: fixedArgs,
Environment: []string{
"KOPIA_PASSWORD=" + repoPassword,
"KOPIA_ADVANCED_COMMANDS=enabled",
},
}
}