Allow to set Syncthing rescanInterval parameter.
[src/xds/xds-server.git] / lib / xdsconfig / fileconfig.go
1 package xdsconfig
2
3 import (
4         "encoding/json"
5         "os"
6         "os/user"
7         "path"
8         "path/filepath"
9         "strings"
10
11         "github.com/iotbzh/xds-server/lib/common"
12 )
13
14 type SyncThingConf struct {
15         BinDir          string `json:"binDir"`
16         Home            string `json:"home"`
17         GuiAddress      string `json:"gui-address"`
18         GuiAPIKey       string `json:"gui-apikey"`
19         RescanIntervalS int    `json:"rescanIntervalS"`
20 }
21
22 type FileConfig struct {
23         WebAppDir    string         `json:"webAppDir"`
24         ShareRootDir string         `json:"shareRootDir"`
25         SdkRootDir   string         `json:"sdkRootDir"`
26         HTTPPort     string         `json:"httpPort"`
27         SThgConf     *SyncThingConf `json:"syncthing"`
28         LogsDir      string         `json:"logsDir"`
29 }
30
31 // getConfigFromFile reads configuration from a config file.
32 // Order to determine which config file is used:
33 //  1/ from command line option: "--config myConfig.json"
34 //  2/ $HOME/.xds/config.json file
35 //  3/ <current_dir>/config.json file
36 //  4/ <xds-server executable dir>/config.json file
37
38 func updateConfigFromFile(c *Config, confFile string) error {
39
40         searchIn := make([]string, 0, 3)
41         if confFile != "" {
42                 searchIn = append(searchIn, confFile)
43         }
44         if usr, err := user.Current(); err == nil {
45                 searchIn = append(searchIn, path.Join(usr.HomeDir, ".xds", "config.json"))
46         }
47         cwd, err := os.Getwd()
48         if err == nil {
49                 searchIn = append(searchIn, path.Join(cwd, "config.json"))
50         }
51         exePath, err := filepath.Abs(filepath.Dir(os.Args[0]))
52         if err == nil {
53                 searchIn = append(searchIn, path.Join(exePath, "config.json"))
54         }
55
56         var cFile *string
57         for _, p := range searchIn {
58                 if _, err := os.Stat(p); err == nil {
59                         cFile = &p
60                         break
61                 }
62         }
63         if cFile == nil {
64                 // No config file found
65                 return nil
66         }
67
68         c.Log.Infof("Use config file: %s", *cFile)
69
70         // TODO move on viper package to support comments in JSON and also
71         // bind with flags (command line options)
72         // see https://github.com/spf13/viper#working-with-flags
73
74         fd, _ := os.Open(*cFile)
75         defer fd.Close()
76         fCfg := FileConfig{}
77         if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
78                 return err
79         }
80         c.FileConf = fCfg
81
82         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in config.json
83         for _, field := range []*string{
84                 &fCfg.WebAppDir,
85                 &fCfg.ShareRootDir,
86                 &fCfg.SdkRootDir,
87                 &fCfg.LogsDir,
88                 &fCfg.SThgConf.Home,
89                 &fCfg.SThgConf.BinDir} {
90
91                 var err error
92                 if *field, err = common.ResolveEnvVar(*field); err != nil {
93                         return err
94                 }
95         }
96
97         // Config file settings overwrite default config
98
99         if fCfg.WebAppDir != "" {
100                 c.WebAppDir = strings.Trim(fCfg.WebAppDir, " ")
101         }
102         // Is it a full path ?
103         if !strings.HasPrefix(c.WebAppDir, "/") && exePath != "" {
104                 // Check first from current directory
105                 for _, rootD := range []string{cwd, exePath} {
106                         ff := path.Join(rootD, c.WebAppDir, "index.html")
107                         if common.Exists(ff) {
108                                 c.WebAppDir = path.Join(rootD, c.WebAppDir)
109                                 break
110                         }
111                 }
112         }
113
114         if fCfg.ShareRootDir != "" {
115                 c.ShareRootDir = fCfg.ShareRootDir
116         }
117
118         if fCfg.HTTPPort != "" {
119                 c.HTTPPort = fCfg.HTTPPort
120         }
121
122         return nil
123 }