github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/rc/config.go (about) 1 // Implement config options reading and writing 2 // 3 // This is done here rather than in fs/fs.go so we don't cause a circular dependency 4 5 package rc 6 7 import ( 8 "context" 9 "fmt" 10 11 "github.com/rclone/rclone/fs" 12 "github.com/rclone/rclone/fs/filter" 13 ) 14 15 var ( 16 optionBlock = map[string]interface{}{} 17 optionReload = map[string]func(context.Context) error{} 18 ) 19 20 // AddOption adds an option set 21 func AddOption(name string, option interface{}) { 22 optionBlock[name] = option 23 } 24 25 // AddOptionReload adds an option set with a reload function to be 26 // called when options are changed 27 func AddOptionReload(name string, option interface{}, reload func(context.Context) error) { 28 optionBlock[name] = option 29 optionReload[name] = reload 30 } 31 32 func init() { 33 Add(Call{ 34 Path: "options/blocks", 35 Fn: rcOptionsBlocks, 36 Title: "List all the option blocks", 37 Help: `Returns: 38 - options - a list of the options block names`, 39 }) 40 } 41 42 // Show the list of all the option blocks 43 func rcOptionsBlocks(ctx context.Context, in Params) (out Params, err error) { 44 options := []string{} 45 for name := range optionBlock { 46 options = append(options, name) 47 } 48 out = make(Params) 49 out["options"] = options 50 return out, nil 51 } 52 53 func init() { 54 Add(Call{ 55 Path: "options/get", 56 Fn: rcOptionsGet, 57 Title: "Get all the global options", 58 Help: `Returns an object where keys are option block names and values are an 59 object with the current option values in. 60 61 Note that these are the global options which are unaffected by use of 62 the _config and _filter parameters. If you wish to read the parameters 63 set in _config then use options/config and for _filter use options/filter. 64 65 This shows the internal names of the option within rclone which should 66 map to the external options very easily with a few exceptions. 67 `, 68 }) 69 } 70 71 // Show the list of all the option blocks 72 func rcOptionsGet(ctx context.Context, in Params) (out Params, err error) { 73 out = make(Params) 74 for name, options := range optionBlock { 75 out[name] = options 76 } 77 return out, nil 78 } 79 80 func init() { 81 Add(Call{ 82 Path: "options/local", 83 Fn: rcOptionsLocal, 84 Title: "Get the currently active config for this call", 85 Help: `Returns an object with the keys "config" and "filter". 86 The "config" key contains the local config and the "filter" key contains 87 the local filters. 88 89 Note that these are the local options specific to this rc call. If 90 _config was not supplied then they will be the global options. 91 Likewise with "_filter". 92 93 This call is mostly useful for seeing if _config and _filter passing 94 is working. 95 96 This shows the internal names of the option within rclone which should 97 map to the external options very easily with a few exceptions. 98 `, 99 }) 100 } 101 102 // Show the current config 103 func rcOptionsLocal(ctx context.Context, in Params) (out Params, err error) { 104 out = make(Params) 105 out["config"] = fs.GetConfig(ctx) 106 out["filter"] = filter.GetConfig(ctx).Opt 107 return out, nil 108 } 109 110 func init() { 111 Add(Call{ 112 Path: "options/set", 113 Fn: rcOptionsSet, 114 Title: "Set an option", 115 Help: `Parameters: 116 117 - option block name containing an object with 118 - key: value 119 120 Repeated as often as required. 121 122 Only supply the options you wish to change. If an option is unknown 123 it will be silently ignored. Not all options will have an effect when 124 changed like this. 125 126 For example: 127 128 This sets DEBUG level logs (-vv) (these can be set by number or string) 129 130 rclone rc options/set --json '{"main": {"LogLevel": "DEBUG"}}' 131 rclone rc options/set --json '{"main": {"LogLevel": 8}}' 132 133 And this sets INFO level logs (-v) 134 135 rclone rc options/set --json '{"main": {"LogLevel": "INFO"}}' 136 137 And this sets NOTICE level logs (normal without -v) 138 139 rclone rc options/set --json '{"main": {"LogLevel": "NOTICE"}}' 140 `, 141 }) 142 } 143 144 // Set an option in an option block 145 func rcOptionsSet(ctx context.Context, in Params) (out Params, err error) { 146 for name, options := range in { 147 current := optionBlock[name] 148 if current == nil { 149 return nil, fmt.Errorf("unknown option block %q", name) 150 } 151 err := Reshape(current, options) 152 if err != nil { 153 return nil, fmt.Errorf("failed to write options from block %q: %w", name, err) 154 } 155 if reload := optionReload[name]; reload != nil { 156 err = reload(ctx) 157 if err != nil { 158 return nil, fmt.Errorf("failed to reload options from block %q: %w", name, err) 159 } 160 } 161 } 162 return out, nil 163 }