diff options
Diffstat (limited to 'lib/xdsconfig/config.go')
-rw-r--r-- | lib/xdsconfig/config.go | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/lib/xdsconfig/config.go b/lib/xdsconfig/config.go new file mode 100644 index 0000000..df98439 --- /dev/null +++ b/lib/xdsconfig/config.go @@ -0,0 +1,231 @@ +package xdsconfig + +import ( + "fmt" + "strings" + + "os" + + "time" + + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/iotbzh/xds-server/lib/syncthing" +) + +// Config parameters (json format) of /config command +type Config struct { + Version string `json:"version"` + APIVersion string `json:"apiVersion"` + VersionGitTag string `json:"gitTag"` + Builder BuilderConfig `json:"builder"` + Folders FoldersConfig `json:"folders"` + + // Private / un-exported fields + progName string + fileConf FileConfig + WebAppDir string `json:"-"` + HTTPPort string `json:"-"` + ShareRootDir string `json:"-"` + Log *logrus.Logger `json:"-"` + SThg *st.SyncThing `json:"-"` +} + +// Config default values +const ( + DefaultAPIVersion = "1" + DefaultPort = "8000" + DefaultShareDir = "/mnt/share" + DefaultLogLevel = "error" +) + +// Init loads the configuration on start-up +func Init(ctx *cli.Context) (Config, error) { + var err error + + // Set logger level and formatter + log := ctx.App.Metadata["logger"].(*logrus.Logger) + + logLevel := ctx.GlobalString("log") + if logLevel == "" { + logLevel = DefaultLogLevel + } + if log.Level, err = logrus.ParseLevel(logLevel); err != nil { + fmt.Printf("Invalid log level : \"%v\"\n", logLevel) + os.Exit(1) + } + log.Formatter = &logrus.TextFormatter{} + + // Define default configuration + c := Config{ + Version: ctx.App.Metadata["version"].(string), + APIVersion: DefaultAPIVersion, + VersionGitTag: ctx.App.Metadata["git-tag"].(string), + Builder: BuilderConfig{}, + Folders: FoldersConfig{}, + + progName: ctx.App.Name, + WebAppDir: "webapp/dist", + HTTPPort: DefaultPort, + ShareRootDir: DefaultShareDir, + Log: log, + SThg: nil, + } + + // config file settings overwrite default config + err = updateConfigFromFile(&c, ctx.GlobalString("config")) + if err != nil { + return Config{}, err + } + + // Update location of shared dir if needed + if !dirExists(c.ShareRootDir) { + if err := os.MkdirAll(c.ShareRootDir, 0770); err != nil { + c.Log.Fatalf("No valid shared directory found (err=%v)", err) + } + } + c.Log.Infoln("Share root directory: ", c.ShareRootDir) + + // FIXME - add a builder interface and support other builder type (eg. native) + builderType := "syncthing" + + switch builderType { + case "syncthing": + // Syncthing settings only configurable from config.json file + stGuiAddr := c.fileConf.SThgConf.GuiAddress + stGuiApikey := c.fileConf.SThgConf.GuiAPIKey + if stGuiAddr == "" { + stGuiAddr = "http://localhost:8384" + } + if stGuiAddr[0:7] != "http://" { + stGuiAddr = "http://" + stGuiAddr + } + + // Retry if connection fail + retry := 5 + for retry > 0 { + c.SThg = st.NewSyncThing(stGuiAddr, stGuiApikey, c.Log) + if c.SThg != nil { + break + } + c.Log.Warningf("Establishing connection to Syncthing (retry %d/5)", retry) + time.Sleep(time.Second) + retry-- + } + if c.SThg == nil { + c.Log.Fatalf("ERROR: cannot connect to Syncthing (url: %s)", stGuiAddr) + } + + // Retrieve Syncthing config + id, err := c.SThg.IDGet() + if err != nil { + return Config{}, err + } + + if c.Builder, err = NewBuilderConfig(id); err != nil { + c.Log.Fatalln(err) + } + + // Retrieve initial Syncthing config + stCfg, err := c.SThg.ConfigGet() + if err != nil { + return Config{}, err + } + for _, stFld := range stCfg.Folders { + relativePath := strings.TrimPrefix(stFld.RawPath, c.ShareRootDir) + if relativePath == "" { + relativePath = stFld.RawPath + } + newFld := NewFolderConfig(stFld.ID, stFld.Label, c.ShareRootDir, strings.Trim(relativePath, "/")) + c.Folders = c.Folders.Update(FoldersConfig{newFld}) + } + + default: + log.Fatalln("Unsupported builder type") + } + + return c, nil +} + +// GetFolderFromID retrieves the Folder config from id +func (c *Config) GetFolderFromID(id string) *FolderConfig { + if idx := c.Folders.GetIdx(id); idx != -1 { + return &c.Folders[idx] + } + return nil +} + +// UpdateAll updates all the current configuration +func (c *Config) UpdateAll(newCfg Config) error { + return fmt.Errorf("Not Supported") + /* + if err := VerifyConfig(newCfg); err != nil { + return err + } + + // TODO: c.Builder = c.Builder.Update(newCfg.Builder) + c.Folders = c.Folders.Update(newCfg.Folders) + + // SEB A SUP model.NotifyListeners(c, NotifyFoldersChange, FolderConfig{}) + // FIXME To be tested & improved error handling + for _, f := range c.Folders { + if err := c.SThg.FolderChange(st.FolderChangeArg{ + ID: f.ID, + Label: f.Label, + RelativePath: f.RelativePath, + SyncThingID: f.SyncThingID, + ShareRootDir: c.ShareRootDir, + }); err != nil { + return err + } + } + + return nil + */ +} + +// UpdateFolder updates a specific folder into the current configuration +func (c *Config) UpdateFolder(newFolder FolderConfig) (FolderConfig, error) { + if err := FolderVerify(newFolder); err != nil { + return FolderConfig{}, err + } + + c.Folders = c.Folders.Update(FoldersConfig{newFolder}) + + // SEB A SUP model.NotifyListeners(c, NotifyFolderAdd, newFolder) + err := c.SThg.FolderChange(st.FolderChangeArg{ + ID: newFolder.ID, + Label: newFolder.Label, + RelativePath: newFolder.RelativePath, + SyncThingID: newFolder.SyncThingID, + ShareRootDir: c.ShareRootDir, + }) + + newFolder.BuilderSThgID = c.Builder.SyncThingID // FIXME - should be removed after local ST config rework + newFolder.Status = FolderStatusEnable + + return newFolder, err +} + +// DeleteFolder deletes a specific folder +func (c *Config) DeleteFolder(id string) (FolderConfig, error) { + var fld FolderConfig + var err error + + //SEB A SUP model.NotifyListeners(c, NotifyFolderDelete, fld) + if err = c.SThg.FolderDelete(id); err != nil { + return fld, err + } + + c.Folders, fld, err = c.Folders.Delete(id) + + return fld, err +} + +func dirExists(path string) bool { + _, err := os.Stat(path) + if os.IsNotExist(err) { + return false + } + return true +} |