e3737f420f3467e8300a454825504a153a218467
[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/ /etc/xds-agent/config.json file
42
43 func readGlobalConfig(c *Config, confFile string) error {
44
45         searchIn := make([]string, 0, 3)
46         if confFile != "" {
47                 searchIn = append(searchIn, confFile)
48         }
49         if homeDir := common.GetUserHome(); homeDir != "" {
50                 searchIn = append(searchIn, path.Join(homeDir, ".xds", "agent", "agent-config.json"))
51         }
52
53         searchIn = append(searchIn, "/etc/xds-agent/agent-config.json")
54
55         var cFile *string
56         for _, p := range searchIn {
57                 if _, err := os.Stat(p); err == nil {
58                         cFile = &p
59                         break
60                 }
61         }
62         if cFile == nil {
63                 c.Log.Infof("No config file found")
64                 return nil
65         }
66
67         c.Log.Infof("Use config file: %s", *cFile)
68
69         // TODO move on viper package to support comments in JSON and also
70         // bind with flags (command line options)
71         // see https://github.com/spf13/viper#working-with-flags
72
73         fd, _ := os.Open(*cFile)
74         defer fd.Close()
75
76         // Decode config file content and save it in a first variable
77         fCfg := FileConfig{}
78         if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
79                 return err
80         }
81
82         // Decode config file content and overwrite default settings
83         fd.Seek(0, 0)
84         json.NewDecoder(fd).Decode(&c.FileConf)
85
86         // Disable Syncthing support when there is no syncthing field in config
87         if fCfg.SThgConf == nil {
88                 c.FileConf.SThgConf = nil
89         }
90
91         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in agent-config.json
92         vars := []*string{
93                 &c.FileConf.LogsDir,
94                 &c.FileConf.WebAppDir,
95         }
96         if c.FileConf.SThgConf != nil {
97                 vars = append(vars, &c.FileConf.SThgConf.Home,
98                         &c.FileConf.SThgConf.BinDir)
99         }
100         for _, field := range vars {
101                 var err error
102                 *field, err = common.ResolveEnvVar(*field)
103                 if err != nil {
104                         return err
105                 }
106         }
107
108         return nil
109 }