diff options
Diffstat (limited to 'lib/xdsconfig/fileconfig.go')
-rw-r--r-- | lib/xdsconfig/fileconfig.go | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/lib/xdsconfig/fileconfig.go b/lib/xdsconfig/fileconfig.go new file mode 100644 index 0000000..262d023 --- /dev/null +++ b/lib/xdsconfig/fileconfig.go @@ -0,0 +1,133 @@ +package xdsconfig + +import ( + "encoding/json" + "os" + "os/user" + "path" + "path/filepath" + "regexp" + "strings" +) + +type SyncThingConf struct { + Home string `json:"home"` + GuiAddress string `json:"gui-address"` + GuiAPIKey string `json:"gui-apikey"` +} + +type FileConfig struct { + WebAppDir string `json:"webAppDir"` + ShareRootDir string `json:"shareRootDir"` + HTTPPort string `json:"httpPort"` + SThgConf SyncThingConf `json:"syncthing"` +} + +// getConfigFromFile reads configuration from a config file. +// Order to determine which config file is used: +// 1/ from command line option: "--config myConfig.json" +// 2/ $HOME/.xds/config.json file +// 3/ <xds-server executable dir>/config.json file + +func updateConfigFromFile(c *Config, confFile string) error { + + searchIn := make([]string, 0, 3) + if confFile != "" { + searchIn = append(searchIn, confFile) + } + if usr, err := user.Current(); err == nil { + searchIn = append(searchIn, path.Join(usr.HomeDir, ".xds", "config.json")) + } + cwd, err := os.Getwd() + if err == nil { + searchIn = append(searchIn, path.Join(cwd, "config.json")) + } + exePath, err := filepath.Abs(filepath.Dir(os.Args[0])) + if err == nil { + searchIn = append(searchIn, path.Join(exePath, "config.json")) + } + + var cFile *string + for _, p := range searchIn { + if _, err := os.Stat(p); err == nil { + cFile = &p + break + } + } + if cFile == nil { + // No config file found + return nil + } + + // TODO move on viper package to support comments in JSON and also + // bind with flags (command line options) + // see https://github.com/spf13/viper#working-with-flags + + fd, _ := os.Open(*cFile) + defer fd.Close() + fCfg := FileConfig{} + if err := json.NewDecoder(fd).Decode(&fCfg); err != nil { + return err + } + c.fileConf = fCfg + + // Support environment variables (IOW ${MY_ENV_VAR} syntax) in config.json + // TODO: better to use reflect package to iterate on fields and be more generic + fCfg.WebAppDir = path.Clean(resolveEnvVar(fCfg.WebAppDir)) + fCfg.ShareRootDir = path.Clean(resolveEnvVar(fCfg.ShareRootDir)) + fCfg.SThgConf.Home = path.Clean(resolveEnvVar(fCfg.SThgConf.Home)) + + // Config file settings overwrite default config + + if fCfg.WebAppDir != "" { + c.WebAppDir = strings.Trim(fCfg.WebAppDir, " ") + } + // Is it a full path ? + if !strings.HasPrefix(c.WebAppDir, "/") && exePath != "" { + // Check first from current directory + for _, rootD := range []string{cwd, exePath} { + ff := path.Join(rootD, c.WebAppDir, "index.html") + if exists(ff) { + c.WebAppDir = path.Join(rootD, c.WebAppDir) + break + } + } + } + + if fCfg.ShareRootDir != "" { + c.ShareRootDir = fCfg.ShareRootDir + } + + if fCfg.HTTPPort != "" { + c.HTTPPort = fCfg.HTTPPort + } + + return nil +} + +// resolveEnvVar Resolved environment variable regarding the syntax ${MYVAR} +func resolveEnvVar(s string) string { + re := regexp.MustCompile("\\${(.*)}") + vars := re.FindAllStringSubmatch(s, -1) + res := s + for _, v := range vars { + val := os.Getenv(v[1]) + if val != "" { + rer := regexp.MustCompile("\\${" + v[1] + "}") + res = rer.ReplaceAllString(res, val) + } + } + return res +} + +// exists returns whether the given file or directory exists or not +func exists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + if os.IsNotExist(err) { + return false + } + return true +} |