Add XDS_SERVER_WORKSPACE_DIR env var support
[src/xds/xds-server.git] / lib / xdsconfig / config.go
1 /*
2  * Copyright (C) 2017-2018 "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         "fmt"
22         "io"
23         "os"
24         "os/user"
25         "path"
26         "path/filepath"
27
28         common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib"
29         "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
30         "github.com/Sirupsen/logrus"
31         "github.com/codegangsta/cli"
32 )
33
34 // Config parameters (json format) of /config command
35 type Config struct {
36         // Public APIConfig fields
37         xsapiv1.APIConfig
38
39         // Private (un-exported fields in REST GET /config route)
40         Options       Options        `json:"-"`
41         FileConf      FileConfig     `json:"-"`
42         Log           *logrus.Logger `json:"-"`
43         LogVerboseOut io.Writer      `json:"-"`
44 }
45
46 // Options set at the command line
47 type Options struct {
48         ConfigFile     string
49         LogLevel       string
50         LogFile        string
51         NoFolderConfig bool
52 }
53
54 // Config default values
55 const (
56         DefaultAPIVersion    = "1"
57         DefaultPort          = "8000"
58         DefaultShareDir      = "projects"
59         DefaultSTHomeDir     = "syncthing-config"
60         DefaultSdkScriptsDir = "${EXEPATH}/sdks"
61         DefaultSdkDbUpdate   = "startup"
62 )
63
64 // Init loads the configuration on start-up
65 func Init(cliCtx *cli.Context, log *logrus.Logger) (*Config, error) {
66         var err error
67
68         dfltShareDir := path.Join(ConfigRootDir(), DefaultShareDir)
69         dfltSTHomeDir := path.Join(ConfigRootDir(), DefaultSTHomeDir)
70         if resDir, err := common.ResolveEnvVar(dfltShareDir); err == nil {
71                 dfltShareDir = resDir
72         }
73         if resDir, err := common.ResolveEnvVar(dfltSTHomeDir); err == nil {
74                 dfltSTHomeDir = resDir
75         }
76
77         // Retrieve Server ID (or create one the first time)
78         uuid, err := ServerIDGet()
79         if err != nil {
80                 return nil, err
81         }
82
83         // Define default configuration
84         c := Config{
85                 APIConfig: xsapiv1.APIConfig{
86                         ServerUID:        uuid,
87                         Version:          cliCtx.App.Metadata["version"].(string),
88                         APIVersion:       DefaultAPIVersion,
89                         VersionGitTag:    cliCtx.App.Metadata["git-tag"].(string),
90                         Builder:          xsapiv1.BuilderConfig{},
91                         SupportedSharing: map[string]bool{xsapiv1.TypePathMap: true},
92                 },
93
94                 Options: Options{
95                         ConfigFile:     cliCtx.GlobalString("config"),
96                         LogLevel:       cliCtx.GlobalString("log"),
97                         LogFile:        cliCtx.GlobalString("logfile"),
98                         NoFolderConfig: cliCtx.GlobalBool("no-folderconfig"),
99                 },
100                 FileConf: FileConfig{
101                         WebAppDir:     "webapp/dist",
102                         ShareRootDir:  dfltShareDir,
103                         SdkScriptsDir: DefaultSdkScriptsDir,
104                         SdkDbUpdate:   DefaultSdkDbUpdate,
105                         HTTPPort:      DefaultPort,
106                         SThgConf:      &SyncThingConf{Home: dfltSTHomeDir},
107                         LogsDir:       "",
108                 },
109                 Log: log,
110         }
111
112         c.Log.Infoln("Server UUID:          ", uuid)
113
114         // config file settings overwrite default config
115         err = readGlobalConfig(&c, c.Options.ConfigFile)
116         if err != nil {
117                 return nil, err
118         }
119
120         // Update location of shared dir if needed
121         if !common.Exists(c.FileConf.ShareRootDir) {
122                 if err := os.MkdirAll(c.FileConf.ShareRootDir, 0770); err != nil {
123                         return nil, fmt.Errorf("No valid shared directory found: %v", err)
124                 }
125         }
126         c.Log.Infoln("Share root directory: ", c.FileConf.ShareRootDir)
127
128         // Where Logs are redirected:
129         //  default 'stdout' (logfile option default value)
130         //  else use file (or filepath) set by --logfile option
131         //  that may be overwritten by LogsDir field of config file
132         logF := c.Options.LogFile
133         logD := c.FileConf.LogsDir
134         if logF != "stdout" {
135                 if logD != "" {
136                         lf := filepath.Base(logF)
137                         if lf == "" || lf == "." {
138                                 lf = "xds-server.log"
139                         }
140                         logF = filepath.Join(logD, lf)
141                 } else {
142                         logD = filepath.Dir(logF)
143                 }
144         }
145         if logD == "" || logD == "." {
146                 logD = "/tmp/xds/logs"
147         }
148         c.Options.LogFile = logF
149         c.FileConf.LogsDir = logD
150
151         if c.FileConf.LogsDir != "" && !common.Exists(c.FileConf.LogsDir) {
152                 if err := os.MkdirAll(c.FileConf.LogsDir, 0770); err != nil {
153                         return nil, fmt.Errorf("Cannot create logs dir: %v", err)
154                 }
155         }
156
157         c.Log.Infoln("Logs file:            ", c.Options.LogFile)
158         c.Log.Infoln("Logs directory:       ", c.FileConf.LogsDir)
159
160         return &c, nil
161 }
162
163 // ConfigRootDir return the root directory where xds server save all config files
164 func ConfigRootDir() string {
165         root := "$HOME"
166         if usr, err := user.Current(); err == nil {
167                 root = usr.HomeDir
168         }
169
170         // Default $HOME/.xds/server but may be changed by an env variable
171         if envVar, envDef := os.LookupEnv("XDS_SERVER_ROOT_CFG_DIR"); envDef {
172                 root = envVar
173         }
174
175         return path.Join(root, "/.xds/server")
176 }
177
178 // WorkspaceRootDir return the path on server side where user xds-workspace dir is accessible
179 func WorkspaceRootDir() string {
180         // May be overloaded by an env variable
181         if envVar, envDef := os.LookupEnv("XDS_SERVER_WORKSPACE_DIR"); envDef {
182                 return envVar
183         }
184
185         home := "${HOME}"
186         if usr, err := user.Current(); err == nil {
187                 home = usr.HomeDir
188         }
189
190         // Default value $HOME/xds-workspace
191         return path.Join(home, "xds-workspace")
192 }