11 "github.com/Sirupsen/logrus"
12 "github.com/codegangsta/cli"
13 "github.com/iotbzh/xds-server/lib/syncthing"
16 // Config parameters (json format) of /config command
18 Version string `json:"version"`
19 APIVersion string `json:"apiVersion"`
20 VersionGitTag string `json:"gitTag"`
21 Builder BuilderConfig `json:"builder"`
22 Folders FoldersConfig `json:"folders"`
24 // Private / un-exported fields
27 WebAppDir string `json:"-"`
28 HTTPPort string `json:"-"`
29 ShareRootDir string `json:"-"`
30 Log *logrus.Logger `json:"-"`
31 SThg *st.SyncThing `json:"-"`
34 // Config default values
36 DefaultAPIVersion = "1"
38 DefaultShareDir = "/mnt/share"
39 DefaultLogLevel = "error"
42 // Init loads the configuration on start-up
43 func Init(ctx *cli.Context) (Config, error) {
46 // Set logger level and formatter
47 log := ctx.App.Metadata["logger"].(*logrus.Logger)
49 logLevel := ctx.GlobalString("log")
51 logLevel = DefaultLogLevel
53 if log.Level, err = logrus.ParseLevel(logLevel); err != nil {
54 fmt.Printf("Invalid log level : \"%v\"\n", logLevel)
57 log.Formatter = &logrus.TextFormatter{}
59 // Define default configuration
61 Version: ctx.App.Metadata["version"].(string),
62 APIVersion: DefaultAPIVersion,
63 VersionGitTag: ctx.App.Metadata["git-tag"].(string),
64 Builder: BuilderConfig{},
65 Folders: FoldersConfig{},
67 progName: ctx.App.Name,
68 WebAppDir: "webapp/dist",
69 HTTPPort: DefaultPort,
70 ShareRootDir: DefaultShareDir,
75 // config file settings overwrite default config
76 err = updateConfigFromFile(&c, ctx.GlobalString("config"))
81 // Update location of shared dir if needed
82 if !dirExists(c.ShareRootDir) {
83 if err := os.MkdirAll(c.ShareRootDir, 0770); err != nil {
84 c.Log.Fatalf("No valid shared directory found (err=%v)", err)
87 c.Log.Infoln("Share root directory: ", c.ShareRootDir)
89 // FIXME - add a builder interface and support other builder type (eg. native)
90 builderType := "syncthing"
94 // Syncthing settings only configurable from config.json file
95 stGuiAddr := c.fileConf.SThgConf.GuiAddress
96 stGuiApikey := c.fileConf.SThgConf.GuiAPIKey
98 stGuiAddr = "http://localhost:8384"
100 if stGuiAddr[0:7] != "http://" {
101 stGuiAddr = "http://" + stGuiAddr
104 // Retry if connection fail
107 c.SThg = st.NewSyncThing(stGuiAddr, stGuiApikey, c.Log)
111 c.Log.Warningf("Establishing connection to Syncthing (retry %d/5)", retry)
112 time.Sleep(time.Second)
116 c.Log.Fatalf("ERROR: cannot connect to Syncthing (url: %s)", stGuiAddr)
119 // Retrieve Syncthing config
120 id, err := c.SThg.IDGet()
125 if c.Builder, err = NewBuilderConfig(id); err != nil {
129 // Retrieve initial Syncthing config
130 stCfg, err := c.SThg.ConfigGet()
134 for _, stFld := range stCfg.Folders {
135 relativePath := strings.TrimPrefix(stFld.RawPath, c.ShareRootDir)
136 if relativePath == "" {
137 relativePath = stFld.RawPath
139 newFld := NewFolderConfig(stFld.ID, stFld.Label, c.ShareRootDir, strings.Trim(relativePath, "/"))
140 c.Folders = c.Folders.Update(FoldersConfig{newFld})
144 log.Fatalln("Unsupported builder type")
150 // GetFolderFromID retrieves the Folder config from id
151 func (c *Config) GetFolderFromID(id string) *FolderConfig {
152 if idx := c.Folders.GetIdx(id); idx != -1 {
153 return &c.Folders[idx]
158 // UpdateAll updates all the current configuration
159 func (c *Config) UpdateAll(newCfg Config) error {
160 return fmt.Errorf("Not Supported")
162 if err := VerifyConfig(newCfg); err != nil {
166 // TODO: c.Builder = c.Builder.Update(newCfg.Builder)
167 c.Folders = c.Folders.Update(newCfg.Folders)
169 // SEB A SUP model.NotifyListeners(c, NotifyFoldersChange, FolderConfig{})
170 // FIXME To be tested & improved error handling
171 for _, f := range c.Folders {
172 if err := c.SThg.FolderChange(st.FolderChangeArg{
175 RelativePath: f.RelativePath,
176 SyncThingID: f.SyncThingID,
177 ShareRootDir: c.ShareRootDir,
187 // UpdateFolder updates a specific folder into the current configuration
188 func (c *Config) UpdateFolder(newFolder FolderConfig) (FolderConfig, error) {
189 if err := FolderVerify(newFolder); err != nil {
190 return FolderConfig{}, err
193 c.Folders = c.Folders.Update(FoldersConfig{newFolder})
195 // SEB A SUP model.NotifyListeners(c, NotifyFolderAdd, newFolder)
196 err := c.SThg.FolderChange(st.FolderChangeArg{
198 Label: newFolder.Label,
199 RelativePath: newFolder.RelativePath,
200 SyncThingID: newFolder.SyncThingID,
201 ShareRootDir: c.ShareRootDir,
204 newFolder.BuilderSThgID = c.Builder.SyncThingID // FIXME - should be removed after local ST config rework
205 newFolder.Status = FolderStatusEnable
207 return newFolder, err
210 // DeleteFolder deletes a specific folder
211 func (c *Config) DeleteFolder(id string) (FolderConfig, error) {
215 //SEB A SUP model.NotifyListeners(c, NotifyFolderDelete, fld)
216 if err = c.SThg.FolderDelete(id); err != nil {
220 c.Folders, fld, err = c.Folders.Delete(id)
225 func dirExists(path string) bool {
226 _, err := os.Stat(path)
227 if os.IsNotExist(err) {