diff --git a/cmd/common.go b/cmd/common.go index 35b3a1cd0..b1a79f31c 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -262,6 +262,17 @@ func verifyCert(caCert []byte) (string, error) { } func loadConfig(ctx *cli.Context) (config.Config, error) { + switch ctx.GlobalString("config-helper") { + case "built-in": + return loadConfigNative(ctx) + default: + // allow loading of rancher config by triggering an + // external helper executable + return loadConfigWithHelper(ctx) + } +} + +func loadConfigNative(ctx *cli.Context) (config.Config, error) { // path will always be set by the global flag default path := ctx.GlobalString("config") path = filepath.Join(path, cfgFile) @@ -269,6 +280,7 @@ func loadConfig(ctx *cli.Context) (config.Config, error) { cf := config.Config{ Path: path, Servers: make(map[string]*config.ServerConfig), + Helper: ctx.GlobalString("config-helper"), } content, err := ioutil.ReadFile(path) @@ -284,6 +296,26 @@ func loadConfig(ctx *cli.Context) (config.Config, error) { return cf, err } +// fetch rancher cli config by executing an external helper +func loadConfigWithHelper(ctx *cli.Context) (config.Config, error) { + cf := config.Config{ + Path: "", + Servers: make(map[string]*config.ServerConfig), + Helper: ctx.GlobalString("config-helper"), + } + + cmd := exec.Command(ctx.GlobalString("config-helper"), "get") + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + content, err := cmd.Output() + if err != nil { + return cf, err + } + + err = json.Unmarshal(content, &cf) + return cf, err +} + func lookupConfig(ctx *cli.Context) (*config.ServerConfig, error) { cf, err := loadConfig(ctx) if err != nil { diff --git a/config/config.go b/config/config.go index ed678fe49..490cbaf27 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/url" "os" + "os/exec" "path" "strings" @@ -18,6 +19,8 @@ type Config struct { Path string `json:"path,omitempty"` // CurrentServer the user has in focus CurrentServer string + // Helper executable to store config + Helper string } //ServerConfig holds the config for each server the user has setup @@ -33,6 +36,17 @@ type ServerConfig struct { } func (c Config) Write() error { + switch c.Helper { + case "built-in": + return c.writeNative() + default: + // if rancher config was loaded by external helper + // use the same helper to persist the config + return c.writeWithHelper() + } +} + +func (c Config) writeNative() error { err := os.MkdirAll(path.Dir(c.Path), 0700) if err != nil { return err @@ -50,6 +64,19 @@ func (c Config) Write() error { return json.NewEncoder(output).Encode(c) } +func (c Config) writeWithHelper() error { + logrus.Infof("Saving config with helper %s", c.Helper) + jsonConfig, err := json.Marshal(c) + if err != nil { + return err + } + cmd := exec.Command(c.Helper, "store", string(jsonConfig)) + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + err = cmd.Run() + return err +} + func (c Config) FocusedServer() *ServerConfig { return c.Servers[c.CurrentServer] } diff --git a/main.go b/main.go index a8ea2f10b..d1d2e02ff 100644 --- a/main.go +++ b/main.go @@ -86,6 +86,12 @@ func mainErr() error { EnvVar: "RANCHER_CONFIG_DIR", Value: os.ExpandEnv("${HOME}/.rancher"), }, + cli.StringFlag{ + Name: "config-helper", + Usage: "Helper executable to load/store config", + EnvVar: "RANCHER_CONFIG_HELPER", + Value: os.ExpandEnv("built-in"), + }, } app.Commands = []cli.Command{ cmd.AppCommand(),