From ce1859cd823dd78fecb9f976a33ba9b69f0beae2 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 4 Jul 2024 10:47:05 +0100 Subject: [PATCH] rc: convert options to new style --- cmd/cmd.go | 4 +- cmd/rcd/rcd.go | 9 ++- fs/rc/config_test.go | 2 +- fs/rc/jobs/job.go | 2 +- fs/rc/jobs/job_test.go | 3 +- fs/rc/rc.go | 126 ++++++++++++++++++++++++-------- fs/rc/rcflags/rcflags.go | 23 +----- fs/rc/rcserver/rcserver.go | 3 +- fs/rc/rcserver/rcserver_test.go | 4 +- fs/rc/webgui/plugins.go | 4 +- fs/rc/webgui/rc_test.go | 3 +- 11 files changed, 113 insertions(+), 70 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 835033ef9..b540bc215 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -32,7 +32,7 @@ import ( "github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/fspath" fslog "github.com/rclone/rclone/fs/log" - "github.com/rclone/rclone/fs/rc/rcflags" + "github.com/rclone/rclone/fs/rc" "github.com/rclone/rclone/fs/rc/rcserver" fssync "github.com/rclone/rclone/fs/sync" "github.com/rclone/rclone/lib/atexit" @@ -423,7 +423,7 @@ func initConfig() { } // Start the remote control server if configured - _, err = rcserver.Start(context.Background(), &rcflags.Opt) + _, err = rcserver.Start(context.Background(), &rc.Opt) if err != nil { log.Fatalf("Failed to start remote control: %v", err) } diff --git a/cmd/rcd/rcd.go b/cmd/rcd/rcd.go index 5d4e1dd0f..1dc875d28 100644 --- a/cmd/rcd/rcd.go +++ b/cmd/rcd/rcd.go @@ -6,6 +6,7 @@ import ( "log" "github.com/rclone/rclone/cmd" + "github.com/rclone/rclone/fs/rc" "github.com/rclone/rclone/fs/rc/rcflags" "github.com/rclone/rclone/fs/rc/rcserver" libhttp "github.com/rclone/rclone/lib/http" @@ -37,17 +38,17 @@ See the [rc documentation](/rc/) for more info on the rc flags. }, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(0, 1, command, args) - if rcflags.Opt.Enabled { + if rc.Opt.Enabled { log.Fatalf("Don't supply --rc flag when using rcd") } // Start the rc - rcflags.Opt.Enabled = true + rc.Opt.Enabled = true if len(args) > 0 { - rcflags.Opt.Files = args[0] + rc.Opt.Files = args[0] } - s, err := rcserver.Start(context.Background(), &rcflags.Opt) + s, err := rcserver.Start(context.Background(), &rc.Opt) if err != nil { log.Fatalf("Failed to start remote control: %v", err) } diff --git a/fs/rc/config_test.go b/fs/rc/config_test.go index b046f24bd..de9c38070 100644 --- a/fs/rc/config_test.go +++ b/fs/rc/config_test.go @@ -77,7 +77,7 @@ func TestOptionsGetMarshal(t *testing.T) { // Add some real options AddOption("main", ci) - AddOption("rc", &DefaultOpt) + AddOption("rc", &Opt) // get them call := Calls.Get("options/get") diff --git a/fs/rc/jobs/job.go b/fs/rc/jobs/job.go index 5523a66d6..2a27e0c8b 100644 --- a/fs/rc/jobs/job.go +++ b/fs/rc/jobs/job.go @@ -130,7 +130,7 @@ var ( func newJobs() *Jobs { return &Jobs{ jobs: map[int64]*Job{}, - opt: &rc.DefaultOpt, + opt: &rc.Opt, } } diff --git a/fs/rc/jobs/job_test.go b/fs/rc/jobs/job_test.go index 6fc4a822c..770843cc8 100644 --- a/fs/rc/jobs/job_test.go +++ b/fs/rc/jobs/job_test.go @@ -11,7 +11,6 @@ import ( "github.com/rclone/rclone/fs/accounting" "github.com/rclone/rclone/fs/filter" "github.com/rclone/rclone/fs/rc" - "github.com/rclone/rclone/fs/rc/rcflags" "github.com/rclone/rclone/fstest/testy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -65,7 +64,7 @@ func TestJobsExpire(t *testing.T) { assert.Equal(t, 1, len(jobs.jobs)) jobs.mu.Lock() job.mu.Lock() - job.EndTime = time.Now().Add(-rcflags.Opt.JobExpireDuration - 60*time.Second) + job.EndTime = time.Now().Add(-rc.Opt.JobExpireDuration - 60*time.Second) assert.Equal(t, true, jobs.expireRunning) job.mu.Unlock() jobs.mu.Unlock() diff --git a/fs/rc/rc.go b/fs/rc/rc.go index ad2b47b52..55287ed6b 100644 --- a/fs/rc/rc.go +++ b/fs/rc/rc.go @@ -13,43 +13,109 @@ import ( _ "net/http/pprof" // install the pprof http handlers "time" + "github.com/rclone/rclone/fs" libhttp "github.com/rclone/rclone/lib/http" ) -// Options contains options for the remote control server -type Options struct { - HTTP libhttp.Config - Auth libhttp.AuthConfig - Template libhttp.TemplateConfig - Enabled bool // set to enable the server - Serve bool // set to serve files from remotes - ServeNoModTime bool // don't read the modification time - Files string // set to enable serving files locally - NoAuth bool // set to disable auth checks on AuthRequired methods - WebUI bool // set to launch the web ui - WebGUIUpdate bool // set to check new update - WebGUIForceUpdate bool // set to force download new update - WebGUINoOpenBrowser bool // set to disable auto opening browser - WebGUIFetchURL string // set the default url for fetching webgui - EnableMetrics bool // set to disable prometheus metrics on /metrics - JobExpireDuration time.Duration - JobExpireInterval time.Duration -} - -// DefaultOpt is the default values used for Options -var DefaultOpt = Options{ - HTTP: libhttp.DefaultCfg(), - Auth: libhttp.DefaultAuthCfg(), - Template: libhttp.DefaultTemplateCfg(), - Enabled: false, - JobExpireDuration: 60 * time.Second, - JobExpireInterval: 10 * time.Second, -} +// OptionsInfo describes the Options in use +var OptionsInfo = fs.Options{{ + Name: "rc", + Default: false, + Help: "Enable the remote control server", + Groups: "RC", +}, { + Name: "rc_files", + Default: "", + Help: "Path to local files to serve on the HTTP server", + Groups: "RC", +}, { + Name: "rc_serve", + Default: false, + Help: "Enable the serving of remote objects", + Groups: "RC", +}, { + Name: "rc_serve_no_modtime", + Default: false, + Help: "Don't read the modification time (can speed things up)", + Groups: "RC", +}, { + Name: "rc_no_auth", + Default: false, + Help: "Don't require auth for certain methods", + Groups: "RC", +}, { + Name: "rc_web_gui", + Default: false, + Help: "Launch WebGUI on localhost", + Groups: "RC", +}, { + Name: "rc_web_gui_update", + Default: false, + Help: "Check and update to latest version of web gui", + Groups: "RC", +}, { + Name: "rc_web_gui_force_update", + Default: false, + Help: "Force update to latest version of web gui", + Groups: "RC", +}, { + Name: "rc_web_gui_no_open_browser", + Default: false, + Help: "Don't open the browser automatically", + Groups: "RC", +}, { + Name: "rc_web_fetch_url", + Default: "https://api.github.com/repos/rclone/rclone-webui-react/releases/latest", + Help: "URL to fetch the releases for webgui", + Groups: "RC", +}, { + Name: "rc_enable_metrics", + Default: false, + Help: "Enable prometheus metrics on /metrics", + Groups: "RC", +}, { + Name: "rc_job_expire_duration", + Default: 60 * time.Second, + Help: "Expire finished async jobs older than this value", + Groups: "RC", +}, { + Name: "rc_job_expire_interval", + Default: 10 * time.Second, + Help: "Interval to check for expired async jobs", + Groups: "RC", +}}. + AddPrefix(libhttp.ConfigInfo, "rc", "RC"). + AddPrefix(libhttp.AuthConfigInfo, "rc", "RC"). + AddPrefix(libhttp.TemplateConfigInfo, "rc", "RC"). + SetDefault("rc_addr", []string{"localhost:5572"}) func init() { - DefaultOpt.HTTP.ListenAddr = []string{"localhost:5572"} + fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "rc", Opt: &Opt, Options: OptionsInfo}) } +// Options contains options for the remote control server +type Options struct { + HTTP libhttp.Config `config:"rc"` + Auth libhttp.AuthConfig `config:"rc"` + Template libhttp.TemplateConfig `config:"rc"` + Enabled bool `config:"rc"` // set to enable the server + Files string `config:"rc_files"` // set to enable serving files locally + Serve bool `config:"rc_serve"` // set to serve files from remotes + ServeNoModTime bool `config:"rc_serve_no_modtime"` // don't read the modification time + NoAuth bool `config:"rc_no_auth"` // set to disable auth checks on AuthRequired methods + WebUI bool `config:"rc_web_gui"` // set to launch the web ui + WebGUIUpdate bool `config:"rc_web_gui_update"` // set to check new update + WebGUIForceUpdate bool `config:"rc_web_gui_force_update"` // set to force download new update + WebGUINoOpenBrowser bool `config:"rc_web_gui_no_open_browser"` // set to disable auto opening browser + WebGUIFetchURL string `config:"rc_web_fetch_url"` // set the default url for fetching webgui + EnableMetrics bool `config:"rc_enable_metrics"` // set to disable prometheus metrics on /metrics + JobExpireDuration time.Duration `config:"rc_job_expire_duration"` + JobExpireInterval time.Duration `config:"rc_job_expire_interval"` +} + +// Opt is the default values used for Options +var Opt Options + // WriteJSON writes JSON in out to w func WriteJSON(w io.Writer, out Params) error { enc := json.NewEncoder(w) diff --git a/fs/rc/rcflags/rcflags.go b/fs/rc/rcflags/rcflags.go index 60c89092b..99108c592 100644 --- a/fs/rc/rcflags/rcflags.go +++ b/fs/rc/rcflags/rcflags.go @@ -10,28 +10,7 @@ import ( // FlagPrefix is the prefix used to uniquely identify command line flags. const FlagPrefix = "rc-" -// Options set by command line flags -var ( - Opt = rc.DefaultOpt -) - // AddFlags adds the remote control flags to the flagSet func AddFlags(flagSet *pflag.FlagSet) { - rc.AddOption("rc", &Opt) - flags.BoolVarP(flagSet, &Opt.Enabled, "rc", "", false, "Enable the remote control server", "RC") - flags.StringVarP(flagSet, &Opt.Files, "rc-files", "", "", "Path to local files to serve on the HTTP server", "RC") - flags.BoolVarP(flagSet, &Opt.Serve, "rc-serve", "", false, "Enable the serving of remote objects", "RC") - flags.BoolVarP(flagSet, &Opt.ServeNoModTime, "rc-serve-no-modtime", "", false, "Don't read the modification time (can speed things up)", "RC") - flags.BoolVarP(flagSet, &Opt.NoAuth, "rc-no-auth", "", false, "Don't require auth for certain methods", "RC") - flags.BoolVarP(flagSet, &Opt.WebUI, "rc-web-gui", "", false, "Launch WebGUI on localhost", "RC") - flags.BoolVarP(flagSet, &Opt.WebGUIUpdate, "rc-web-gui-update", "", false, "Check and update to latest version of web gui", "RC") - flags.BoolVarP(flagSet, &Opt.WebGUIForceUpdate, "rc-web-gui-force-update", "", false, "Force update to latest version of web gui", "RC") - flags.BoolVarP(flagSet, &Opt.WebGUINoOpenBrowser, "rc-web-gui-no-open-browser", "", false, "Don't open the browser automatically", "RC") - flags.StringVarP(flagSet, &Opt.WebGUIFetchURL, "rc-web-fetch-url", "", "https://api.github.com/repos/rclone/rclone-webui-react/releases/latest", "URL to fetch the releases for webgui", "RC") - flags.BoolVarP(flagSet, &Opt.EnableMetrics, "rc-enable-metrics", "", false, "Enable prometheus metrics on /metrics", "RC") - flags.DurationVarP(flagSet, &Opt.JobExpireDuration, "rc-job-expire-duration", "", Opt.JobExpireDuration, "Expire finished async jobs older than this value", "RC") - flags.DurationVarP(flagSet, &Opt.JobExpireInterval, "rc-job-expire-interval", "", Opt.JobExpireInterval, "Interval to check for expired async jobs", "RC") - Opt.HTTP.AddFlagsPrefix(flagSet, FlagPrefix) - Opt.Auth.AddFlagsPrefix(flagSet, FlagPrefix) - Opt.Template.AddFlagsPrefix(flagSet, FlagPrefix) + flags.AddFlagsFromOptions(flagSet, "", rc.OptionsInfo) } diff --git a/fs/rc/rcserver/rcserver.go b/fs/rc/rcserver/rcserver.go index ae355a757..7e20213ab 100644 --- a/fs/rc/rcserver/rcserver.go +++ b/fs/rc/rcserver/rcserver.go @@ -28,7 +28,6 @@ import ( "github.com/rclone/rclone/fs/list" "github.com/rclone/rclone/fs/rc" "github.com/rclone/rclone/fs/rc/jobs" - "github.com/rclone/rclone/fs/rc/rcflags" "github.com/rclone/rclone/fs/rc/webgui" libhttp "github.com/rclone/rclone/lib/http" "github.com/rclone/rclone/lib/http/serve" @@ -101,7 +100,7 @@ func newServer(ctx context.Context, opt *rc.Options, mux *http.ServeMux) (*Serve } else { if opt.Auth.BasicUser == "" && opt.Auth.HtPasswd == "" { opt.Auth.BasicUser = "gui" - fs.Infof(nil, "No username specified. Using default username: %s \n", rcflags.Opt.Auth.BasicUser) + fs.Infof(nil, "No username specified. Using default username: %s \n", rc.Opt.Auth.BasicUser) } if opt.Auth.BasicPass == "" && opt.Auth.HtPasswd == "" { randomPass, err := random.Password(128) diff --git a/fs/rc/rcserver/rcserver_test.go b/fs/rc/rcserver/rcserver_test.go index 66009becd..69fd7eef7 100644 --- a/fs/rc/rcserver/rcserver_test.go +++ b/fs/rc/rcserver/rcserver_test.go @@ -49,7 +49,7 @@ func TestMain(m *testing.M) { // Test the RC server runs and we can do HTTP fetches from it. // We'll do the majority of the testing with the httptest framework func TestRcServer(t *testing.T) { - opt := rc.DefaultOpt + opt := rc.Opt opt.HTTP.ListenAddr = []string{testBindAddress} opt.Template.Path = defaultTestTemplate opt.Enabled = true @@ -170,7 +170,7 @@ func testServer(t *testing.T, tests []testRun, opt *rc.Options) { // return an enabled rc func newTestOpt() rc.Options { - opt := rc.DefaultOpt + opt := rc.Opt opt.Enabled = true opt.HTTP.ListenAddr = []string{testBindAddress} return opt diff --git a/fs/rc/webgui/plugins.go b/fs/rc/webgui/plugins.go index 8784ae465..29bf8c1f7 100644 --- a/fs/rc/webgui/plugins.go +++ b/fs/rc/webgui/plugins.go @@ -16,7 +16,7 @@ import ( "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config" - "github.com/rclone/rclone/fs/rc/rcflags" + "github.com/rclone/rclone/fs/rc" ) // PackageJSON is the structure of package.json of a plugin @@ -83,7 +83,7 @@ func newPlugins(fileName string) *Plugins { } func initPluginsOrError() error { - if !rcflags.Opt.WebUI { + if !rc.Opt.WebUI { return errors.New("WebUI needs to be enabled for plugins to work") } initMutex.Lock() diff --git a/fs/rc/webgui/rc_test.go b/fs/rc/webgui/rc_test.go index ec003d23f..57c5c4a09 100644 --- a/fs/rc/webgui/rc_test.go +++ b/fs/rc/webgui/rc_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/rclone/rclone/fs/rc" - "github.com/rclone/rclone/fs/rc/rcflags" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -18,7 +17,7 @@ const testPluginKey = testPluginAuthor + "/" + testPluginName const testPluginURL = "https://github.com/" + testPluginAuthor + "/" + testPluginName + "/" func init() { - rcflags.Opt.WebUI = true + rc.Opt.WebUI = true } func setCacheDir(t *testing.T) {