mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-13 23:39:33 +01:00
shell: return flag parse errors from every command (#12618)
* shell: return flag parse errors from every command 48 commands returned nil when their flags failed to parse, so a mistyped flag printed the flag error but the command still counted as a success: a piped weed shell run exited 0, the master maintenance loop logged no error, and admin script jobs reported the line as done. Return the parse error as s3.bucket.create (#12544) and the other shell commands already do. TestCommandsReturnFlagParseErrors runs every registered command with an unknown flag and fails for the 48 on master. Signed-off-by: anant <170962632+antcybersec@users.noreply.github.com> * shell: don't report -h as a failure With the parse errors returned, -h on those commands now returns flag.ErrHelp, so the shell printed "error: flag: help requested" and a piped run exited 1. The flag package has already printed the usage, so processEachCmd now treats flag.ErrHelp as success for every command. Signed-off-by: anant <170962632+antcybersec@users.noreply.github.com> * shell: keep the -h test beside the flag parse test TestProcessEachCmdTreatsHelpAsSuccess covers the same change as TestCommandsReturnFlagParseErrors, so it lives in the same new file and shell_liner_test.go stays as it was. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Signed-off-by: anant <170962632+antcybersec@users.noreply.github.com> Co-authored-by: anant <170962632+antcybersec@users.noreply.github.com> Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
51 files changed
+113
-51
No files matched your search
+12
-1
@@ -1,6 +1,10 @@
|
||||
package shell
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"io"
|
||||
)
|
||||
|
||||
type command interface {
|
||||
Name() string
|
||||
@@ -19,3 +23,10 @@ const (
|
||||
ResourceHeavy CommandTag = "resourceHeavy"
|
||||
Hidden CommandTag = "hidden"
|
||||
)
|
||||
|
||||
// isHelpError reports whether a command only stopped because it was run
|
||||
// with -h: the flag package has already printed its usage, so this is not a
|
||||
// failure.
|
||||
func isHelpError(err error) bool {
|
||||
return errors.Is(err, flag.ErrHelp)
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func (c *commandClusterCheck) Do(args []string, commandEnv *CommandEnv, writer i
|
||||
|
||||
clusterPsCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if err = clusterPsCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// collect topology information
|
||||
|
||||
@@ -44,7 +44,7 @@ func (c *commandClusterPs) Do(args []string, commandEnv *CommandEnv, writer io.W
|
||||
|
||||
clusterPsCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if err = clusterPsCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
listClusterNodes := func(clientType string) ([]*master_pb.ListClusterNodesResponse_ClusterNode, error) {
|
||||
|
||||
@@ -39,7 +39,7 @@ func (c *commandRaftServerAdd) Do(args []string, commandEnv *CommandEnv, writer
|
||||
serverAddress := raftServerAddCommand.String("address", "", "server grpc address")
|
||||
serverVoter := raftServerAddCommand.Bool("voter", true, "assign it a vote")
|
||||
if err = raftServerAddCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *serverId == "" || *serverAddress == "" {
|
||||
|
||||
@@ -35,7 +35,7 @@ func (c *commandRaftClusterPs) Do(args []string, commandEnv *CommandEnv, writer
|
||||
|
||||
raftClusterPsCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if err = raftClusterPsCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
err = commandEnv.MasterClient.WithClient(context.Background(), false, func(client master_pb.SeaweedClient) error {
|
||||
|
||||
@@ -37,7 +37,7 @@ func (c *commandRaftServerRemove) Do(args []string, commandEnv *CommandEnv, writ
|
||||
raftServerAddCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
serverId := raftServerAddCommand.String("id", "", "server id")
|
||||
if err = raftServerAddCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *serverId == "" {
|
||||
|
||||
@@ -41,7 +41,7 @@ func (c *commandCollectionDelete) Do(args []string, commandEnv *CommandEnv, writ
|
||||
applyBalancingAlias := colDeleteCommand.Bool("force", false, "apply the collection (alias for -apply)")
|
||||
|
||||
if err = colDeleteCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, colDeleteCommand, applyBalancingAlias, applyBalancing)
|
||||
|
||||
@@ -55,7 +55,7 @@ func (c *commandEcBalance) Do(args []string, commandEnv *CommandEnv, writer io.W
|
||||
applyBalancingAlias := balanceCommand.Bool("force", false, "apply the balancing plan (alias for -apply)")
|
||||
|
||||
if err = balanceCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, balanceCommand, applyBalancingAlias, applyBalancing)
|
||||
|
||||
@@ -60,7 +60,7 @@ func (c *commandEcDecode) Do(args []string, commandEnv *CommandEnv, writer io.Wr
|
||||
checkMinFreeSpace := decodeCommand.Bool("checkMinFreeSpace", true, "check min free space when selecting the decode target")
|
||||
batchSize := decodeCommand.Int("batchSize", DefaultEcBatchSize, "decode up to this many volumes per topology refresh (0 = one snapshot for all volumes)")
|
||||
if err = decodeCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if *batchSize < 0 {
|
||||
return fmt.Errorf("-batchSize must be >= 0")
|
||||
|
||||
@@ -114,7 +114,7 @@ func (c *commandEcEncode) Do(args []string, commandEnv *CommandEnv, writer io.Wr
|
||||
verbose := encodeCommand.Bool("verbose", false, "show detailed reasons why volumes are not selected for encoding")
|
||||
|
||||
if err = encodeCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if err = commandEnv.confirmIsLocked(args); err != nil {
|
||||
return
|
||||
|
||||
@@ -88,7 +88,7 @@ func (c *commandEcRebuild) Do(args []string, commandEnv *CommandEnv, writer io.W
|
||||
// TODO: remove this alias
|
||||
applyChangesAlias := fixCommand.Bool("force", false, "apply the changes (alias for -apply)")
|
||||
if err = fixCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
handleDeprecatedForceFlag(writer, fixCommand, applyChangesAlias, applyChanges)
|
||||
infoAboutSimulationMode(writer, *applyChanges, "-apply")
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A command that parses flags must report a bad flag as an error. Returning
|
||||
// nil makes a typo in a weed shell script or a master maintenance script look
|
||||
// like a successful run that did nothing.
|
||||
func TestCommandsReturnFlagParseErrors(t *testing.T) {
|
||||
for _, c := range Commands {
|
||||
t.Run(c.Name(), func(t *testing.T) {
|
||||
// fs.meta.load parses every argument but the last as flags.
|
||||
err, needsEnv := doWithoutCommandEnv(c, []string{"-notAFlagOfAnyCommand", "arg"})
|
||||
if needsEnv {
|
||||
t.Skip("uses the command environment before parsing any flags")
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("an unknown flag was reported as success")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "flag provided but not defined") {
|
||||
t.Skipf("rejects its arguments without parsing flags: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// doWithoutCommandEnv runs c with a nil CommandEnv. A command that panics here
|
||||
// used the environment before parsing flags, or takes no flags at all.
|
||||
func doWithoutCommandEnv(c command, args []string) (err error, needsEnv bool) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
needsEnv = true
|
||||
}
|
||||
}()
|
||||
var out bytes.Buffer
|
||||
return c.Do(args, nil, &out), false
|
||||
}
|
||||
|
||||
func TestProcessEachCmdTreatsHelpAsSuccess(t *testing.T) {
|
||||
Commands = append(Commands, &fakeCommand{name: "test.help.command", err: flag.ErrHelp})
|
||||
t.Cleanup(func() { Commands = Commands[:len(Commands)-1] })
|
||||
|
||||
exit, err := processEachCmd("test.help.command -h", nil)
|
||||
if exit || err != nil {
|
||||
t.Errorf("-h must not count as a failure, got exit=%v err=%v", exit, err)
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func (c *commandFsConfigure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
isDelete := fsConfigureCommand.Bool("delete", false, "delete the configuration by locationPrefix")
|
||||
apply := fsConfigureCommand.Bool("apply", false, "update and apply filer configuration")
|
||||
if err = fsConfigureCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
fc, err := filer.ReadFilerConf(commandEnv.FilerAddress(), commandEnv.option.GrpcDialOption, commandEnv.MasterClient)
|
||||
|
||||
@@ -57,7 +57,7 @@ func (c *commandFsMetaLoad) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
concurrency := metaLoadCommand.Int("concurrency", 1, "number of parallel meta load to filer")
|
||||
verbose := metaLoadCommand.Bool("v", true, "verbose mode")
|
||||
if err = metaLoadCommand.Parse(args[0 : len(args)-1]); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
var dst io.Reader
|
||||
|
||||
@@ -45,7 +45,7 @@ func (c *commandMountConfigure) Do(args []string, commandEnv *CommandEnv, writer
|
||||
mountDir := mountConfigureCommand.String("dir", "", "the mount directory same as how \"weed mount -dir=<mount_directory>\" was started")
|
||||
mountQuota := mountConfigureCommand.Int("quotaMB", 0, "the quota in MB")
|
||||
if err = mountConfigureCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
mountDirHash := util.HashToInt32([]byte(*mountDir))
|
||||
|
||||
@@ -74,7 +74,7 @@ func (c *commandRemoteCache) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
fileFiler := newFileFilter(remoteCacheCommand)
|
||||
|
||||
if err = remoteCacheCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *dir == "" {
|
||||
|
||||
@@ -69,7 +69,7 @@ func (c *commandRemoteConfigure) Do(args []string, commandEnv *CommandEnv, write
|
||||
|
||||
fs, isDelete, uploadConcurrency, downloadConcurrency := c.configureFlagSet(conf, false)
|
||||
if err = fs.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if conf.Name == "" {
|
||||
@@ -110,7 +110,7 @@ func (c *commandRemoteConfigure) Do(args []string, commandEnv *CommandEnv, write
|
||||
}
|
||||
fs, isDelete, uploadConcurrency, downloadConcurrency = c.configureFlagSet(conf, true)
|
||||
if err = fs.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ func (c *commandRemoteMetaSync) Do(args []string, commandEnv *CommandEnv, writer
|
||||
statFiles := remoteMetaSyncCommand.Bool("statFiles", false, "stat each new or changed file when the listing does not report all metadata (S3 listings lack Content-Encoding); costs one extra remote request per file")
|
||||
|
||||
if err = remoteMetaSyncCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
mappings, localMountedDir, remoteStorageMountedLocation, remoteStorageConf, detectErr := detectMountInfo(commandEnv, writer, *dir)
|
||||
|
||||
@@ -76,7 +76,7 @@ func (c *commandRemoteMount) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
cacheWait := remoteMountCommand.Duration("cacheWait", -1, "how long a read of an uncached object waits for the local cache, ex. 0 or 500ms (default: by object size)")
|
||||
|
||||
if err = remoteMountCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *dir == "" {
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c *commandRemoteMountBuckets) Do(args []string, commandEnv *CommandEnv, wr
|
||||
trimBucketSuffix := remoteMountBucketsCommand.Bool("trimBucketSuffix", true, "remote suffix auto generated by 'weed filer.remote.sync'")
|
||||
apply := remoteMountBucketsCommand.Bool("apply", false, "apply the mount for listed buckets")
|
||||
if err = remoteMountBucketsCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
infoAboutSimulationMode(writer, *apply, "-apply")
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func (c *commandRemoteUncache) Do(args []string, commandEnv *CommandEnv, writer
|
||||
fileFiler := newFileFilter(remoteUncacheCommand)
|
||||
|
||||
if err = remoteUncacheCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
mappings, listErr := filer.ReadMountMappings(commandEnv.option.GrpcDialOption, commandEnv.FilerAddress())
|
||||
|
||||
@@ -49,7 +49,7 @@ func (c *commandRemoteUnmount) Do(args []string, commandEnv *CommandEnv, writer
|
||||
dir := remoteMountCommand.String("dir", "", "a directory in filer")
|
||||
|
||||
if err = remoteMountCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
mappings, listErr := filer.ReadMountMappings(commandEnv.option.GrpcDialOption, commandEnv.FilerAddress())
|
||||
|
||||
@@ -37,7 +37,7 @@ func (c *commandS3BucketDelete) Do(args []string, commandEnv *CommandEnv, writer
|
||||
bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
bucketName := bucketCommand.String("name", "", "bucket name")
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *bucketName == "" {
|
||||
|
||||
@@ -37,7 +37,7 @@ func (c *commandS3BucketList) Do(args []string, commandEnv *CommandEnv, writer i
|
||||
|
||||
bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// collect collection information
|
||||
|
||||
@@ -56,7 +56,7 @@ func (c *commandS3BucketOwner) Do(args []string, commandEnv *CommandEnv, writer
|
||||
bucketOwner := bucketCommand.String("owner", "", "new bucket owner identity name")
|
||||
deleteOwner := bucketCommand.Bool("delete", false, "remove the bucket owner (make admin-only)")
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *bucketName == "" {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (c *commandS3BucketQuota) Do(args []string, commandEnv *CommandEnv, writer
|
||||
operationName := bucketCommand.String("op", "set", "operation name [set|get|remove|enable|disable]")
|
||||
sizeMB := bucketCommand.Int64("sizeMB", 0, "bucket quota size in MiB")
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *bucketName == "" {
|
||||
|
||||
@@ -40,7 +40,7 @@ func (c *commandS3BucketQuotaEnforce) Do(args []string, commandEnv *CommandEnv,
|
||||
bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
applyQuotaLimit := bucketCommand.Bool("apply", false, "actually change the buckets readonly attribute")
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
infoAboutSimulationMode(writer, *applyQuotaLimit, "-apply")
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ func (c *commandS3CircuitBreaker) Do(args []string, commandEnv *CommandEnv, writ
|
||||
apply := s3CircuitBreakerCommand.Bool("apply", false, "update and apply current configuration")
|
||||
|
||||
if err = s3CircuitBreakerCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ func (c *commandS3CleanUploads) Do(args []string, commandEnv *CommandEnv, writer
|
||||
bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
uploadedTimeAgo := bucketCommand.Duration("timeAgo", 24*time.Hour, "created time before now. \"1.5h\" or \"2h45m\". Valid time units are \"m\", \"h\"")
|
||||
if err = bucketCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
var filerBucketsPath string
|
||||
|
||||
@@ -63,7 +63,7 @@ func (c *commandS3Configure) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
isDelete := s3ConfigureCommand.Bool("delete", false, "delete users, actions, access keys or policies")
|
||||
apply := s3ConfigureCommand.Bool("apply", false, "update and apply s3 configuration")
|
||||
if err = s3ConfigureCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Case 1: List configuration (no user specified)
|
||||
|
||||
@@ -158,7 +158,7 @@ func (c *commandVolumeBalance) Do(args []string, commandEnv *CommandEnv, writer
|
||||
return fmt.Errorf("use \"ALL\", \"ACTIVE\" or \"FULL\"")
|
||||
})
|
||||
if err = balanceCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
handleDeprecatedForceFlag(writer, balanceCommand, applyBalancingAlias, applyBalancing)
|
||||
c.applyBalancing = *applyBalancing
|
||||
|
||||
@@ -112,7 +112,7 @@ func (c *commandVolumeCheckDisk) Do(args []string, commandEnv *CommandEnv, write
|
||||
nonRepairThreshold := fsckCommand.Float64("nonRepairThreshold", 0.3, "repair when missing keys is not more than this limit")
|
||||
resurrectMissingNeedles := fsckCommand.Bool("resurrectMissingNeedles", false, "copy needles absent on one replica back from the other, only into never-vacuumed replicas (compaction revision 0)")
|
||||
if err = fsckCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, fsckCommand, applyChangesAlias, applyChanges)
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c *commandVolumeConfigureReplication) Do(args []string, commandEnv *Comman
|
||||
collectionPattern := configureReplicationCommand.String("collectionPattern", "", "comma-separated collection names, with '*' and '?' wildcards; empty matches all")
|
||||
maxParallelization := configureReplicationCommand.Int("maxParallelization", DefaultMaxParallelization, "run up to X tasks in parallel, whenever possible")
|
||||
if err = configureReplicationCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = commandEnv.confirmIsLocked(args); err != nil {
|
||||
|
||||
@@ -44,7 +44,7 @@ func (c *commandVolumeCopy) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
targetNodeStr := volCopyCommand.String("target", "", "the target volume server <host>:<port>")
|
||||
noLock := volCopyCommand.Bool("noLock", false, "do not lock the admin shell at one's own risk")
|
||||
if err = volCopyCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *noLock {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (c *commandVolumeDelete) Do(args []string, commandEnv *CommandEnv, writer i
|
||||
nodeStr := volDeleteCommand.String("node", "", "the volume server <host>:<port>")
|
||||
timeout := volDeleteCommand.Duration("timeout", 0, "wall-clock cap on the deletion; 0 = no timeout")
|
||||
if err = volDeleteCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = commandEnv.confirmIsLocked(args); err != nil {
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c *commandVolumeDeleteEmpty) Do(args []string, commandEnv *CommandEnv, wri
|
||||
// TODO: remove this alias
|
||||
applyBalancingAlias := volDeleteCommand.Bool("force", false, "apply to delete empty volumes (alias for -apply)")
|
||||
if err = volDeleteCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, volDeleteCommand, applyBalancingAlias, applyBalancing)
|
||||
|
||||
@@ -84,7 +84,7 @@ func (c *commandVolumeFixReplication) Do(args []string, commandEnv *CommandEnv,
|
||||
volumesPerStep := volFixReplicationCommand.Int("volumesPerStep", 0, "how many volumes to fix in one cycle")
|
||||
|
||||
if err = volFixReplicationCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if c.collectionMatcher, err = wildcard.CompileCollectionMatcher(*collectionPattern); err != nil {
|
||||
|
||||
@@ -141,7 +141,7 @@ func (c *commandVolumeFsck) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
c.verifyNeedle = fsckCommand.Bool("verifyNeedles", false, "check needles status from volume server")
|
||||
|
||||
if err = fsckCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// The command struct is a singleton registered in init(), so any state
|
||||
|
||||
@@ -46,7 +46,7 @@ func (c *commandGrow) Do(args []string, commandEnv *CommandEnv, writer io.Writer
|
||||
diskType := volumeVacuumCommand.String("diskType", "", "grow volumes only from the specified disk type")
|
||||
|
||||
if err = volumeVacuumCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if *collection == "" {
|
||||
return fmt.Errorf("collection option is required")
|
||||
|
||||
@@ -63,7 +63,7 @@ func (c *commandVolumeList) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
c.dataNode = volumeListCommand.String("dataNode", "", "show volumes only from the specified data node")
|
||||
|
||||
if err = volumeListCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if c.collectionMatcher, err = wildcard.CompileCollectionMatcher(*collectionPattern); err != nil {
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c *commandVolumeMark) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
readonly := volMarkCommand.Bool("readonly", false, "volume mark readonly")
|
||||
readonlyCanDelete := volMarkCommand.Bool("readonlyCanDelete", false, "volume mark readonly but still accepting deletes")
|
||||
if err = volMarkCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
collectionSet, nodeSet, volumeIdSet := false, false, false
|
||||
volMarkCommand.Visit(func(f *flag.Flag) {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (c *commandVolumeMount) Do(args []string, commandEnv *CommandEnv, writer io
|
||||
volumeIdInt := volMountCommand.Int("volumeId", 0, "the volume id")
|
||||
nodeStr := volMountCommand.String("node", "", "the volume server <host>:<port>")
|
||||
if err = volMountCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = commandEnv.confirmIsLocked(args); err != nil {
|
||||
|
||||
@@ -64,7 +64,7 @@ func (c *commandVolumeMove) Do(args []string, commandEnv *CommandEnv, writer io.
|
||||
noLock := volMoveCommand.Bool("noLock", false, "do not lock the admin shell at one's own risk")
|
||||
|
||||
if err = volMoveCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if *noLock {
|
||||
|
||||
@@ -48,7 +48,7 @@ func (c *commandVolumeServerLeave) Do(args []string, commandEnv *CommandEnv, wri
|
||||
// TODO: remove this alias
|
||||
applyChangesAlias := vsLeaveCommand.Bool("force", false, "apply the changes (alias for -apply)")
|
||||
if err = vsLeaveCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, vsLeaveCommand, applyChangesAlias, applyChanges)
|
||||
|
||||
@@ -68,7 +68,7 @@ func (c *commandVolumeTierCompact) Do(args []string, commandEnv *CommandEnv, wri
|
||||
garbageThreshold := tierCommand.Float64("garbageThreshold", 0.3, "compact when garbage ratio exceeds this value")
|
||||
concurrency := tierCommand.Int("concurrency", 0, "multipart transfer concurrency (0 = backend default)")
|
||||
if err = tierCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = validateTierConcurrency(*concurrency); err != nil {
|
||||
|
||||
@@ -66,7 +66,7 @@ func (c *commandVolumeTierDownload) Do(args []string, commandEnv *CommandEnv, wr
|
||||
collection := tierCommand.String("collection", "", "comma-separated collection names, wildcards, or regex patterns; empty matches the collection with no name")
|
||||
concurrency := tierCommand.Int("concurrency", 0, "multipart download concurrency (0 = backend default)")
|
||||
if err = tierCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = validateTierConcurrency(*concurrency); err != nil {
|
||||
|
||||
@@ -95,7 +95,7 @@ func (c *commandVolumeTierMove) Do(args []string, commandEnv *CommandEnv, writer
|
||||
replicationString := tierCommand.String("toReplication", "", "the new target replication setting")
|
||||
|
||||
if err = tierCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
handleDeprecatedForceFlag(writer, tierCommand, applyChangeAlias, applyChange)
|
||||
|
||||
@@ -97,7 +97,7 @@ func (c *commandVolumeTierUpload) Do(args []string, commandEnv *CommandEnv, writ
|
||||
disk := tierCommand.String("disk", "", "[hdd|ssd|<tag>] hard drive or solid state drive or any tag")
|
||||
concurrency := tierCommand.Int("concurrency", 0, "multipart upload concurrency (0 = backend default)")
|
||||
if err = tierCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if err = validateTierConcurrency(*concurrency); err != nil {
|
||||
|
||||
@@ -44,7 +44,7 @@ func (c *commandVolumeUnmount) Do(args []string, commandEnv *CommandEnv, writer
|
||||
volumeIdInt := volUnmountCommand.Int("volumeId", 0, "the volume id")
|
||||
nodeStr := volUnmountCommand.String("node", "", "the volume server <host>:<port>")
|
||||
if err = volUnmountCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if *nodeStr == "" {
|
||||
return fmt.Errorf("-node option is required")
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c *commandVacuum) Do(args []string, commandEnv *CommandEnv, writer io.Writ
|
||||
collection := volumeVacuumCommand.String("collection", "", "comma-separated collection names, wildcards, or regex patterns; empty or \"*\" matches all, \""+CollectionDefault+"\" the collection with no name")
|
||||
volumeIds := volumeVacuumCommand.String("volumeId", "", "comma-separated list of volume IDs")
|
||||
if err = volumeVacuumCommand.Parse(args); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
collectionMatcher, err := wildcard.CompileCollectionMatcher(*collection)
|
||||
|
||||
@@ -137,7 +137,7 @@ func processEachCmd(cmd string, commandEnv *CommandEnv) (exit bool, cmdErr error
|
||||
// every later command in the session unlocked, so a real
|
||||
// mutation right after a simulation would skip its lock.
|
||||
commandEnv.SetNoLock(false)
|
||||
if err := c.Do(args, commandEnv, os.Stdout); err != nil {
|
||||
if err := c.Do(args, commandEnv, os.Stdout); err != nil && !isHelpError(err) {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
cmdErr = err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user