Fixed Syncthing folder status events and exec command.
[src/xds/xds-agent.git] / lib / xdsconfig / configfile.go
1 package xdsconfig
2
3 import (
4         "encoding/json"
5         "os"
6         "path"
7
8         common "github.com/iotbzh/xds-common/golib"
9 )
10
11 type SyncThingConf struct {
12         BinDir     string `json:"binDir"`
13         Home       string `json:"home"`
14         GuiAddress string `json:"gui-address"`
15         GuiAPIKey  string `json:"gui-apikey"`
16 }
17
18 type XDSServerConf struct {
19         URL       string `json:"url"`
20         ConnRetry int    `json:"connRetry"`
21
22         // private/not exported fields
23         ID            string `json:"-"`
24         APIBaseURL    string `json:"-"`
25         APIPartialURL string `json:"-"`
26 }
27
28 type FileConfig struct {
29         HTTPPort    string          `json:"httpPort"`
30         WebAppDir   string          `json:"webAppDir"`
31         LogsDir     string          `json:"logsDir"`
32         XDSAPIKey   string          `json:"xds-apikey"`
33         ServersConf []XDSServerConf `json:"xdsServers"`
34         SThgConf    *SyncThingConf  `json:"syncthing"`
35 }
36
37 // readGlobalConfig reads configuration from a config file.
38 // Order to determine which config file is used:
39 //  1/ from command line option: "--config myConfig.json"
40 //  2/ $HOME/.xds/agent/agent-config.json file
41 //  3/ <current_dir>/agent-config.json file
42 //  4/ <executable dir>/agent-config.json file
43
44 func readGlobalConfig(c *Config, confFile string) error {
45
46         searchIn := make([]string, 0, 3)
47         if confFile != "" {
48                 searchIn = append(searchIn, confFile)
49         }
50         if homeDir := common.GetUserHome(); homeDir != "" {
51                 searchIn = append(searchIn, path.Join(homeDir, ".xds", "agent", "agent-config.json"))
52         }
53
54         searchIn = append(searchIn, "/etc/xds-agent/agent-config.json")
55
56         searchIn = append(searchIn, path.Join(common.GetExePath(), "agent-config.json"))
57
58         var cFile *string
59         for _, p := range searchIn {
60                 if _, err := os.Stat(p); err == nil {
61                         cFile = &p
62                         break
63                 }
64         }
65         if cFile == nil {
66                 c.Log.Infof("No config file found")
67                 return nil
68         }
69
70         c.Log.Infof("Use config file: %s", *cFile)
71
72         // TODO move on viper package to support comments in JSON and also
73         // bind with flags (command line options)
74         // see https://github.com/spf13/viper#working-with-flags
75
76         fd, _ := os.Open(*cFile)
77         defer fd.Close()
78
79         // Decode config file content and save it in a first variable
80         fCfg := FileConfig{}
81         if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
82                 return err
83         }
84
85         // Decode config file content and overwrite default settings
86         fd.Seek(0, 0)
87         json.NewDecoder(fd).Decode(&c.FileConf)
88
89         // Disable Syncthing support when there is no syncthing field in config
90         if fCfg.SThgConf == nil {
91                 c.FileConf.SThgConf = nil
92         }
93
94         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in agent-config.json
95         vars := []*string{
96                 &c.FileConf.LogsDir,
97                 &c.FileConf.WebAppDir,
98         }
99         if c.FileConf.SThgConf != nil {
100                 vars = append(vars, &c.FileConf.SThgConf.Home,
101                         &c.FileConf.SThgConf.BinDir)
102         }
103         for _, field := range vars {
104                 var err error
105                 *field, err = common.ResolveEnvVar(*field)
106                 if err != nil {
107                         return err
108                 }
109         }
110
111         return nil
112 }