From 1e10381143d6e12e3acca55ea1f854f4cc0d5045 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Thu, 9 Jul 2020 18:58:22 +0200 Subject: [PATCH] improve help strings formatting Fixes #139 --- cmd/initprovider.go | 8 +++-- cmd/install_windows.go | 3 +- cmd/portable.go | 74 ++++++++++++++++++++++++++------------- cmd/root.go | 74 +++++++++++++++++++++++++++------------ cmd/rotatelogs_windows.go | 2 +- cmd/serve.go | 5 +-- cmd/service_windows.go | 2 +- docs/portable-mode.md | 69 ++++++++++++++++++++++++++---------- docs/service.md | 4 +-- 9 files changed, 165 insertions(+), 76 deletions(-) diff --git a/cmd/initprovider.go b/cmd/initprovider.go index 2b5f6069..90540059 100644 --- a/cmd/initprovider.go +++ b/cmd/initprovider.go @@ -17,17 +17,19 @@ var ( initProviderCmd = &cobra.Command{ Use: "initprovider", Short: "Initializes the configured data provider", - Long: `This command reads the data provider connection details from the specified configuration file and creates the initial structure. + Long: `This command reads the data provider connection details from the specified +configuration file and creates the initial structure. Some data providers such as bolt and memory does not require an initialization. For SQLite provider the database file will be auto created if missing. -For PostgreSQL and MySQL providers you need to create the configured database, this command will create the required tables. +For PostgreSQL and MySQL providers you need to create the configured database, +this command will create the required tables. To initialize the data provider from the configuration directory simply use: -sftpgo initprovider +$ sftpgo initprovider Please take a look at the usage below to customize the options.`, Run: func(cmd *cobra.Command, args []string) { diff --git a/cmd/install_windows.go b/cmd/install_windows.go index fe964836..c4353f50 100644 --- a/cmd/install_windows.go +++ b/cmd/install_windows.go @@ -15,7 +15,8 @@ var ( installCmd = &cobra.Command{ Use: "install", Short: "Install SFTPGo as Windows Service", - Long: `To install the SFTPGo Windows Service with the default values for the command line flags simply use: + Long: `To install the SFTPGo Windows Service with the default values for the command +line flags simply use: sftpgo service install diff --git a/cmd/portable.go b/cmd/portable.go index fcf7ee9a..4cd4d9cf 100644 --- a/cmd/portable.go +++ b/cmd/portable.go @@ -52,9 +52,10 @@ var ( portableCmd = &cobra.Command{ Use: "portable", Short: "Serve a single directory", - Long: `To serve the current working directory with auto generated credentials simply use: + Long: `To serve the current working directory with auto generated credentials simply +use: -sftpgo portable +$ sftpgo portable Please take a look at the usage below to customize the serving parameters`, Run: func(cmd *cobra.Command, args []string) { @@ -145,45 +146,70 @@ Please take a look at the usage below to customize the serving parameters`, func init() { version.AddFeature("+portable") - portableCmd.Flags().StringVarP(&directoryToServe, "directory", "d", ".", - "Path to the directory to serve. This can be an absolute path or a path relative to the current directory") - portableCmd.Flags().IntVarP(&portableSFTPDPort, "sftpd-port", "s", 0, "0 means a random non privileged port") + portableCmd.Flags().StringVarP(&directoryToServe, "directory", "d", ".", `Path to the directory to serve. +This can be an absolute path or a path +relative to the current directory +`) + portableCmd.Flags().IntVarP(&portableSFTPDPort, "sftpd-port", "s", 0, "0 means a random unprivileged port") portableCmd.Flags().StringSliceVarP(&portableSSHCommands, "ssh-commands", "c", sftpd.GetDefaultSSHCommands(), - "SSH commands to enable. \"*\" means any supported SSH command including scp") - portableCmd.Flags().StringVarP(&portableUsername, "username", "u", "", "Leave empty to use an auto generated value") - portableCmd.Flags().StringVarP(&portablePassword, "password", "p", "", "Leave empty to use an auto generated value") + `SSH commands to enable. +"*" means any supported SSH command +including scp +`) + portableCmd.Flags().StringVarP(&portableUsername, "username", "u", "", `Leave empty to use an auto generated +value`) + portableCmd.Flags().StringVarP(&portablePassword, "password", "p", "", `Leave empty to use an auto generated +value`) portableCmd.Flags().StringVarP(&portableLogFile, logFilePathFlag, "l", "", "Leave empty to disable logging") portableCmd.Flags().BoolVarP(&portableLogVerbose, logVerboseFlag, "v", false, "Enable verbose logs") portableCmd.Flags().StringSliceVarP(&portablePublicKeys, "public-key", "k", []string{}, "") portableCmd.Flags().StringSliceVarP(&portablePermissions, "permissions", "g", []string{"list", "download"}, - "User's permissions. \"*\" means any permission") + `User's permissions. "*" means any +permission`) portableCmd.Flags().StringArrayVar(&portableAllowedExtensions, "allowed-extensions", []string{}, - "Allowed file extensions case insensitive. The format is /dir::ext1,ext2. For example: \"/somedir::.jpg,.png\"") + `Allowed file extensions case +insensitive. The format is +/dir::ext1,ext2. +For example: "/somedir::.jpg,.png"`) portableCmd.Flags().StringArrayVar(&portableDeniedExtensions, "denied-extensions", []string{}, - "Denied file extensions case insensitive. The format is /dir::ext1,ext2. For example: \"/somedir::.jpg,.png\"") + `Denied file extensions case +insensitive. The format is +/dir::ext1,ext2. +For example: "/somedir::.jpg,.png"`) portableCmd.Flags().BoolVarP(&portableAdvertiseService, "advertise-service", "S", false, - "Advertise SFTP service using multicast DNS") + `Advertise SFTP service using multicast +DNS`) portableCmd.Flags().BoolVarP(&portableAdvertiseCredentials, "advertise-credentials", "C", false, - "If the SFTP service is advertised via multicast DNS, this flag allows to put username/password inside the advertised TXT record") - portableCmd.Flags().IntVarP(&portableFsProvider, "fs-provider", "f", 0, "0 means local filesystem, 1 Amazon S3 compatible, "+ - "2 Google Cloud Storage") + `If the SFTP service is advertised via +multicast DNS, this flag allows to put +username/password inside the advertised +TXT record`) + portableCmd.Flags().IntVarP(&portableFsProvider, "fs-provider", "f", 0, `0 means local filesystem, +1 Amazon S3 compatible, +2 Google Cloud Storage`) portableCmd.Flags().StringVar(&portableS3Bucket, "s3-bucket", "", "") portableCmd.Flags().StringVar(&portableS3Region, "s3-region", "", "") portableCmd.Flags().StringVar(&portableS3AccessKey, "s3-access-key", "", "") portableCmd.Flags().StringVar(&portableS3AccessSecret, "s3-access-secret", "", "") portableCmd.Flags().StringVar(&portableS3Endpoint, "s3-endpoint", "", "") portableCmd.Flags().StringVar(&portableS3StorageClass, "s3-storage-class", "", "") - portableCmd.Flags().StringVar(&portableS3KeyPrefix, "s3-key-prefix", "", "Allows to restrict access to the virtual folder "+ - "identified by this prefix and its contents") - portableCmd.Flags().IntVar(&portableS3ULPartSize, "s3-upload-part-size", 5, "The buffer size for multipart uploads (MB)") - portableCmd.Flags().IntVar(&portableS3ULConcurrency, "s3-upload-concurrency", 2, "How many parts are uploaded in parallel") + portableCmd.Flags().StringVar(&portableS3KeyPrefix, "s3-key-prefix", "", `Allows to restrict access to the +virtual folder identified by this +prefix and its contents`) + portableCmd.Flags().IntVar(&portableS3ULPartSize, "s3-upload-part-size", 5, `The buffer size for multipart uploads +(MB)`) + portableCmd.Flags().IntVar(&portableS3ULConcurrency, "s3-upload-concurrency", 2, `How many parts are uploaded in +parallel`) portableCmd.Flags().StringVar(&portableGCSBucket, "gcs-bucket", "", "") portableCmd.Flags().StringVar(&portableGCSStorageClass, "gcs-storage-class", "", "") - portableCmd.Flags().StringVar(&portableGCSKeyPrefix, "gcs-key-prefix", "", "Allows to restrict access to the virtual folder "+ - "identified by this prefix and its contents") - portableCmd.Flags().StringVar(&portableGCSCredentialsFile, "gcs-credentials-file", "", "Google Cloud Storage JSON credentials file") - portableCmd.Flags().IntVar(&portableGCSAutoCredentials, "gcs-automatic-credentials", 1, "0 means explicit credentials using a JSON "+ - "credentials file, 1 automatic") + portableCmd.Flags().StringVar(&portableGCSKeyPrefix, "gcs-key-prefix", "", `Allows to restrict access to the +virtual folder identified by this +prefix and its contents`) + portableCmd.Flags().StringVar(&portableGCSCredentialsFile, "gcs-credentials-file", "", `Google Cloud Storage JSON credentials +file`) + portableCmd.Flags().IntVar(&portableGCSAutoCredentials, "gcs-automatic-credentials", 1, `0 means explicit credentials using +a JSON credentials file, 1 automatic +`) rootCmd.AddCommand(portableCmd) } diff --git a/cmd/root.go b/cmd/root.go index ff1d3eaf..55b16d69 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -79,18 +79,29 @@ func addConfigFlags(cmd *cobra.Command) { viper.SetDefault(configDirKey, defaultConfigDir) viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint:errcheck // err is not nil only if the key to bind is missing cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey), - "Location for SFTPGo config dir. This directory should contain the \"sftpgo\" configuration file or the configured "+ - "config-file and it is used as the base for files with a relative path (eg. the private keys for the SFTP server, "+ - "the SQLite database if you use SQLite as data provider). This flag can be set using SFTPGO_CONFIG_DIR env var too.") + `Location for SFTPGo config dir. This directory +should contain the "sftpgo" configuration file +or the configured config-file and it is used as +the base for files with a relative path (eg. the +private keys for the SFTP server, the SQLite +database if you use SQLite as data provider). +This flag can be set using SFTPGO_CONFIG_DIR +env var too.`) viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint:errcheck viper.SetDefault(configFileKey, defaultConfigName) viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint:errcheck cmd.Flags().StringVarP(&configFile, configFileFlag, "f", viper.GetString(configFileKey), - "Name for SFTPGo configuration file. It must be the name of a file stored in config-dir not the absolute path to the "+ - "configuration file. The specified file name must have no extension we automatically load JSON, YAML, TOML, HCL and "+ - "Java properties. Therefore if you set \"sftpgo\" then \"sftpgo.json\", \"sftpgo.yaml\" and so on are searched. "+ - "This flag can be set using SFTPGO_CONFIG_FILE env var too.") + `Name for SFTPGo configuration file. It must be +the name of a file stored in config-dir not the +absolute path to the configuration file. The +specified file name must have no extension we +automatically load JSON, YAML, TOML, HCL and +Java properties. Therefore if you set "sftpgo" +then "sftpgo.json", "sftpgo.yaml" and so on +are searched. +This flag can be set using SFTPGO_CONFIG_FILE +env var too.`) viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint:errcheck } @@ -100,48 +111,65 @@ func addServeFlags(cmd *cobra.Command) { viper.SetDefault(logFilePathKey, defaultLogFile) viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint:errcheck cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey), - "Location for the log file. Leave empty to write logs to the standard output. This flag can be set using SFTPGO_LOG_FILE_PATH "+ - "env var too.") + `Location for the log file. Leave empty to write +logs to the standard output. This flag can be +set using SFTPGO_LOG_FILE_PATH env var too. +`) viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag)) //nolint:errcheck viper.SetDefault(logMaxSizeKey, defaultLogMaxSize) viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE") //nolint:errcheck cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey), - "Maximum size in megabytes of the log file before it gets rotated. This flag can be set using SFTPGO_LOG_MAX_SIZE "+ - "env var too. It is unused if log-file-path is empty.") + `Maximum size in megabytes of the log file +before it gets rotated. This flag can be set +using SFTPGO_LOG_MAX_SIZE env var too. It is +unused if log-file-path is empty. +`) viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag)) //nolint:errcheck viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup) viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS") //nolint:errcheck cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey), - "Maximum number of old log files to retain. This flag can be set using SFTPGO_LOG_MAX_BACKUPS env var too. "+ - "It is unused if log-file-path is empty.") + `Maximum number of old log files to retain. +This flag can be set using SFTPGO_LOG_MAX_BACKUPS +env var too. It is unused if log-file-path is +empty.`) viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag)) //nolint:errcheck viper.SetDefault(logMaxAgeKey, defaultLogMaxAge) viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE") //nolint:errcheck cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey), - "Maximum number of days to retain old log files. This flag can be set using SFTPGO_LOG_MAX_AGE env var too. "+ - "It is unused if log-file-path is empty.") + `Maximum number of days to retain old log files. +This flag can be set using SFTPGO_LOG_MAX_AGE env +var too. It is unused if log-file-path is empty. +`) viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag)) //nolint:errcheck viper.SetDefault(logCompressKey, defaultLogCompress) viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS") //nolint:errcheck - cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), "Determine if the rotated "+ - "log files should be compressed using gzip. This flag can be set using SFTPGO_LOG_COMPRESS env var too. "+ - "It is unused if log-file-path is empty.") + cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), + `Determine if the rotated log files +should be compressed using gzip. This flag can +be set using SFTPGO_LOG_COMPRESS env var too. +It is unused if log-file-path is empty. +`) viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag)) //nolint:errcheck viper.SetDefault(logVerboseKey, defaultLogVerbose) viper.BindEnv(logVerboseKey, "SFTPGO_LOG_VERBOSE") //nolint:errcheck - cmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), "Enable verbose logs. "+ - "This flag can be set using SFTPGO_LOG_VERBOSE env var too.") + cmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), + `Enable verbose logs. This flag can be set +using SFTPGO_LOG_VERBOSE env var too. +`) viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck viper.SetDefault(profilerKey, defaultProfiler) viper.BindEnv(profilerKey, "SFTPGO_PROFILER") //nolint:errcheck - cmd.Flags().BoolVarP(&profiler, profilerFlag, "p", viper.GetBool(profilerKey), "Enable the built-in profiler. "+ - "The profiler will be accessible via HTTP/HTTPS using the base URL \"/debug/pprof/\". "+ - "This flag can be set using SFTPGO_PROFILER env var too.") + cmd.Flags().BoolVarP(&profiler, profilerFlag, "p", viper.GetBool(profilerKey), + `Enable the built-in profiler. The profiler will +be accessible via HTTP/HTTPS using the base URL +"/debug/pprof/". +This flag can be set using SFTPGO_PROFILER env +var too.`) viper.BindPFlag(profilerKey, cmd.Flags().Lookup(profilerFlag)) //nolint:errcheck } diff --git a/cmd/rotatelogs_windows.go b/cmd/rotatelogs_windows.go index 3812808c..7fdbc409 100644 --- a/cmd/rotatelogs_windows.go +++ b/cmd/rotatelogs_windows.go @@ -12,7 +12,7 @@ import ( var ( rotateLogCmd = &cobra.Command{ Use: "rotatelogs", - Short: "Signal to the running service to close the existing log file and immediately create a new one", + Short: "Signal to the running service to rotate the logs", Run: func(cmd *cobra.Command, args []string) { s := service.WindowsService{ Service: service.Service{ diff --git a/cmd/serve.go b/cmd/serve.go index f7858632..14dc6659 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -13,9 +13,10 @@ var ( serveCmd = &cobra.Command{ Use: "serve", Short: "Start the SFTP Server", - Long: `To start the SFTPGo with the default values for the command line flags simply use: + Long: `To start the SFTPGo with the default values for the command line flags simply +use: -sftpgo serve +$ sftpgo serve Please take a look at the usage below to customize the startup options`, Run: func(cmd *cobra.Command, args []string) { diff --git a/cmd/service_windows.go b/cmd/service_windows.go index 05ca98d9..11c12a5b 100644 --- a/cmd/service_windows.go +++ b/cmd/service_windows.go @@ -7,7 +7,7 @@ import ( var ( serviceCmd = &cobra.Command{ Use: "service", - Short: "Install, Uninstall, Start, Stop, Reload and retrieve status for SFTPGo Windows Service", + Short: "Manage SFTPGo Windows Service", } ) diff --git a/docs/portable-mode.md b/docs/portable-mode.md index c9b49ae0..ba111c69 100644 --- a/docs/portable-mode.md +++ b/docs/portable-mode.md @@ -4,9 +4,10 @@ SFTPGo allows to share a single directory on demand using the `portable` subcomm ```console sftpgo portable --help -To serve the current working directory with auto generated credentials simply use: +To serve the current working directory with auto generated credentials simply +use: -sftpgo portable +$ sftpgo portable Please take a look at the usage below to customize the serving parameters @@ -14,35 +15,65 @@ Usage: sftpgo portable [flags] Flags: - -C, --advertise-credentials If the SFTP service is advertised via multicast DNS, this flag allows to put username/password inside the advertised TXT record - -S, --advertise-service Advertise SFTP service using multicast DNS - --allowed-extensions stringArray Allowed file extensions case insensitive. The format is /dir::ext1,ext2. For example: "/somedir::.jpg,.png" - --denied-extensions stringArray Denied file extensions case insensitive. The format is /dir::ext1,ext2. For example: "/somedir::.jpg,.png" - -d, --directory string Path to the directory to serve. This can be an absolute path or a path relative to the current directory (default ".") - -f, --fs-provider int 0 means local filesystem, 1 Amazon S3 compatible, 2 Google Cloud Storage - --gcs-automatic-credentials int 0 means explicit credentials using a JSON credentials file, 1 automatic (default 1) + -C, --advertise-credentials If the SFTP service is advertised via + multicast DNS, this flag allows to put + username/password inside the advertised + TXT record + -S, --advertise-service Advertise SFTP service using multicast + DNS + --allowed-extensions stringArray Allowed file extensions case + insensitive. The format is + /dir::ext1,ext2. + For example: "/somedir::.jpg,.png" + --denied-extensions stringArray Denied file extensions case + insensitive. The format is + /dir::ext1,ext2. + For example: "/somedir::.jpg,.png" + -d, --directory string Path to the directory to serve. + This can be an absolute path or a path + relative to the current directory + (default ".") + -f, --fs-provider int 0 means local filesystem, + 1 Amazon S3 compatible, + 2 Google Cloud Storage + --gcs-automatic-credentials int 0 means explicit credentials using + a JSON credentials file, 1 automatic + (default 1) --gcs-bucket string - --gcs-credentials-file string Google Cloud Storage JSON credentials file - --gcs-key-prefix string Allows to restrict access to the virtual folder identified by this prefix and its contents + --gcs-credentials-file string Google Cloud Storage JSON credentials + file + --gcs-key-prefix string Allows to restrict access to the + virtual folder identified by this + prefix and its contents --gcs-storage-class string -h, --help help for portable -l, --log-file-path string Leave empty to disable logging -v, --log-verbose Enable verbose logs - -p, --password string Leave empty to use an auto generated value - -g, --permissions strings User's permissions. "*" means any permission (default [list,download]) + -p, --password string Leave empty to use an auto generated + value + -g, --permissions strings User's permissions. "*" means any + permission (default [list,download]) -k, --public-key strings --s3-access-key string --s3-access-secret string --s3-bucket string --s3-endpoint string - --s3-key-prefix string Allows to restrict access to the virtual folder identified by this prefix and its contents + --s3-key-prefix string Allows to restrict access to the + virtual folder identified by this + prefix and its contents --s3-region string --s3-storage-class string - --s3-upload-concurrency int How many parts are uploaded in parallel (default 2) - --s3-upload-part-size int The buffer size for multipart uploads (MB) (default 5) - -s, --sftpd-port int 0 means a random non privileged port - -c, --ssh-commands strings SSH commands to enable. "*" means any supported SSH command including scp (default [md5sum,sha1sum,cd,pwd]) - -u, --username string Leave empty to use an auto generated value + --s3-upload-concurrency int How many parts are uploaded in + parallel (default 2) + --s3-upload-part-size int The buffer size for multipart uploads + (MB) (default 5) + -s, --sftpd-port int 0 means a random unprivileged port + -c, --ssh-commands strings SSH commands to enable. + "*" means any supported SSH command + including scp + (default [md5sum,sha1sum,cd,pwd,scp]) + -u, --username string Leave empty to use an auto generated + value ``` In portable mode, SFTPGo can advertise the SFTP service and, optionally, the credentials via multicast DNS, so there is a standard way to discover the service and to automatically connect to it. diff --git a/docs/service.md b/docs/service.md index 5b02b203..a27972e9 100644 --- a/docs/service.md +++ b/docs/service.md @@ -79,7 +79,7 @@ On Windows, you can register SFTPGo as Windows Service. Take a look at the CLI u ```powershell PS> sftpgo.exe service --help -Install, Uninstall, Start, Stop, Reload and retrieve status for SFTPGo Windows Service +Manage SFTPGo Windows Service Usage: sftpgo service [command] @@ -87,7 +87,7 @@ Usage: Available Commands: install Install SFTPGo as Windows Service reload Reload the SFTPGo Windows Service sending a "paramchange" request - rotatelogs Signal to the running service to close the existing log file and immediately create a new one + rotatelogs Signal to the running service to rotate the logs start Start SFTPGo Windows Service status Retrieve the status for the SFTPGo Windows Service stop Stop SFTPGo Windows Service