efe94bf0c06ddb58fc39c1355ae478ed9abac7be
[src/xds/xds-agent.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
10         common "github.com/iotbzh/xds-common/golib"
11 )
12
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"`
18 }
19
20 type FileConfig struct {
21         HTTPPort  string         `json:"httpPort"`
22         LogsDir   string         `json:"logsDir"`
23         XDSAPIKey string         `json:"xds-apikey"`
24         SThgConf  *SyncThingConf `json:"syncthing"`
25 }
26
27 // getConfigFromFile reads configuration from a config file.
28 // Order to determine which config file is used:
29 //  1/ from command line option: "--config myConfig.json"
30 //  2/ $HOME/.xds/agent/agent-config.json file
31 //  3/ <current_dir>/agent-config.json file
32 //  4/ <executable dir>/agent-config.json file
33
34 func updateConfigFromFile(c *Config, confFile string) (*FileConfig, error) {
35
36         searchIn := make([]string, 0, 3)
37         if confFile != "" {
38                 searchIn = append(searchIn, confFile)
39         }
40         if usr, err := user.Current(); err == nil {
41                 searchIn = append(searchIn, path.Join(usr.HomeDir, ".xds", "agent", "agent-config.json"))
42         }
43
44         searchIn = append(searchIn, "/etc/xds-agent/agent-config.json")
45
46         exePath := os.Args[0]
47         ee, _ := os.Executable()
48         exeAbsPath, err := filepath.Abs(ee)
49         if err == nil {
50                 exePath, err = filepath.EvalSymlinks(exeAbsPath)
51                 if err == nil {
52                         exePath = filepath.Dir(ee)
53                 } else {
54                         exePath = filepath.Dir(exeAbsPath)
55                 }
56         }
57         searchIn = append(searchIn, path.Join(exePath, "agent-config.json"))
58
59         var cFile *string
60         for _, p := range searchIn {
61                 if _, err := os.Stat(p); err == nil {
62                         cFile = &p
63                         break
64                 }
65         }
66         // Use default settings
67         fCfg := *c.FileConf
68
69         // Read config file when existing
70         if cFile != nil {
71                 c.Log.Infof("Use config file: %s", *cFile)
72
73                 // TODO move on viper package to support comments in JSON and also
74                 // bind with flags (command line options)
75                 // see https://github.com/spf13/viper#working-with-flags
76
77                 fd, _ := os.Open(*cFile)
78                 defer fd.Close()
79                 if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
80                         return nil, err
81                 }
82         }
83
84         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in agent-config.json
85         vars := []*string{
86                 &fCfg.LogsDir,
87         }
88         if fCfg.SThgConf != nil {
89                 vars = append(vars, &fCfg.SThgConf.Home, &fCfg.SThgConf.BinDir)
90         }
91         for _, field := range vars {
92                 var err error
93                 *field, err = common.ResolveEnvVar(*field)
94                 if err != nil {
95                         return nil, err
96                 }
97         }
98
99         // Config file settings overwrite default config
100         if fCfg.HTTPPort != "" {
101                 c.HTTPPort = fCfg.HTTPPort
102         }
103
104         // Set default apikey
105         // FIXME - rework with dynamic key
106         if fCfg.XDSAPIKey == "" {
107                 fCfg.XDSAPIKey = "1234abcezam"
108         }
109
110         return &fCfg, nil
111 }