You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/04/13 22:06:55 UTC
[cloudstack-cloudmonkey] 02/04: config: implement ini based config
same as legacy cloudmonkey
This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack-cloudmonkey.git
commit ed77ec07d952c49d987a26a3c3d355bcaf00233b
Author: Rohit Yadav <ro...@apache.org>
AuthorDate: Sat Apr 14 03:24:27 2018 +0530
config: implement ini based config same as legacy cloudmonkey
Signed-off-by: Rohit Yadav <ro...@apache.org>
---
cli/completer.go | 2 +-
cli/selector.go | 2 +-
cli/shell.go | 3 +
cmd/network.go | 6 +-
config/about.go | 1 +
config/config.go | 211 +++++++++++++++++++++++++++++++++++--------------------
6 files changed, 144 insertions(+), 81 deletions(-)
diff --git a/cli/completer.go b/cli/completer.go
index 9cd9a04..58ff60b 100644
--- a/cli/completer.go
+++ b/cli/completer.go
@@ -188,7 +188,7 @@ func (t *CliCompleter) Do(line []rune, pos int) (options [][]rune, offset int) {
return nil, 0
}
- r := cmd.NewRequest(nil, config.NewConfig(), nil, nil)
+ r := cmd.NewRequest(nil, shellConfig, nil, nil)
autocompleteApiArgs := []string{"listall=true"}
if autocompleteApi.Noun == "templates" {
autocompleteApiArgs = append(autocompleteApiArgs, "templatefilter=all")
diff --git a/cli/selector.go b/cli/selector.go
index 0f0b998..27e03b2 100644
--- a/cli/selector.go
+++ b/cli/selector.go
@@ -21,8 +21,8 @@ import (
"fmt"
"strings"
- "github.com/manifoldco/promptui"
"github.com/chzyer/readline"
+ "github.com/manifoldco/promptui"
)
type SelectOption struct {
diff --git a/cli/shell.go b/cli/shell.go
index f8fc031..1dfc075 100644
--- a/cli/shell.go
+++ b/cli/shell.go
@@ -28,7 +28,10 @@ import (
"github.com/chzyer/readline"
)
+var shellConfig *config.Config
+
func ExecShell(cfg *config.Config) {
+ shellConfig = cfg
shell, err := readline.NewEx(&readline.Config{
Prompt: cfg.GetPrompt(),
HistoryFile: cfg.HistoryFile,
diff --git a/cmd/network.go b/cmd/network.go
index 6ff7d7c..94f67ad 100644
--- a/cmd/network.go
+++ b/cmd/network.go
@@ -66,8 +66,8 @@ func NewAPIRequest(r *Request, api string, args []string) (map[string]interface{
}
}
- apiKey := r.Config.ActiveProfile.ApiKey
- secretKey := r.Config.ActiveProfile.SecretKey
+ apiKey := r.Config.Core.ActiveProfile.ApiKey
+ secretKey := r.Config.Core.ActiveProfile.SecretKey
if len(apiKey) > 0 {
params.Add("apiKey", apiKey)
@@ -81,7 +81,7 @@ func NewAPIRequest(r *Request, api string, args []string) (map[string]interface{
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))
encodedParams = encodedParams + fmt.Sprintf("&signature=%s", url.QueryEscape(signature))
- apiUrl := fmt.Sprintf("%s?%s", r.Config.ActiveProfile.Url, encodedParams)
+ apiUrl := fmt.Sprintf("%s?%s", r.Config.Core.ActiveProfile.Url, encodedParams)
//fmt.Println("[debug] Requesting: ", apiUrl)
response, err := http.Get(apiUrl)
diff --git a/config/about.go b/config/about.go
new file mode 100644
index 0000000..d912156
--- /dev/null
+++ b/config/about.go
@@ -0,0 +1 @@
+package config
diff --git a/config/config.go b/config/config.go
index 9122ec8..b89cc54 100644
--- a/config/config.go
+++ b/config/config.go
@@ -19,56 +19,54 @@ package config
import (
"fmt"
- homedir "github.com/mitchellh/go-homedir"
+ "github.com/mitchellh/go-homedir"
+ "gopkg.in/ini.v1"
"os"
"path"
+ "strconv"
)
-var name = "cloudmonkey"
-var version = "6.0.0-alpha1"
-
-func getDefaultConfigDir() string {
- home, err := homedir.Dir()
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- return path.Join(home, ".cmk")
-}
-
-type OutputFormat string
-
const (
- Json OutputFormat = "json"
- Xml OutputFormat = "xml"
- Table OutputFormat = "table"
- Text OutputFormat = "text"
+ Json = "json"
+ Xml = "xml"
+ Table = "table"
+ Text = "text"
)
-type Profile struct {
- Name string
- Url string
- VerifyCert bool
- Username string
- Password string
- Domain string
- ApiKey string
- SecretKey string
+type ServerProfile struct {
+ Url string `ini:"url"`
+ Username string `ini:"username"`
+ Password string `ini:"password"`
+ Domain string `ini:"domain"`
+ ApiKey string `ini:"apikey"`
+ SecretKey string `ini:"secretkey"`
+ VerifyCert bool `ini:"verifycert"`
+}
+
+type Core struct {
+ AsyncBlock bool `ini:"asyncblock"`
+ Timeout int `ini:"timeout"`
+ Output string `ini:"output"`
+ ProfileName string `ini:"profile"`
+ ActiveProfile *ServerProfile `ini:"-"`
}
type Config struct {
- Dir string
- ConfigFile string
- HistoryFile string
- CacheFile string
- LogFile string
- Output OutputFormat
- AsyncBlock bool
- ActiveProfile Profile
+ Dir string
+ ConfigFile string
+ HistoryFile string
+ CacheFile string
+ LogFile string
+ Core *Core
}
-func NewConfig() *Config {
- return loadConfig()
+func getDefaultConfigDir() string {
+ home, err := homedir.Dir()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ return path.Join(home, ".cmk")
}
func defaultConfig() *Config {
@@ -76,58 +74,86 @@ func defaultConfig() *Config {
return &Config{
Dir: configDir,
ConfigFile: path.Join(configDir, "config"),
- HistoryFile: path.Join(configDir, "history"),
CacheFile: path.Join(configDir, "cache"),
+ HistoryFile: path.Join(configDir, "history"),
LogFile: path.Join(configDir, "log"),
- Output: Json,
- AsyncBlock: true,
- ActiveProfile: Profile{
- Name: "local",
- Url: "http://192.168.1.10:8080/client/api",
- VerifyCert: false,
- Username: "admin",
- Password: "password",
- Domain: "/",
- // TODO: remove test data
- ApiKey: "IgrUOA_46IVoBNzAR_Th2JbdbgIs2lMW1kGe9A80F9X0uOnfGO0Su23IqOSqbdzZW3To95PNrcdWsk60ieXYBQ",
- SecretKey: "E7NRSv5d_1VhqXUHJEqvAsm7htR_V_vtPJZsCPkgPKSgkiS3sh4SOrIqMm_eWhSFoL6RHRIlxtA_viQAt7EDVA",
+ Core: &Core{
+ AsyncBlock: false,
+ Timeout: 1800,
+ Output: Json,
+ ProfileName: "local",
+ ActiveProfile: &ServerProfile{
+ Url: "http://localhost:8080/client/api",
+ Username: "admin",
+ Password: "password",
+ Domain: "/",
+ ApiKey: "",
+ SecretKey: "",
+ VerifyCert: false,
+ },
},
}
}
-func loadConfig() *Config {
- cfg := defaultConfig()
+func reloadConfig(cfg *Config) *Config {
if _, err := os.Stat(cfg.Dir); err != nil {
os.Mkdir(cfg.Dir, 0700)
}
+ // Save on missing config
if _, err := os.Stat(cfg.ConfigFile); err != nil {
- // FIXME: write default cfg
- } else {
- //load config?
+ defaultConf := defaultConfig()
+ conf := ini.Empty()
+ conf.Section(ini.DEFAULT_SECTION).ReflectFrom(defaultConf.Core)
+ conf.Section(cfg.Core.ProfileName).ReflectFrom(defaultConf.Core.ActiveProfile)
+ conf.SaveTo(cfg.ConfigFile)
}
- LoadCache(cfg)
-
- return cfg
-}
+ // Read config
+ conf, err := ini.LoadSources(ini.LoadOptions{
+ IgnoreInlineComment: true,
+ }, cfg.ConfigFile)
-func (c *Config) Name() string {
- return name
-}
+ if err != nil {
+ fmt.Printf("Fail to read config file: %v", err)
+ os.Exit(1)
+ }
-func (c *Config) Version() string {
- return version
-}
+ core, err := conf.GetSection(ini.DEFAULT_SECTION)
+ if core == nil {
+ section, _ := conf.NewSection(ini.DEFAULT_SECTION)
+ section.ReflectFrom(&defaultConfig().Core)
+ } else {
+ // Write
+ if cfg.Core != nil {
+ conf.Section(ini.DEFAULT_SECTION).ReflectFrom(&cfg.Core)
+ }
+ // Update
+ core := new(Core)
+ conf.Section(ini.DEFAULT_SECTION).MapTo(core)
+ cfg.Core = core
+ }
-func (c *Config) PrintHeader() {
- fmt.Printf("Apache CloudStack 🐵 cloudmonkey %s.\n", version)
- fmt.Printf("Type \"help\" for details, \"sync\" to update API cache or press tab to list commands.\n\n")
-}
+ profile, err := conf.GetSection(cfg.Core.ProfileName)
+ if profile == nil {
+ section, _ := conf.NewSection(cfg.Core.ProfileName)
+ section.ReflectFrom(&defaultConfig().Core.ActiveProfile)
+ } else {
+ // Write
+ if cfg.Core.ActiveProfile != nil {
+ conf.Section(cfg.Core.ProfileName).ReflectFrom(&cfg.Core.ActiveProfile)
+ }
+ // Update
+ profile := new(ServerProfile)
+ conf.Section(cfg.Core.ProfileName).MapTo(profile)
+ cfg.Core.ActiveProfile = profile
+ }
+ // Save
+ conf.SaveTo(cfg.ConfigFile)
-func (c *Config) GetPrompt() string {
- return fmt.Sprintf("(%s) 🐒 > ", c.ActiveProfile.Name)
+ fmt.Println("Updating config to:", cfg.Core, cfg.Core.ActiveProfile)
+ return cfg
}
func (c *Config) UpdateGlobalConfig(key string, value string) {
@@ -135,9 +161,42 @@ func (c *Config) UpdateGlobalConfig(key string, value string) {
}
func (c *Config) UpdateConfig(namespace string, key string, value string) {
- fmt.Println("👌 Updating for key", key, ", value=", value, ", in ns=", namespace)
- if key == "profile" {
- //FIXME
- c.ActiveProfile.Name = value
+ switch key {
+ case "asyncblock":
+ c.Core.AsyncBlock = value == "true"
+ case "output":
+ c.Core.Output = value
+ case "timeout":
+ intValue, _ := strconv.Atoi(value)
+ c.Core.Timeout = intValue
+ case "profile":
+ c.Core.ProfileName = value
+ c.Core.ActiveProfile = nil
+ case "url":
+ c.Core.ActiveProfile.Url = value
+ case "username":
+ c.Core.ActiveProfile.Username = value
+ case "password":
+ c.Core.ActiveProfile.Password = value
+ case "domain":
+ c.Core.ActiveProfile.Domain = value
+ case "apikey":
+ c.Core.ActiveProfile.ApiKey = value
+ case "secretkey":
+ c.Core.ActiveProfile.SecretKey = value
+ case "verifycert":
+ c.Core.ActiveProfile.VerifyCert = value == "true"
+ default:
+ return
}
+
+ reloadConfig(c)
+}
+
+func NewConfig() *Config {
+ defaultConf := defaultConfig()
+ defaultConf.Core = nil
+ cfg := reloadConfig(defaultConf)
+ LoadCache(cfg)
+ return cfg
}
--
To stop receiving notification emails like this one, please contact
rohit@apache.org.