mirror of
https://github.com/rclone/rclone.git
synced 2024-11-07 09:04:52 +01:00
config: allow config create and friends to take key=value parameters #3455
This commit is contained in:
parent
095cf9e4be
commit
99caf79ffe
@ -108,6 +108,11 @@ var configProvidersCommand = &cobra.Command{
|
|||||||
var updateRemoteOpt config.UpdateRemoteOpt
|
var updateRemoteOpt config.UpdateRemoteOpt
|
||||||
|
|
||||||
var configPasswordHelp = strings.ReplaceAll(`
|
var configPasswordHelp = strings.ReplaceAll(`
|
||||||
|
Note that if the config process would normally ask a question the
|
||||||
|
default is taken (unless |--non-interactive| is used). Each time
|
||||||
|
that happens rclone will print or DEBUG a message saying how to
|
||||||
|
affect the value taken.
|
||||||
|
|
||||||
If any of the parameters passed is a password field, then rclone will
|
If any of the parameters passed is a password field, then rclone will
|
||||||
automatically obscure them if they aren't already obscured before
|
automatically obscure them if they aren't already obscured before
|
||||||
putting them in the config file.
|
putting them in the config file.
|
||||||
@ -170,24 +175,21 @@ with |State| as empty string.
|
|||||||
var configCreateCommand = &cobra.Command{
|
var configCreateCommand = &cobra.Command{
|
||||||
Use: "create `name` `type` [`key` `value`]*",
|
Use: "create `name` `type` [`key` `value`]*",
|
||||||
Short: `Create a new remote with name, type and options.`,
|
Short: `Create a new remote with name, type and options.`,
|
||||||
Long: `
|
Long: strings.ReplaceAll(`
|
||||||
Create a new remote of ` + "`name`" + ` with ` + "`type`" + ` and options. The options
|
Create a new remote of |name| with |type| and options. The options
|
||||||
should be passed in pairs of ` + "`key` `value`" + `.
|
should be passed in pairs of |key| |value| or as |key=value|.
|
||||||
|
|
||||||
For example to make a swift remote of name myremote using auto config
|
For example to make a swift remote of name myremote using auto config
|
||||||
you would do:
|
you would do:
|
||||||
|
|
||||||
rclone config create myremote swift env_auth true
|
rclone config create myremote swift env_auth true
|
||||||
|
rclone config create myremote swift env_auth=true
|
||||||
|
|
||||||
Note that if the config process would normally ask a question the
|
|
||||||
default is taken. Each time that happens rclone will print a message
|
|
||||||
saying how to affect the value taken.
|
|
||||||
` + configPasswordHelp + `
|
|
||||||
So for example if you wanted to configure a Google Drive remote but
|
So for example if you wanted to configure a Google Drive remote but
|
||||||
using remote authorization you would do this:
|
using remote authorization you would do this:
|
||||||
|
|
||||||
rclone config create mydrive drive config_is_local false
|
rclone config create mydrive drive config_is_local=false
|
||||||
`,
|
`, "|", "`") + configPasswordHelp,
|
||||||
RunE: func(command *cobra.Command, args []string) error {
|
RunE: func(command *cobra.Command, args []string) error {
|
||||||
cmd.CheckArgs(2, 256, command, args)
|
cmd.CheckArgs(2, 256, command, args)
|
||||||
in, err := argsToMap(args[2:])
|
in, err := argsToMap(args[2:])
|
||||||
@ -233,22 +235,23 @@ func init() {
|
|||||||
var configUpdateCommand = &cobra.Command{
|
var configUpdateCommand = &cobra.Command{
|
||||||
Use: "update `name` [`key` `value`]+",
|
Use: "update `name` [`key` `value`]+",
|
||||||
Short: `Update options in an existing remote.`,
|
Short: `Update options in an existing remote.`,
|
||||||
Long: `
|
Long: strings.ReplaceAll(`
|
||||||
Update an existing remote's options. The options should be passed in
|
Update an existing remote's options. The options should be passed in
|
||||||
in pairs of ` + "`key` `value`" + `.
|
pairs of |key| |value| or as |key=value|.
|
||||||
|
|
||||||
For example to update the env_auth field of a remote of name myremote
|
For example to update the env_auth field of a remote of name myremote
|
||||||
you would do:
|
you would do:
|
||||||
|
|
||||||
rclone config update myremote swift env_auth true
|
rclone config update myremote env_auth true
|
||||||
` + configPasswordHelp + `
|
rclone config update myremote env_auth=true
|
||||||
|
|
||||||
If the remote uses OAuth the token will be updated, if you don't
|
If the remote uses OAuth the token will be updated, if you don't
|
||||||
require this add an extra parameter thus:
|
require this add an extra parameter thus:
|
||||||
|
|
||||||
rclone config update myremote swift env_auth true config_refresh_token false
|
rclone config update myremote swift env_auth=true config_refresh_token=false
|
||||||
`,
|
`, "|", "`") + configPasswordHelp,
|
||||||
RunE: func(command *cobra.Command, args []string) error {
|
RunE: func(command *cobra.Command, args []string) error {
|
||||||
cmd.CheckArgs(3, 256, command, args)
|
cmd.CheckArgs(1, 256, command, args)
|
||||||
in, err := argsToMap(args[1:])
|
in, err := argsToMap(args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -271,19 +274,21 @@ var configDeleteCommand = &cobra.Command{
|
|||||||
var configPasswordCommand = &cobra.Command{
|
var configPasswordCommand = &cobra.Command{
|
||||||
Use: "password `name` [`key` `value`]+",
|
Use: "password `name` [`key` `value`]+",
|
||||||
Short: `Update password in an existing remote.`,
|
Short: `Update password in an existing remote.`,
|
||||||
Long: `
|
Long: strings.ReplaceAll(`
|
||||||
Update an existing remote's password. The password
|
Update an existing remote's password. The password
|
||||||
should be passed in pairs of ` + "`key` `value`" + `.
|
should be passed in pairs of |key| |password| or as |key=password|.
|
||||||
|
The |password| should be passed in in clear (unobscured).
|
||||||
|
|
||||||
For example to set password of a remote of name myremote you would do:
|
For example to set password of a remote of name myremote you would do:
|
||||||
|
|
||||||
rclone config password myremote fieldname mypassword
|
rclone config password myremote fieldname mypassword
|
||||||
|
rclone config password myremote fieldname=mypassword
|
||||||
|
|
||||||
This command is obsolete now that "config update" and "config create"
|
This command is obsolete now that "config update" and "config create"
|
||||||
both support obscuring passwords directly.
|
both support obscuring passwords directly.
|
||||||
`,
|
`, "|", "`"),
|
||||||
RunE: func(command *cobra.Command, args []string) error {
|
RunE: func(command *cobra.Command, args []string) error {
|
||||||
cmd.CheckArgs(3, 256, command, args)
|
cmd.CheckArgs(1, 256, command, args)
|
||||||
in, err := argsToMap(args[1:])
|
in, err := argsToMap(args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -297,16 +302,24 @@ both support obscuring passwords directly.
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// This takes a list of arguments in key value key value form and
|
// This takes a list of arguments in key value key value form, or
|
||||||
// converts it into a map
|
// key=value key=value form and converts it into a map
|
||||||
func argsToMap(args []string) (out rc.Params, err error) {
|
func argsToMap(args []string) (out rc.Params, err error) {
|
||||||
if len(args)%2 != 0 {
|
|
||||||
return nil, errors.New("found key without value")
|
|
||||||
}
|
|
||||||
out = rc.Params{}
|
out = rc.Params{}
|
||||||
// Set the config
|
for i := 0; i < len(args); i++ {
|
||||||
for i := 0; i < len(args); i += 2 {
|
key := args[i]
|
||||||
out[args[i]] = args[i+1]
|
equals := strings.IndexRune(key, '=')
|
||||||
|
var value string
|
||||||
|
if equals >= 0 {
|
||||||
|
key, value = key[:equals], key[equals+1:]
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
if i >= len(args) {
|
||||||
|
return nil, errors.New("found key without value")
|
||||||
|
}
|
||||||
|
value = args[i]
|
||||||
|
}
|
||||||
|
out[key] = value
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
59
cmd/config/config_test.go
Normal file
59
cmd/config/config_test.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rclone/rclone/fs/rc"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestArgsToMap(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
args []string
|
||||||
|
want rc.Params
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
args: []string{},
|
||||||
|
want: rc.Params{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello", "42"},
|
||||||
|
want: rc.Params{"hello": "42"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello", "42", "bye", "43"},
|
||||||
|
want: rc.Params{"hello": "42", "bye": "43"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello=42", "bye", "43"},
|
||||||
|
want: rc.Params{"hello": "42", "bye": "43"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello", "42", "bye=43"},
|
||||||
|
want: rc.Params{"hello": "42", "bye": "43"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello=42", "bye=43"},
|
||||||
|
want: rc.Params{"hello": "42", "bye": "43"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello", "42", "bye", "43", "unused"},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"hello=42", "bye=43", "unused"},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
what := fmt.Sprintf("args = %#v", test.args)
|
||||||
|
got, err := argsToMap(test.args)
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err, what)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err, what)
|
||||||
|
assert.Equal(t, test.want, got, what)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user