Make all config file variables be settable in the environment

These are set in the form RCLONE_CONFIG_remote_option where remote is
the uppercased remote name and option is the uppercased config file
option name.  Note that RCLONE_CONFIG_remote_TYPE must be set if
defining a new remote.

Fixes #616
This commit is contained in:
Nick Craig-Wood 2016-12-20 18:03:09 +00:00
parent 0d75d2585f
commit f73ee5eade
13 changed files with 152 additions and 78 deletions

View File

@ -229,15 +229,15 @@ func NewFs(name, root string) (fs.Fs, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
account := fs.ConfigFile.MustValue(name, "account") account := fs.ConfigFileGet(name, "account")
if account == "" { if account == "" {
return nil, errors.New("account not found") return nil, errors.New("account not found")
} }
key := fs.ConfigFile.MustValue(name, "key") key := fs.ConfigFileGet(name, "key")
if key == "" { if key == "" {
return nil, errors.New("key not found") return nil, errors.New("key not found")
} }
endpoint := fs.ConfigFile.MustValue(name, "endpoint", defaultEndpoint) endpoint := fs.ConfigFileGet(name, "endpoint", defaultEndpoint)
f := &Fs{ f := &Fs{
name: name, name: name,
bucket: bucket, bucket: bucket,

View File

@ -29,7 +29,7 @@ When uses with the -l flag it lists the types too.
`, `,
Run: func(command *cobra.Command, args []string) { Run: func(command *cobra.Command, args []string) {
cmd.CheckArgs(0, 0, command, args) cmd.CheckArgs(0, 0, command, args)
remotes := fs.ConfigFile.GetSectionList() remotes := fs.ConfigFileSections()
sort.Strings(remotes) sort.Strings(remotes)
maxlen := 1 maxlen := 1
for _, remote := range remotes { for _, remote := range remotes {
@ -39,7 +39,7 @@ When uses with the -l flag it lists the types too.
} }
for _, remote := range remotes { for _, remote := range remotes {
if listLong { if listLong {
remoteType := fs.ConfigFile.MustValue(remote, "type", "UNKNOWN") remoteType := fs.ConfigFileGet(remote, "type", "UNKNOWN")
fmt.Printf("%-*s %s\n", maxlen+1, remote+":", remoteType) fmt.Printf("%-*s %s\n", maxlen+1, remote+":", remoteType)
} else { } else {
fmt.Printf("%s:\n", remote) fmt.Printf("%s:\n", remote)

View File

@ -48,11 +48,11 @@ func init() {
// NewFs contstructs an Fs from the path, container:path // NewFs contstructs an Fs from the path, container:path
func NewFs(name, rpath string) (fs.Fs, error) { func NewFs(name, rpath string) (fs.Fs, error) {
mode, err := NewNameEncryptionMode(fs.ConfigFile.MustValue(name, "filename_encryption", "standard")) mode, err := NewNameEncryptionMode(fs.ConfigFileGet(name, "filename_encryption", "standard"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
password := fs.ConfigFile.MustValue(name, "password", "") password := fs.ConfigFileGet(name, "password", "")
if password == "" { if password == "" {
return nil, errors.New("password not set in config file") return nil, errors.New("password not set in config file")
} }
@ -60,7 +60,7 @@ func NewFs(name, rpath string) (fs.Fs, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to decrypt password") return nil, errors.Wrap(err, "failed to decrypt password")
} }
salt := fs.ConfigFile.MustValue(name, "password2", "") salt := fs.ConfigFileGet(name, "password2", "")
if salt != "" { if salt != "" {
salt, err = fs.Reveal(salt) salt, err = fs.Reveal(salt)
if err != nil { if err != nil {
@ -71,7 +71,7 @@ func NewFs(name, rpath string) (fs.Fs, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to make cipher") return nil, errors.Wrap(err, "failed to make cipher")
} }
remote := fs.ConfigFile.MustValue(name, "remote") remote := fs.ConfigFileGet(name, "remote")
if strings.HasPrefix(remote, name+":") { if strings.HasPrefix(remote, name+":") {
return nil, errors.New("can't point crypt remote at itself - check the value of the remote setting") return nil, errors.New("can't point crypt remote at itself - check the value of the remote setting")
} }

View File

@ -63,7 +63,7 @@ func init() {
// Configuration helper - called after the user has put in the defaults // Configuration helper - called after the user has put in the defaults
func configHelper(name string) { func configHelper(name string) {
// See if already have a token // See if already have a token
token := fs.ConfigFile.MustValue(name, "token") token := fs.ConfigFileGet(name, "token")
if token != "" { if token != "" {
fmt.Printf("Already have a dropbox token - refresh?\n") fmt.Printf("Already have a dropbox token - refresh?\n")
if !fs.Confirm() { if !fs.Confirm() {
@ -86,9 +86,9 @@ func configHelper(name string) {
token = db.AccessToken() token = db.AccessToken()
// Stuff it in the config file if it has changed // Stuff it in the config file if it has changed
old := fs.ConfigFile.MustValue(name, "token") old := fs.ConfigFileGet(name, "token")
if token != old { if token != old {
fs.ConfigFile.SetValue(name, "token", token) fs.ConfigFileSet(name, "token", token)
fs.SaveConfig() fs.SaveConfig()
} }
} }
@ -133,11 +133,11 @@ func (f *Fs) String() string {
func newDropbox(name string) (*dropbox.Dropbox, error) { func newDropbox(name string) (*dropbox.Dropbox, error) {
db := dropbox.NewDropbox() db := dropbox.NewDropbox()
appKey := fs.ConfigFile.MustValue(name, "app_key") appKey := fs.ConfigFileGet(name, "app_key")
if appKey == "" { if appKey == "" {
appKey = rcloneAppKey appKey = rcloneAppKey
} }
appSecret := fs.ConfigFile.MustValue(name, "app_secret") appSecret := fs.ConfigFileGet(name, "app_secret")
if appSecret == "" { if appSecret == "" {
appSecret = fs.MustReveal(rcloneEncryptedAppSecret) appSecret = fs.MustReveal(rcloneEncryptedAppSecret)
} }
@ -162,7 +162,7 @@ func NewFs(name, root string) (fs.Fs, error) {
f.setRoot(root) f.setRoot(root)
// Read the token from the config file // Read the token from the config file
token := fs.ConfigFile.MustValue(name, "token") token := fs.ConfigFileGet(name, "token")
// Set our custom context which enables our custom transport for timeouts etc // Set our custom context which enables our custom transport for timeouts etc
db.SetContext(oauthutil.Context()) db.SetContext(oauthutil.Context())

View File

@ -17,6 +17,7 @@ import (
"os" "os"
"os/user" "os/user"
"path" "path"
"regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -47,8 +48,8 @@ const (
// Global // Global
var ( var (
// ConfigFile is the config file data structure // configData is the config file data structure
ConfigFile *goconfig.ConfigFile configData *goconfig.ConfigFile
// HomeDir is the home directory of the user // HomeDir is the home directory of the user
HomeDir = configHome() HomeDir = configHome()
// ConfigPath points to the config file // ConfigPath points to the config file
@ -284,10 +285,10 @@ func LoadConfig() {
// Load configuration file. // Load configuration file.
var err error var err error
ConfigFile, err = loadConfigFile() configData, err = loadConfigFile()
if err == errorConfigFileNotFound { if err == errorConfigFileNotFound {
Log(nil, "Config file %q not found - using defaults", ConfigPath) Log(nil, "Config file %q not found - using defaults", ConfigPath)
ConfigFile, _ = goconfig.LoadFromReader(&bytes.Buffer{}) configData, _ = goconfig.LoadFromReader(&bytes.Buffer{})
} else if err != nil { } else if err != nil {
log.Fatalf("Failed to load config file %q: %v", ConfigPath, err) log.Fatalf("Failed to load config file %q: %v", ConfigPath, err)
} }
@ -483,7 +484,7 @@ func changeConfigPassword() {
// if configKey has been set, the file will be encrypted. // if configKey has been set, the file will be encrypted.
func SaveConfig() { func SaveConfig() {
if len(configKey) == 0 { if len(configKey) == 0 {
err := goconfig.SaveConfigFile(ConfigFile, ConfigPath) err := goconfig.SaveConfigFile(configData, ConfigPath)
if err != nil { if err != nil {
log.Fatalf("Failed to save config file: %v", err) log.Fatalf("Failed to save config file: %v", err)
} }
@ -494,7 +495,7 @@ func SaveConfig() {
return return
} }
var buf bytes.Buffer var buf bytes.Buffer
err := goconfig.SaveConfigData(ConfigFile, &buf) err := goconfig.SaveConfigData(configData, &buf)
if err != nil { if err != nil {
log.Fatalf("Failed to save config file: %v", err) log.Fatalf("Failed to save config file: %v", err)
} }
@ -545,7 +546,7 @@ func SaveConfig() {
// disk first and overwrites the given value only. // disk first and overwrites the given value only.
func ConfigSetValueAndSave(name, key, value string) (err error) { func ConfigSetValueAndSave(name, key, value string) (err error) {
// Set the value in config in case we fail to reload it // Set the value in config in case we fail to reload it
ConfigFile.SetValue(name, key, value) configData.SetValue(name, key, value)
// Reload the config file // Reload the config file
reloadedConfigFile, err := loadConfigFile() reloadedConfigFile, err := loadConfigFile()
if err == errorConfigFileNotFound { if err == errorConfigFileNotFound {
@ -560,7 +561,7 @@ func ConfigSetValueAndSave(name, key, value string) (err error) {
return err return err
} }
// Update the config file with the reloaded version // Update the config file with the reloaded version
ConfigFile = reloadedConfigFile configData = reloadedConfigFile
// Set the value in the reloaded version // Set the value in the reloaded version
reloadedConfigFile.SetValue(name, key, value) reloadedConfigFile.SetValue(name, key, value)
// Save it again // Save it again
@ -570,7 +571,7 @@ func ConfigSetValueAndSave(name, key, value string) (err error) {
// ShowRemotes shows an overview of the config file // ShowRemotes shows an overview of the config file
func ShowRemotes() { func ShowRemotes() {
remotes := ConfigFile.GetSectionList() remotes := configData.GetSectionList()
if len(remotes) == 0 { if len(remotes) == 0 {
return return
} }
@ -578,13 +579,13 @@ func ShowRemotes() {
fmt.Printf("%-20s %s\n", "Name", "Type") fmt.Printf("%-20s %s\n", "Name", "Type")
fmt.Printf("%-20s %s\n", "====", "====") fmt.Printf("%-20s %s\n", "====", "====")
for _, remote := range remotes { for _, remote := range remotes {
fmt.Printf("%-20s %s\n", remote, ConfigFile.MustValue(remote, "type")) fmt.Printf("%-20s %s\n", remote, ConfigFileGet(remote, "type"))
} }
} }
// ChooseRemote chooses a remote name // ChooseRemote chooses a remote name
func ChooseRemote() string { func ChooseRemote() string {
remotes := ConfigFile.GetSectionList() remotes := configData.GetSectionList()
sort.Strings(remotes) sort.Strings(remotes)
return Choose("remote", remotes, nil, false) return Choose("remote", remotes, nil, false)
} }
@ -703,7 +704,7 @@ func ShowRemote(name string) {
fmt.Printf("--------------------\n") fmt.Printf("--------------------\n")
fmt.Printf("[%s]\n", name) fmt.Printf("[%s]\n", name)
fs := MustFindByName(name) fs := MustFindByName(name)
for _, key := range ConfigFile.GetKeyList(name) { for _, key := range configData.GetKeyList(name) {
isPassword := false isPassword := false
for _, option := range fs.Options { for _, option := range fs.Options {
if option.Name == key && option.IsPassword { if option.Name == key && option.IsPassword {
@ -711,7 +712,7 @@ func ShowRemote(name string) {
break break
} }
} }
value := ConfigFile.MustValue(name, key) value := ConfigFileGet(name, key)
if isPassword && value != "" { if isPassword && value != "" {
fmt.Printf("%s = *** ENCRYPTED ***\n", key) fmt.Printf("%s = *** ENCRYPTED ***\n", key)
} else { } else {
@ -730,7 +731,7 @@ func OkRemote(name string) bool {
case 'e': case 'e':
return false return false
case 'd': case 'd':
ConfigFile.DeleteSection(name) configData.DeleteSection(name)
return true return true
default: default:
ErrorLog(nil, "Bad choice %c", i) ErrorLog(nil, "Bad choice %c", i)
@ -741,7 +742,7 @@ func OkRemote(name string) bool {
// MustFindByName finds the RegInfo for the remote name passed in or // MustFindByName finds the RegInfo for the remote name passed in or
// exits with a fatal error. // exits with a fatal error.
func MustFindByName(name string) *RegInfo { func MustFindByName(name string) *RegInfo {
fsType := ConfigFile.MustValue(name, "type") fsType := ConfigFileGet(name, "type")
if fsType == "" { if fsType == "" {
log.Fatalf("Couldn't find type of fs for %q", name) log.Fatalf("Couldn't find type of fs for %q", name)
} }
@ -829,10 +830,10 @@ func fsOption() *Option {
// NewRemote make a new remote from its name // NewRemote make a new remote from its name
func NewRemote(name string) { func NewRemote(name string) {
newType := ChooseOption(fsOption()) newType := ChooseOption(fsOption())
ConfigFile.SetValue(name, "type", newType) configData.SetValue(name, "type", newType)
fs := MustFind(newType) fs := MustFind(newType)
for _, option := range fs.Options { for _, option := range fs.Options {
ConfigFile.SetValue(name, option.Name, ChooseOption(&option)) configData.SetValue(name, option.Name, ChooseOption(&option))
} }
RemoteConfig(name) RemoteConfig(name)
if OkRemote(name) { if OkRemote(name) {
@ -849,12 +850,12 @@ func EditRemote(fs *RegInfo, name string) {
for { for {
for _, option := range fs.Options { for _, option := range fs.Options {
key := option.Name key := option.Name
value := ConfigFile.MustValue(name, key) value := ConfigFileGet(name, key)
fmt.Printf("Value %q = %q\n", key, value) fmt.Printf("Value %q = %q\n", key, value)
fmt.Printf("Edit? (y/n)>\n") fmt.Printf("Edit? (y/n)>\n")
if Confirm() { if Confirm() {
newValue := ChooseOption(&option) newValue := ChooseOption(&option)
ConfigFile.SetValue(name, key, newValue) configData.SetValue(name, key, newValue)
} }
} }
RemoteConfig(name) RemoteConfig(name)
@ -867,14 +868,14 @@ func EditRemote(fs *RegInfo, name string) {
// DeleteRemote gets the user to delete a remote // DeleteRemote gets the user to delete a remote
func DeleteRemote(name string) { func DeleteRemote(name string) {
ConfigFile.DeleteSection(name) configData.DeleteSection(name)
SaveConfig() SaveConfig()
} }
// EditConfig edits the config file interactively // EditConfig edits the config file interactively
func EditConfig() { func EditConfig() {
for { for {
haveRemotes := len(ConfigFile.GetSectionList()) != 0 haveRemotes := len(configData.GetSectionList()) != 0
what := []string{"eEdit existing remote", "nNew remote", "dDelete remote", "sSet configuration password", "qQuit config"} what := []string{"eEdit existing remote", "nNew remote", "dDelete remote", "sSet configuration password", "qQuit config"}
if haveRemotes { if haveRemotes {
fmt.Printf("Current remotes:\n\n") fmt.Printf("Current remotes:\n\n")
@ -981,10 +982,87 @@ func Authorize(args []string) {
defer DeleteRemote(name) defer DeleteRemote(name)
// Indicate that we want fully automatic configuration. // Indicate that we want fully automatic configuration.
ConfigFile.SetValue(name, ConfigAutomatic, "yes") configData.SetValue(name, ConfigAutomatic, "yes")
if len(args) == 3 { if len(args) == 3 {
ConfigFile.SetValue(name, ConfigClientID, args[1]) configData.SetValue(name, ConfigClientID, args[1])
ConfigFile.SetValue(name, ConfigClientSecret, args[2]) configData.SetValue(name, ConfigClientSecret, args[2])
} }
fs.Config(name) fs.Config(name)
} }
// configToEnv converts an config section and name, eg ("myremote",
// "ignore-size") into an environment name
// "RCLONE_CONFIG_MYREMOTE_IGNORE_SIZE"
func configToEnv(section, name string) string {
return "RCLONE_CONFIG_" + strings.ToUpper(strings.Replace(section+"_"+name, "-", "_", -1))
}
// ConfigFileGet gets the config key under section returning the
// default or empty string if not set.
//
// It looks up defaults in the environment if they are present
func ConfigFileGet(section, key string, defaultVal ...string) string {
envKey := configToEnv(section, key)
newValue, found := os.LookupEnv(envKey)
if found {
defaultVal = []string{newValue}
}
return configData.MustValue(section, key, defaultVal...)
}
// ConfigFileGetBool gets the config key under section returning the
// default or false if not set.
//
// It looks up defaults in the environment if they are present
func ConfigFileGetBool(section, key string, defaultVal ...bool) bool {
envKey := configToEnv(section, key)
newValue, found := os.LookupEnv(envKey)
if found {
newBool, err := strconv.ParseBool(newValue)
if err != nil {
ErrorLog(nil, "Couldn't parse %q into bool - ignoring: %v", envKey, err)
} else {
defaultVal = []bool{newBool}
}
}
return configData.MustBool(section, key, defaultVal...)
}
// ConfigFileGetInt gets the config key under section returning the
// default or 0 if not set.
//
// It looks up defaults in the environment if they are present
func ConfigFileGetInt(section, key string, defaultVal ...int) int {
envKey := configToEnv(section, key)
newValue, found := os.LookupEnv(envKey)
if found {
newInt, err := strconv.Atoi(newValue)
if err != nil {
ErrorLog(nil, "Couldn't parse %q into int - ignoring: %v", envKey, err)
} else {
defaultVal = []int{newInt}
}
}
return configData.MustInt(section, key, defaultVal...)
}
// ConfigFileSet sets the key in section to value. It doesn't save
// the config file.
func ConfigFileSet(section, key, value string) {
configData.SetValue(section, key, value)
}
var matchEnv = regexp.MustCompile(`^RCLONE_CONFIG_(.*?)_TYPE=.*$`)
// ConfigFileSections returns the sections in the config file
// including any defined by environment variables.
func ConfigFileSections() []string {
sections := configData.GetSectionList()
for _, item := range os.Environ() {
matches := matchEnv.FindStringSubmatch(item)
if len(matches) == 2 {
sections = append(sections, strings.ToLower(matches[1]))
}
}
return sections
}

View File

@ -430,9 +430,8 @@ func ParseRemote(path string) (fsInfo *RegInfo, configName, fsPath string, err e
fsName, configName, fsPath = "local", "local", path fsName, configName, fsPath = "local", "local", path
if parts != nil && !isDriveLetter(parts[1]) { if parts != nil && !isDriveLetter(parts[1]) {
configName, fsPath = parts[1], parts[2] configName, fsPath = parts[1], parts[2]
var err error fsName = ConfigFileGet(configName, "type")
fsName, err = ConfigFile.GetValue(configName, "type") if fsName == "" {
if err != nil {
return nil, "", "", ErrorNotFoundInConfigFile return nil, "", "", ErrorNotFoundInConfigFile
} }
} }

View File

@ -71,7 +71,7 @@ func TestInit(t *testing.T) {
fs.LoadConfig() fs.LoadConfig()
// Set extra config if supplied // Set extra config if supplied
for _, item := range ExtraConfig { for _, item := range ExtraConfig {
fs.ConfigFile.SetValue(item.Name, item.Key, item.Value) fs.ConfigFileSet(item.Name, item.Key, item.Value)
} }
fs.Config.Verbose = *verbose fs.Config.Verbose = *verbose
fs.Config.Quiet = !*verbose fs.Config.Quiet = !*verbose

View File

@ -62,7 +62,7 @@ func init() {
Description: "Google Cloud Storage (this is not Google Drive)", Description: "Google Cloud Storage (this is not Google Drive)",
NewFs: NewFs, NewFs: NewFs,
Config: func(name string) { Config: func(name string) {
if fs.ConfigFile.MustValue(name, "service_account_file") != "" { if fs.ConfigFileGet(name, "service_account_file") != "" {
return return
} }
err := oauthutil.Config("google cloud storage", name, storageConfig) err := oauthutil.Config("google cloud storage", name, storageConfig)
@ -208,7 +208,7 @@ func NewFs(name, root string) (fs.Fs, error) {
var oAuthClient *http.Client var oAuthClient *http.Client
var err error var err error
serviceAccountPath := fs.ConfigFile.MustValue(name, "service_account_file") serviceAccountPath := fs.ConfigFileGet(name, "service_account_file")
if serviceAccountPath != "" { if serviceAccountPath != "" {
oAuthClient, err = getServiceAccountClient(serviceAccountPath) oAuthClient, err = getServiceAccountClient(serviceAccountPath)
if err != nil { if err != nil {
@ -230,9 +230,9 @@ func NewFs(name, root string) (fs.Fs, error) {
name: name, name: name,
bucket: bucket, bucket: bucket,
root: directory, root: directory,
projectNumber: fs.ConfigFile.MustValue(name, "project_number"), projectNumber: fs.ConfigFileGet(name, "project_number"),
objectACL: fs.ConfigFile.MustValue(name, "object_acl"), objectACL: fs.ConfigFileGet(name, "object_acl"),
bucketACL: fs.ConfigFile.MustValue(name, "bucket_acl"), bucketACL: fs.ConfigFileGet(name, "bucket_acl"),
} }
if f.objectACL == "" { if f.objectACL == "" {
f.objectACL = "private" f.objectACL = "private"

View File

@ -70,7 +70,7 @@ type Object struct {
func NewFs(name, root string) (fs.Fs, error) { func NewFs(name, root string) (fs.Fs, error) {
var err error var err error
nounc, _ := fs.ConfigFile.GetValue(name, "nounc") nounc := fs.ConfigFileGet(name, "nounc")
f := &Fs{ f := &Fs{
name: name, name: name,
warned: make(map[string]struct{}), warned: make(map[string]struct{}),

View File

@ -54,15 +54,12 @@ type oldToken struct {
// getToken returns the token saved in the config file under // getToken returns the token saved in the config file under
// section name. // section name.
func getToken(name string) (*oauth2.Token, error) { func getToken(name string) (*oauth2.Token, error) {
tokenString, err := fs.ConfigFile.GetValue(string(name), fs.ConfigToken) tokenString := fs.ConfigFileGet(name, fs.ConfigToken)
if err != nil {
return nil, err
}
if tokenString == "" { if tokenString == "" {
return nil, errors.New("empty token found - please run rclone config again") return nil, errors.New("empty token found - please run rclone config again")
} }
token := new(oauth2.Token) token := new(oauth2.Token)
err = json.Unmarshal([]byte(tokenString), token) err := json.Unmarshal([]byte(tokenString), token)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -97,7 +94,7 @@ func putToken(name string, token *oauth2.Token) error {
return err return err
} }
tokenString := string(tokenBytes) tokenString := string(tokenBytes)
old := fs.ConfigFile.MustValue(name, fs.ConfigToken) old := fs.ConfigFileGet(name, fs.ConfigToken)
if tokenString != old { if tokenString != old {
err = fs.ConfigSetValueAndSave(name, fs.ConfigToken, tokenString) err = fs.ConfigSetValueAndSave(name, fs.ConfigToken, tokenString)
if err != nil { if err != nil {
@ -199,12 +196,12 @@ func Context() context.Context {
// If any value is overridden, true is returned. // If any value is overridden, true is returned.
func overrideCredentials(name string, config *oauth2.Config) bool { func overrideCredentials(name string, config *oauth2.Config) bool {
changed := false changed := false
ClientID := fs.ConfigFile.MustValue(name, fs.ConfigClientID) ClientID := fs.ConfigFileGet(name, fs.ConfigClientID)
if ClientID != "" { if ClientID != "" {
config.ClientID = ClientID config.ClientID = ClientID
changed = true changed = true
} }
ClientSecret := fs.ConfigFile.MustValue(name, fs.ConfigClientSecret) ClientSecret := fs.ConfigFileGet(name, fs.ConfigClientSecret)
if ClientSecret != "" { if ClientSecret != "" {
config.ClientSecret = ClientSecret config.ClientSecret = ClientSecret
changed = true changed = true
@ -241,10 +238,10 @@ func NewClient(name string, config *oauth2.Config) (*http.Client, *TokenSource,
// It may run an internal webserver to receive the results // It may run an internal webserver to receive the results
func Config(id, name string, config *oauth2.Config) error { func Config(id, name string, config *oauth2.Config) error {
changed := overrideCredentials(name, config) changed := overrideCredentials(name, config)
automatic := fs.ConfigFile.MustValue(name, fs.ConfigAutomatic) != "" automatic := fs.ConfigFileGet(name, fs.ConfigAutomatic) != ""
// See if already have a token // See if already have a token
tokenString := fs.ConfigFile.MustValue(name, "token") tokenString := fs.ConfigFileGet(name, "token")
if tokenString != "" { if tokenString != "" {
fmt.Printf("Already have a token - refresh?\n") fmt.Printf("Already have a token - refresh?\n")
if !fs.Confirm() { if !fs.Confirm() {

View File

@ -283,8 +283,8 @@ func s3ParsePath(path string) (bucket, directory string, err error) {
func s3Connection(name string) (*s3.S3, *session.Session, error) { func s3Connection(name string) (*s3.S3, *session.Session, error) {
// Make the auth // Make the auth
v := credentials.Value{ v := credentials.Value{
AccessKeyID: fs.ConfigFile.MustValue(name, "access_key_id"), AccessKeyID: fs.ConfigFileGet(name, "access_key_id"),
SecretAccessKey: fs.ConfigFile.MustValue(name, "secret_access_key"), SecretAccessKey: fs.ConfigFileGet(name, "secret_access_key"),
} }
// first provider to supply a credential set "wins" // first provider to supply a credential set "wins"
@ -307,7 +307,7 @@ func s3Connection(name string) (*s3.S3, *session.Session, error) {
cred := credentials.NewChainCredentials(providers) cred := credentials.NewChainCredentials(providers)
switch { switch {
case fs.ConfigFile.MustBool(name, "env_auth", false): case fs.ConfigFileGetBool(name, "env_auth", false):
// No need for empty checks if "env_auth" is true // No need for empty checks if "env_auth" is true
case v.AccessKeyID == "" && v.SecretAccessKey == "": case v.AccessKeyID == "" && v.SecretAccessKey == "":
// if no access key/secret and iam is explicitly disabled then fall back to anon interaction // if no access key/secret and iam is explicitly disabled then fall back to anon interaction
@ -318,8 +318,8 @@ func s3Connection(name string) (*s3.S3, *session.Session, error) {
return nil, nil, errors.New("secret_access_key not found") return nil, nil, errors.New("secret_access_key not found")
} }
endpoint := fs.ConfigFile.MustValue(name, "endpoint") endpoint := fs.ConfigFileGet(name, "endpoint")
region := fs.ConfigFile.MustValue(name, "region") region := fs.ConfigFileGet(name, "region")
if region == "" && endpoint == "" { if region == "" && endpoint == "" {
endpoint = "https://s3.amazonaws.com/" endpoint = "https://s3.amazonaws.com/"
} }
@ -367,11 +367,11 @@ func NewFs(name, root string) (fs.Fs, error) {
c: c, c: c,
bucket: bucket, bucket: bucket,
ses: ses, ses: ses,
acl: fs.ConfigFile.MustValue(name, "acl"), acl: fs.ConfigFileGet(name, "acl"),
root: directory, root: directory,
locationConstraint: fs.ConfigFile.MustValue(name, "location_constraint"), locationConstraint: fs.ConfigFileGet(name, "location_constraint"),
sse: fs.ConfigFile.MustValue(name, "server_side_encryption"), sse: fs.ConfigFileGet(name, "server_side_encryption"),
storageClass: fs.ConfigFile.MustValue(name, "storage_class"), storageClass: fs.ConfigFileGet(name, "storage_class"),
} }
if *s3ACL != "" { if *s3ACL != "" {
f.acl = *s3ACL f.acl = *s3ACL

View File

@ -144,15 +144,15 @@ func parsePath(path string) (container, directory string, err error) {
// swiftConnection makes a connection to swift // swiftConnection makes a connection to swift
func swiftConnection(name string) (*swift.Connection, error) { func swiftConnection(name string) (*swift.Connection, error) {
userName := fs.ConfigFile.MustValue(name, "user") userName := fs.ConfigFileGet(name, "user")
if userName == "" { if userName == "" {
return nil, errors.New("user not found") return nil, errors.New("user not found")
} }
apiKey := fs.ConfigFile.MustValue(name, "key") apiKey := fs.ConfigFileGet(name, "key")
if apiKey == "" { if apiKey == "" {
return nil, errors.New("key not found") return nil, errors.New("key not found")
} }
authURL := fs.ConfigFile.MustValue(name, "auth") authURL := fs.ConfigFileGet(name, "auth")
if authURL == "" { if authURL == "" {
return nil, errors.New("auth not found") return nil, errors.New("auth not found")
} }
@ -160,11 +160,11 @@ func swiftConnection(name string) (*swift.Connection, error) {
UserName: userName, UserName: userName,
ApiKey: apiKey, ApiKey: apiKey,
AuthUrl: authURL, AuthUrl: authURL,
AuthVersion: fs.ConfigFile.MustInt(name, "auth_version", 0), AuthVersion: fs.ConfigFileGetInt(name, "auth_version", 0),
Tenant: fs.ConfigFile.MustValue(name, "tenant"), Tenant: fs.ConfigFileGet(name, "tenant"),
Region: fs.ConfigFile.MustValue(name, "region"), Region: fs.ConfigFileGet(name, "region"),
Domain: fs.ConfigFile.MustValue(name, "domain"), Domain: fs.ConfigFileGet(name, "domain"),
TenantDomain: fs.ConfigFile.MustValue(name, "tenant_domain"), TenantDomain: fs.ConfigFileGet(name, "tenant_domain"),
ConnectTimeout: 10 * fs.Config.ConnectTimeout, // Use the timeouts in the transport ConnectTimeout: 10 * fs.Config.ConnectTimeout, // Use the timeouts in the transport
Timeout: 10 * fs.Config.Timeout, // Use the timeouts in the transport Timeout: 10 * fs.Config.Timeout, // Use the timeouts in the transport
Transport: fs.Config.Transport(), Transport: fs.Config.Transport(),
@ -191,7 +191,7 @@ func NewFsWithConnection(name, root string, c *swift.Connection) (fs.Fs, error)
root: directory, root: directory,
} }
// StorageURL overloading // StorageURL overloading
storageURL := fs.ConfigFile.MustValue(name, "storage_url") storageURL := fs.ConfigFileGet(name, "storage_url")
if storageURL != "" { if storageURL != "" {
f.c.StorageUrl = storageURL f.c.StorageUrl = storageURL
f.c.Auth = newAuth(f.c.Auth, storageURL) f.c.Auth = newAuth(f.c.Auth, storageURL)

View File

@ -101,7 +101,7 @@ func (f *Fs) String() string {
// read access token from ConfigFile string // read access token from ConfigFile string
func getAccessToken(name string) (*oauth2.Token, error) { func getAccessToken(name string) (*oauth2.Token, error) {
// Read the token from the config file // Read the token from the config file
tokenConfig := fs.ConfigFile.MustValue(name, "token") tokenConfig := fs.ConfigFileGet(name, "token")
//Get access token from config string //Get access token from config string
decoder := json.NewDecoder(strings.NewReader(tokenConfig)) decoder := json.NewDecoder(strings.NewReader(tokenConfig))
var result *oauth2.Token var result *oauth2.Token