cmd/syncthing: Don't fail early on api setup error (fixes 7558) (#7591)

* cmd/syncthing: Don't fail early on api setup error (fixes 7558)

* switch to factory pattern

* refactor config command to show help on nothing

* wip

* wip

* already abort in before
This commit is contained in:
Simon Frei
2021-04-25 20:48:17 +01:00
committed by GitHub
parent 54e27f551d
commit ef4b8a2cf8
6 changed files with 185 additions and 103 deletions
+9 -85
View File
@@ -8,14 +8,10 @@ package cli
import (
"bufio"
"crypto/tls"
"encoding/json"
"io/ioutil"
"os"
"reflect"
"strings"
"github.com/AudriusButkevicius/recli"
"github.com/alecthomas/kong"
"github.com/flynn-archive/go-shlex"
"github.com/mattn/go-isatty"
@@ -24,9 +20,6 @@ import (
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/protocol"
)
type preCli struct {
@@ -51,68 +44,16 @@ func Run() error {
if err != nil {
return errors.Wrap(err, "Command line options:")
}
guiCfg := config.GUIConfiguration{
RawAddress: c.GUIAddress,
APIKey: c.GUIAPIKey,
clientFactory := &apiClientFactory{
cfg: config.GUIConfiguration{
RawAddress: c.GUIAddress,
APIKey: c.GUIAPIKey,
},
}
// Now if the API key and address is not provided (we are not connecting to a remote instance),
// try to rip it out of the config.
if guiCfg.RawAddress == "" && guiCfg.APIKey == "" {
// Load the certs and get the ID
cert, err := tls.LoadX509KeyPair(
locations.Get(locations.CertFile),
locations.Get(locations.KeyFile),
)
if err != nil {
return errors.Wrap(err, "reading device ID")
}
myID := protocol.NewDeviceID(cert.Certificate[0])
// Load the config
cfg, _, err := config.Load(locations.Get(locations.ConfigFile), myID, events.NoopLogger)
if err != nil {
return errors.Wrap(err, "loading config")
}
guiCfg = cfg.GUI()
} else if guiCfg.Address() == "" || guiCfg.APIKey == "" {
return errors.New("Both --gui-address and --gui-apikey should be specified")
}
if guiCfg.Address() == "" {
return errors.New("Could not find GUI Address")
}
if guiCfg.APIKey == "" {
return errors.New("Could not find GUI API key")
}
client := getClient(guiCfg)
cfg, cfgErr := getConfig(client)
original := cfg.Copy()
// Copy the config and set the default flags
recliCfg := recli.DefaultConfig
recliCfg.IDTag.Name = "xml"
recliCfg.SkipTag.Name = "json"
configCommand := cli.Command{
Name: "config",
HideHelp: true,
Usage: "Configuration modification command group",
}
if cfgErr != nil {
configCommand.Action = func(*cli.Context) error {
return cfgErr
}
} else {
configCommand.Subcommands, err = recli.New(recliCfg).Construct(&cfg)
if err != nil {
return errors.Wrap(err, "config reflect")
}
configCommand, err := getConfigCommand(clientFactory)
if err != nil {
return err
}
// Implement the same flags at the upper CLI, but do nothing with them.
@@ -144,7 +85,7 @@ func Run() error {
app := cli.NewApp()
app.Author = "The Syncthing Authors"
app.Metadata = map[string]interface{}{
"client": client,
"clientFactory": clientFactory,
}
app.Commands = []cli.Command{{
Name: "cli",
@@ -187,23 +128,6 @@ func Run() error {
}
}
if cfgErr == nil && !reflect.DeepEqual(cfg, original) {
body, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
resp, err := client.Post("system/config", string(body))
if err != nil {
return err
}
if resp.StatusCode != 200 {
body, err := responseToBArray(resp)
if err != nil {
return err
}
return errors.New(string(body))
}
}
return nil
}