Remove duplicate fields and set default SDK dir.
[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
81         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in config.json
82         for _, field := range []*string{
83                 &fCfg.WebAppDir,
84                 &fCfg.ShareRootDir,
85                 &fCfg.SdkRootDir,
86                 &fCfg.LogsDir,
87                 &fCfg.SThgConf.Home,
88                 &fCfg.SThgConf.BinDir} {
89
90                 var err error
91                 if *field, err = common.ResolveEnvVar(*field); err != nil {
92                         return err
93                 }
94         }
95
96         // Use config file settings else use default config
97         if fCfg.WebAppDir == "" {
98                 fCfg.WebAppDir = c.FileConf.WebAppDir
99         }
100         if fCfg.ShareRootDir == "" {
101                 fCfg.ShareRootDir = c.FileConf.ShareRootDir
102         }
103         if fCfg.SdkRootDir == "" {
104                 fCfg.SdkRootDir = c.FileConf.SdkRootDir
105         }
106         if fCfg.HTTPPort == "" {
107                 fCfg.HTTPPort = c.FileConf.HTTPPort
108         }
109
110         // Resolve webapp dir (support relative or full path)
111         fCfg.WebAppDir = strings.Trim(fCfg.WebAppDir, " ")
112         if !strings.HasPrefix(fCfg.WebAppDir, "/") && exePath != "" {
113                 // Check first from current directory
114                 for _, rootD := range []string{cwd, exePath} {
115                         ff := path.Join(rootD, fCfg.WebAppDir, "index.html")
116                         if common.Exists(ff) {
117                                 fCfg.WebAppDir = path.Join(rootD, fCfg.WebAppDir)
118                                 break
119                         }
120                 }
121         }
122
123         c.FileConf = fCfg
124         return nil
125 }