13 type SyncThingConf struct {
14 BinDir string `json:"binDir"`
15 Home string `json:"home"`
16 GuiAddress string `json:"gui-address"`
17 GuiAPIKey string `json:"gui-apikey"`
20 type FileConfig struct {
21 HTTPPort string `json:"httpPort"`
22 SThgConf *SyncThingConf `json:"syncthing"`
25 // getConfigFromFile reads configuration from a config file.
26 // Order to determine which config file is used:
27 // 1/ from command line option: "--config myConfig.json"
28 // 2/ $HOME/.xds/agent-config.json file
29 // 3/ <current_dir>/agent-config.json file
30 // 4/ <executable dir>/agent-config.json file
32 func updateConfigFromFile(c *Config, confFile string) (*FileConfig, error) {
34 searchIn := make([]string, 0, 3)
36 searchIn = append(searchIn, confFile)
38 if usr, err := user.Current(); err == nil {
39 searchIn = append(searchIn, path.Join(usr.HomeDir, ".xds", "agent-config.json"))
41 cwd, err := os.Getwd()
43 searchIn = append(searchIn, path.Join(cwd, "agent-config.json"))
45 exePath, err := filepath.Abs(filepath.Dir(os.Args[0]))
47 searchIn = append(searchIn, path.Join(exePath, "agent-config.json"))
51 for _, p := range searchIn {
52 if _, err := os.Stat(p); err == nil {
59 // No config file found
63 c.log.Infof("Use config file: %s", *cFile)
65 // TODO move on viper package to support comments in JSON and also
66 // bind with flags (command line options)
67 // see https://github.com/spf13/viper#working-with-flags
69 fd, _ := os.Open(*cFile)
71 if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
75 // Support environment variables (IOW ${MY_ENV_VAR} syntax) in agent-config.json
76 // TODO: better to use reflect package to iterate on fields and be more generic
79 if rep, err = resolveEnvVar(fCfg.SThgConf.BinDir); err != nil {
82 fCfg.SThgConf.BinDir = path.Clean(rep)
84 if rep, err = resolveEnvVar(fCfg.SThgConf.Home); err != nil {
87 fCfg.SThgConf.Home = path.Clean(rep)
92 // resolveEnvVar Resolved environment variable regarding the syntax ${MYVAR}
93 func resolveEnvVar(s string) (string, error) {
94 re := regexp.MustCompile("\\${(.*)}")
95 vars := re.FindAllStringSubmatch(s, -1)
97 for _, v := range vars {
98 val := os.Getenv(v[1])
100 return res, fmt.Errorf("ERROR: %s env variable not defined", v[1])
103 rer := regexp.MustCompile("\\${" + v[1] + "}")
104 res = rer.ReplaceAllString(res, val)
110 // exists returns whether the given file or directory exists or not
111 func exists(path string) bool {
112 _, err := os.Stat(path)
116 if os.IsNotExist(err) {