Standardized XDS config file name and location.
[src/xds/xds-agent.git] / lib / xdsconfig / configfile.go
1 /*
2  * Copyright (C) 2017 "IoT.bzh"
3  * Author Sebastien Douheret <sebastien@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package xdsconfig
19
20 import (
21         "encoding/json"
22         "os"
23         "path"
24
25         common "github.com/iotbzh/xds-common/golib"
26 )
27
28 type SyncThingConf struct {
29         BinDir     string `json:"binDir"`
30         Home       string `json:"home"`
31         GuiAddress string `json:"gui-address"`
32         GuiAPIKey  string `json:"gui-apikey"`
33 }
34
35 type XDSServerConf struct {
36         URL       string `json:"url"`
37         ConnRetry int    `json:"connRetry"`
38
39         // private/not exported fields
40         ID            string `json:"-"`
41         APIBaseURL    string `json:"-"`
42         APIPartialURL string `json:"-"`
43 }
44
45 type FileConfig struct {
46         HTTPPort    string          `json:"httpPort"`
47         WebAppDir   string          `json:"webAppDir"`
48         LogsDir     string          `json:"logsDir"`
49         XDSAPIKey   string          `json:"xds-apikey"`
50         ServersConf []XDSServerConf `json:"xdsServers"`
51         SThgConf    *SyncThingConf  `json:"syncthing"`
52 }
53
54 // readGlobalConfig reads configuration from a config file.
55 // Order to determine which config file is used:
56 //  1/ from command line option: "--config myConfig.json"
57 //  2/ $HOME/.xds/agent/agent-config.json file
58 //  3/ /etc/xds/agent/agent-config.json file
59
60 func readGlobalConfig(c *Config, confFile string) error {
61
62         searchIn := make([]string, 0, 3)
63         if confFile != "" {
64                 searchIn = append(searchIn, confFile)
65         }
66         if homeDir := common.GetUserHome(); homeDir != "" {
67                 searchIn = append(searchIn, path.Join(homeDir, ".xds", "agent", "agent-config.json"))
68         }
69
70         searchIn = append(searchIn, "/etc/xds/agent/agent-config.json")
71
72         var cFile *string
73         for _, p := range searchIn {
74                 if _, err := os.Stat(p); err == nil {
75                         cFile = &p
76                         break
77                 }
78         }
79         if cFile == nil {
80                 c.Log.Infof("No config file found")
81                 return nil
82         }
83
84         c.Log.Infof("Use config file: %s", *cFile)
85
86         // TODO move on viper package to support comments in JSON and also
87         // bind with flags (command line options)
88         // see https://github.com/spf13/viper#working-with-flags
89
90         fd, _ := os.Open(*cFile)
91         defer fd.Close()
92
93         // Decode config file content and save it in a first variable
94         fCfg := FileConfig{}
95         if err := json.NewDecoder(fd).Decode(&fCfg); err != nil {
96                 return err
97         }
98
99         // Decode config file content and overwrite default settings
100         fd.Seek(0, 0)
101         json.NewDecoder(fd).Decode(&c.FileConf)
102
103         // Disable Syncthing support when there is no syncthing field in config
104         if fCfg.SThgConf == nil {
105                 c.FileConf.SThgConf = nil
106         }
107
108         // Support environment variables (IOW ${MY_ENV_VAR} syntax) in agent-config.json
109         vars := []*string{
110                 &c.FileConf.LogsDir,
111                 &c.FileConf.WebAppDir,
112         }
113         if c.FileConf.SThgConf != nil {
114                 vars = append(vars, &c.FileConf.SThgConf.Home,
115                         &c.FileConf.SThgConf.BinDir)
116         }
117         for _, field := range vars {
118                 var err error
119                 *field, err = common.ResolveEnvVar(*field)
120                 if err != nil {
121                         return err
122                 }
123         }
124
125         return nil
126 }