X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=lib%2Fxdsconfig%2Ffileconfig.go;h=57e7043f0cfd5404bbafb83e713ff40655f88592;hb=5dc2ff003106f0ced38caadb06033f24c792f9b9;hp=ed3e82db954efca0ce69a30f3313358d12f521ff;hpb=7ecaccbae9b7741d8a285b98885e786dc1d4c79c;p=src%2Fxds%2Fxds-server.git diff --git a/lib/xdsconfig/fileconfig.go b/lib/xdsconfig/fileconfig.go index ed3e82d..57e7043 100644 --- a/lib/xdsconfig/fileconfig.go +++ b/lib/xdsconfig/fileconfig.go @@ -1,52 +1,96 @@ +/* + * Copyright (C) 2017-2018 "IoT.bzh" + * Author Sebastien Douheret + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package xdsconfig import ( "encoding/json" - "fmt" "os" "os/user" "path" "path/filepath" - "regexp" "strings" + + common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git" ) +const ( + // GlobalConfigFilename Global config filename + GlobalConfigFilename = "server-config.json" + // ServerDataFilename Server data filename + ServerDataFilename = "server-data.xml" + // FoldersConfigFilename Folders config filename + FoldersConfigFilename = "server-config_folders.xml" + // TargetsConfigFilename Targets config filename + TargetsConfigFilename = "server-config_targets.xml" +) + +// SyncThingConf definition type SyncThingConf struct { - Home string `json:"home"` - GuiAddress string `json:"gui-address"` - GuiAPIKey string `json:"gui-apikey"` + BinDir string `json:"binDir"` + Home string `json:"home"` + GuiAddress string `json:"gui-address"` + GuiAPIKey string `json:"gui-apikey"` + RescanIntervalS int `json:"rescanIntervalS"` } +// FileConfig is the JSON structure of xds-server config file (server-config.json) type FileConfig struct { - WebAppDir string `json:"webAppDir"` - ShareRootDir string `json:"shareRootDir"` - HTTPPort string `json:"httpPort"` - SThgConf SyncThingConf `json:"syncthing"` + WebAppDir string `json:"webAppDir"` + ShareRootDir string `json:"shareRootDir"` + SdkScriptsDir string `json:"sdkScriptsDir"` + XdsUtilsScriptsDir string `json:"xdsUtilsScriptsDir"` + SdkDbUpdate string `json:"sdkDbUpdate"` + HTTPPort string `json:"httpPort"` + SThgConf *SyncThingConf `json:"syncthing"` + LogsDir string `json:"logsDir"` + XdsSrvUpdateTime string `json:"xdsSrvUpdateTime"` } -// getConfigFromFile reads configuration from a config file. +// readGlobalConfig reads configuration from a config file. // Order to determine which config file is used: // 1/ from command line option: "--config myConfig.json" -// 2/ $HOME/.xds/config.json file -// 3/ /config.json file - -func updateConfigFromFile(c *Config, confFile string) error { +// 2/ $HOME/.xds/server/server-config.json file +// 3/ /etc/xds/server/server-config.json file +// 4/ /server-config.json file +func readGlobalConfig(c *Config, confFile string) error { searchIn := make([]string, 0, 3) if confFile != "" { searchIn = append(searchIn, confFile) } - if usr, err := user.Current(); err == nil { - searchIn = append(searchIn, path.Join(usr.HomeDir, ".xds", "config.json")) + if _, err := user.Current(); err == nil { + searchIn = append(searchIn, path.Join(ConfigRootDir(), GlobalConfigFilename)) } - cwd, err := os.Getwd() - if err == nil { - searchIn = append(searchIn, path.Join(cwd, "config.json")) - } - exePath, err := filepath.Abs(filepath.Dir(os.Args[0])) + + searchIn = append(searchIn, "/etc/xds/server/server-config.json") + + exePath := os.Args[0] + ee, _ := os.Executable() + exeAbsPath, err := filepath.Abs(ee) if err == nil { - searchIn = append(searchIn, path.Join(exePath, "config.json")) + exePath, err = filepath.EvalSymlinks(exeAbsPath) + if err == nil { + exePath = filepath.Dir(ee) + } else { + exePath = filepath.Dir(exeAbsPath) + } } + searchIn = append(searchIn, path.Join(exePath, "server-config.json")) var cFile *string for _, p := range searchIn { @@ -59,93 +103,96 @@ func updateConfigFromFile(c *Config, confFile string) error { // No config file found return nil } - - c.Log.Infof("Use config file: %s", *cFile) + c.Log.Infof("Use config file: %s", *cFile) // TODO move on viper package to support comments in JSON and also // bind with flags (command line options) // see https://github.com/spf13/viper#working-with-flags - fd, _ := os.Open(*cFile) defer fd.Close() fCfg := FileConfig{} if err := json.NewDecoder(fd).Decode(&fCfg); err != nil { return err } - c.fileConf = fCfg - // Support environment variables (IOW ${MY_ENV_VAR} syntax) in config.json - // TODO: better to use reflect package to iterate on fields and be more generic - var rep string - if rep, err = resolveEnvVar(fCfg.WebAppDir); err != nil { - return err + // Support environment variables (IOW ${MY_ENV_VAR} syntax) in server-config.json + vars := []*string{ + &fCfg.WebAppDir, + &fCfg.ShareRootDir, + &fCfg.SdkScriptsDir, + &fCfg.XdsUtilsScriptsDir, + &fCfg.LogsDir, + &fCfg.XdsSrvUpdateTime} + if fCfg.SThgConf != nil { + vars = append(vars, &fCfg.SThgConf.Home, &fCfg.SThgConf.BinDir) } - fCfg.WebAppDir = path.Clean(rep) - - if rep, err = resolveEnvVar(fCfg.ShareRootDir); err != nil { - return err + // Use config file settings else use default config + if fCfg.WebAppDir == "" { + fCfg.WebAppDir = c.FileConf.WebAppDir + } + if fCfg.ShareRootDir == "" { + fCfg.ShareRootDir = c.FileConf.ShareRootDir + } + if fCfg.SdkScriptsDir == "" { + fCfg.SdkScriptsDir = c.FileConf.SdkScriptsDir + } + if fCfg.XdsUtilsScriptsDir == "" { + fCfg.XdsUtilsScriptsDir = c.FileConf.XdsUtilsScriptsDir + } + if fCfg.SdkDbUpdate == "" { + fCfg.SdkDbUpdate = c.FileConf.SdkDbUpdate + } + if fCfg.HTTPPort == "" { + fCfg.HTTPPort = c.FileConf.HTTPPort + } + if fCfg.LogsDir == "" { + fCfg.LogsDir = c.FileConf.LogsDir + } + if fCfg.XdsSrvUpdateTime == "" { + fCfg.XdsSrvUpdateTime = c.FileConf.XdsSrvUpdateTime } - fCfg.ShareRootDir = path.Clean(rep) - if rep, err = resolveEnvVar(fCfg.SThgConf.Home); err != nil { - return err + for _, field := range vars { + var err error + if *field, err = common.ResolveEnvVar(*field); err != nil { + return err + } } - fCfg.SThgConf.Home = path.Clean(rep) - // Config file settings overwrite default config + // Resolve webapp dir (support relative or full path) + fCfg.WebAppDir = strings.Trim(fCfg.WebAppDir, " ") + if !strings.HasPrefix(fCfg.WebAppDir, "/") && exePath != "" { + cwd, _ := os.Getwd() - if fCfg.WebAppDir != "" { - c.WebAppDir = strings.Trim(fCfg.WebAppDir, " ") - } - // Is it a full path ? - if !strings.HasPrefix(c.WebAppDir, "/") && exePath != "" { // Check first from current directory - for _, rootD := range []string{cwd, exePath} { - ff := path.Join(rootD, c.WebAppDir, "index.html") - if exists(ff) { - c.WebAppDir = path.Join(rootD, c.WebAppDir) + for _, rootD := range []string{exePath, cwd} { + ff := path.Join(rootD, fCfg.WebAppDir, "index.html") + if common.Exists(ff) { + fCfg.WebAppDir = path.Join(rootD, fCfg.WebAppDir) break } } } - if fCfg.ShareRootDir != "" { - c.ShareRootDir = fCfg.ShareRootDir - } - - if fCfg.HTTPPort != "" { - c.HTTPPort = fCfg.HTTPPort - } - + c.FileConf = fCfg return nil } -// resolveEnvVar Resolved environment variable regarding the syntax ${MYVAR} -func resolveEnvVar(s string) (string, error) { - re := regexp.MustCompile("\\${(.*)}") - vars := re.FindAllStringSubmatch(s, -1) - res := s - for _, v := range vars { - val := os.Getenv(v[1]) - if val == "" { - return res, fmt.Errorf("ERROR: %s env variable not defined", v[1]) - } +func configFilenameGet(cfgFile string) (string, error) { + return path.Join(ConfigRootDir(), cfgFile), nil +} - rer := regexp.MustCompile("\\${" + v[1] + "}") - res = rer.ReplaceAllString(res, val) - } +// FoldersConfigFilenameGet Return the FoldersConfig filename +func FoldersConfigFilenameGet() (string, error) { + return configFilenameGet(FoldersConfigFilename) +} - return res, nil +// TargetsConfigFilenameGet Return the TargetsConfig filename +func TargetsConfigFilenameGet() (string, error) { + return configFilenameGet(TargetsConfigFilename) } -// exists returns whether the given file or directory exists or not -func exists(path string) bool { - _, err := os.Stat(path) - if err == nil { - return true - } - if os.IsNotExist(err) { - return false - } - return true +// ServerDataFilenameGet Return the ServerData filename +func ServerDataFilenameGet() (string, error) { + return configFilenameGet(ServerDataFilename) }