summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-11-24 01:28:00 +0100
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-11-24 01:28:00 +0100
commit67a7d6e46143410a5fa9cfa2554023ab7687ea34 (patch)
tree6168592c5cc72a39795aa49a5683a81f2b872a19
parentd2335afe1058153a3aad27fa483499b0639e096c (diff)
Add folder update support and ClientData field.
- folder config can be updated using PUT /folders/:id route - ClientData field of FolderConfig can be used by client to store any data (used from example by dashboard to save build settings)
-rw-r--r--.vscode/settings.json88
-rw-r--r--glide.yaml2
-rw-r--r--lib/apiv1/apiv1.go1
-rw-r--r--lib/apiv1/events.go22
-rw-r--r--lib/apiv1/folders.go24
-rw-r--r--lib/folder/folder-interface.go7
-rw-r--r--lib/folder/folder-pathmap.go9
-rw-r--r--lib/folder/folder-st-disable.go5
-rw-r--r--lib/model/folders.go49
-rw-r--r--lib/syncthing/folder-st.go9
10 files changed, 151 insertions, 65 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d2c6144..569ca52 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,61 +1,33 @@
// Place your settings in this file to overwrite default and user settings.
{
- // Configure glob patterns for excluding files and folders.
- "files.exclude": {
- ".tmp": true,
- ".git": true,
- "glide.lock": true,
- "vendor": true,
- "debug": true,
- "bin": true,
- "tools": true,
- "webapp/dist": true,
- "webapp/node_modules": true
- },
- // Specify paths/files to ignore. (Supports Globs)
- "cSpell.ignorePaths": [
- "**/node_modules/**",
- "**/vscode-extension/**",
- "**/.git/**",
- "**/vendor/**",
- ".vscode",
- "typings"
- ],
- // Words to add to dictionary for a workspace.
- "cSpell.words": [
- "apiv",
- "gonic",
- "devel",
- "csrffound",
- "Syncthing",
- "STID",
- "ISTCONFIG",
- "socketio",
- "ldflags",
- "SThg",
- "Intf",
- "dismissible",
- "rpath",
- "WSID",
- "sess",
- "IXDS",
- "xdsconfig",
- "xdsserver",
- "mfolder",
- "inotify",
- "Inot",
- "pname",
- "pkill",
- "sdkid",
- "CLOUDSYNC",
- "xdsagent",
- "gdbserver",
- "golib",
- "eows",
- "mfolders",
- "IFOLDER",
- "flds",
- "dflt",
- "stconfig"
- ]
+ // Configure glob patterns for excluding files and folders.
+ "files.exclude": {
+ ".tmp": true,
+ ".git": true,
+ "glide.lock": true,
+ "vendor": true,
+ "debug": true,
+ "bin": true,
+ "tools": true,
+ "webapp/dist": true,
+ "webapp/node_modules": true
+ },
+ // Specify paths/files to ignore. (Supports Globs)
+ "cSpell.ignorePaths": [
+ "**/node_modules/**",
+ "**/vscode-extension/**",
+ "**/.git/**",
+ "**/vendor/**",
+ ".vscode",
+ "typings"
+ ],
+ // Words to add to dictionary for a workspace.
+ "cSpell.words": [
+ "apiv", "gonic", "devel", "csrffound", "Syncthing", "STID",
+ "ISTCONFIG", "socketio", "ldflags", "SThg", "Intf", "dismissible",
+ "rpath", "WSID", "sess", "IXDS", "xdsconfig", "xdsserver", "mfolder",
+ "inotify", "Inot", "pname", "pkill", "sdkid", "CLOUDSYNC", "xdsagent",
+ "gdbserver", "golib", "eows", "mfolders", "IFOLDER", "flds", "dflt",
+ "stconfig", "reflectme", "franciscocpg"
+ ]
}
diff --git a/glide.yaml b/glide.yaml
index 94ef2db..fcd0f5c 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -31,3 +31,5 @@ import:
- golib/eows
- package: github.com/kr/pty
version: ^1.0.0
+- package: github.com/franciscocpg/reflectme
+ version: ^0.1.9
diff --git a/lib/apiv1/apiv1.go b/lib/apiv1/apiv1.go
index d10a08e..fffed2d 100644
--- a/lib/apiv1/apiv1.go
+++ b/lib/apiv1/apiv1.go
@@ -40,6 +40,7 @@ func New(r *gin.Engine, sess *session.Sessions, cfg *xdsconfig.Config, mfolders
s.apiRouter.GET("/folders", s.getFolders)
s.apiRouter.GET("/folders/:id", s.getFolder)
+ s.apiRouter.PUT("/folders/:id", s.updateFolder)
s.apiRouter.POST("/folders", s.addFolder)
s.apiRouter.POST("/folders/sync/:id", s.syncFolder)
s.apiRouter.DELETE("/folders/:id", s.delFolder)
diff --git a/lib/apiv1/events.go b/lib/apiv1/events.go
index 9444262..d837571 100644
--- a/lib/apiv1/events.go
+++ b/lib/apiv1/events.go
@@ -2,6 +2,7 @@ package apiv1
import (
"net/http"
+ "strings"
"time"
"github.com/iotbzh/xds-server/lib/folder"
@@ -29,8 +30,15 @@ type EventMsg struct {
}
// EventEvent Event send in WS when an internal event (eg. Syncthing event is received)
-const EventEventAll = "event:all"
-const EventEventType = "event:" // following by event type
+const (
+ // EventTypePrefix Used as event prefix
+ EventTypePrefix = "event:" // following by event type
+
+ // Supported Events type
+ EVTAll = EventTypePrefix + "all"
+ EVTFolderChange = EventTypePrefix + "folder-change" // type EventMsg with Data type apiv1.???
+ EVTFolderStateChange = EventTypePrefix + "folder-state-change" // type EventMsg with Data type apiv1.???
+)
// eventsList Registering for events that will be send over a WS
func (s *APIService) eventsList(c *gin.Context) {
@@ -52,7 +60,7 @@ func (s *APIService) eventsRegister(c *gin.Context) {
return
}
- evType := "FolderStateChanged"
+ evType := strings.TrimPrefix(EVTFolderStateChange, EventTypePrefix)
if args.Name != evType {
common.APIError(c, "Unsupported event name")
return
@@ -79,11 +87,11 @@ func (s *APIService) eventsRegister(c *gin.Context) {
Data: ev.Data,
}
- if err := (*so).Emit(EventEventAll, msg); err != nil {
+ if err := (*so).Emit(EVTAll, msg); err != nil {
s.log.Errorf("WS Emit Event : %v", err)
}
- if err := (*so).Emit(EventEventType+ev.Type, msg); err != nil {
+ if err := (*so).Emit(EventTypePrefix+ev.Type, msg); err != nil {
s.log.Errorf("WS Emit Event : %v", err)
}
}
@@ -113,9 +121,9 @@ func (s *APIService) eventsRegister(c *gin.Context) {
}
s.log.Debugf("WS Emit %s - Status=%10s, IsInSync=%6v, ID=%s",
- EventEventType+evType, cfg.Status, cfg.IsInSync, cfg.ID)
+ EventTypePrefix+evType, cfg.Status, cfg.IsInSync, cfg.ID)
- if err := (*so).Emit(EventEventType+evType, msg); err != nil {
+ if err := (*so).Emit(EventTypePrefix+evType, msg); err != nil {
s.log.Errorf("WS Emit Folder StateChanged event : %v", err)
}
}
diff --git a/lib/apiv1/folders.go b/lib/apiv1/folders.go
index 398e21c..073445c 100644
--- a/lib/apiv1/folders.go
+++ b/lib/apiv1/folders.go
@@ -105,3 +105,27 @@ func (s *APIService) delFolder(c *gin.Context) {
}
c.JSON(http.StatusOK, delEntry)
}
+
+// updateFolder update some field of a folder
+func (s *APIService) updateFolder(c *gin.Context) {
+ id, err := s.mfolders.ResolveID(c.Param("id"))
+ if err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ s.log.Debugln("Update folder id ", id)
+
+ var cfgArg folder.FolderConfig
+ if c.BindJSON(&cfgArg) != nil {
+ common.APIError(c, "Invalid arguments")
+ return
+ }
+
+ upFld, err := s.mfolders.Update(id, cfgArg)
+ if err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+ c.JSON(http.StatusOK, upFld)
+}
diff --git a/lib/folder/folder-interface.go b/lib/folder/folder-interface.go
index 9eb6829..3208869 100644
--- a/lib/folder/folder-interface.go
+++ b/lib/folder/folder-interface.go
@@ -30,6 +30,7 @@ type IFOLDER interface {
ConvPathCli2Svr(s string) string // Convert path from Client to Server
ConvPathSvr2Cli(s string) string // Convert path from Server to Client
Remove() error // Remove a folder
+ Update(cfg FolderConfig) (*FolderConfig, error) // Update a new folder
RegisterEventChange(cb *EventCB, data *EventCBData) error // Request events registration (sent through WS)
UnRegisterEventChange() error // Un-register events
Sync() error // Force folder files synchronization
@@ -45,6 +46,7 @@ type FolderConfig struct {
Status string `json:"status"`
IsInSync bool `json:"isInSync"`
DefaultSdk string `json:"defaultSdk"`
+ ClientData string `json:"clientData"` // free form field that can used by client
// Not exported fields from REST API point of view
RootPath string `json:"-"`
@@ -58,6 +60,11 @@ type FolderConfig struct {
DataCloudSync CloudSyncConfig `json:"dataCloudSync,omitempty"`
}
+// FolderConfigUpdatableFields List fields that can be updated using Update function
+var FolderConfigUpdatableFields = []string{
+ "Label", "DefaultSdk", "ClientData",
+}
+
// PathMapConfig Path mapping specific data
type PathMapConfig struct {
ServerPath string `json:"serverPath"`
diff --git a/lib/folder/folder-pathmap.go b/lib/folder/folder-pathmap.go
index e200164..c5691a3 100644
--- a/lib/folder/folder-pathmap.go
+++ b/lib/folder/folder-pathmap.go
@@ -145,6 +145,15 @@ func (f *PathMap) Remove() error {
return nil
}
+// Update update some fields of a folder
+func (f *PathMap) Update(cfg FolderConfig) (*FolderConfig, error) {
+ if f.config.ID != cfg.ID {
+ return nil, fmt.Errorf("Invalid id")
+ }
+ f.config = cfg
+ return &f.config, nil
+}
+
// RegisterEventChange requests registration for folder change event
func (f *PathMap) RegisterEventChange(cb *EventCB, data *EventCBData) error {
return nil
diff --git a/lib/folder/folder-st-disable.go b/lib/folder/folder-st-disable.go
index 7b53ca8..e936494 100644
--- a/lib/folder/folder-st-disable.go
+++ b/lib/folder/folder-st-disable.go
@@ -65,6 +65,11 @@ func (f *STFolderDisable) Remove() error {
return nil
}
+// Update update some fields of a folder
+func (f *STFolderDisable) Update(cfg FolderConfig) (*FolderConfig, error) {
+ return nil, nil
+}
+
// RegisterEventChange requests registration for folder change event
func (f *STFolderDisable) RegisterEventChange(cb *EventCB, data *EventCBData) error {
return nil
diff --git a/lib/model/folders.go b/lib/model/folders.go
index b8e6cf5..0e28538 100644
--- a/lib/model/folders.go
+++ b/lib/model/folders.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/Sirupsen/logrus"
+ "github.com/franciscocpg/reflectme"
common "github.com/iotbzh/xds-common/golib"
"github.com/iotbzh/xds-server/lib/folder"
"github.com/iotbzh/xds-server/lib/syncthing"
@@ -318,6 +319,54 @@ func (f *Folders) Delete(id string) (folder.FolderConfig, error) {
return fld, err
}
+// Update Update a specific folder
+func (f *Folders) Update(id string, cfg folder.FolderConfig) (*folder.FolderConfig, error) {
+ fcMutex.Lock()
+ defer fcMutex.Unlock()
+
+ fc, exist := f.folders[id]
+ if !exist {
+ return nil, fmt.Errorf("unknown id")
+ }
+
+ // Copy current in a new object to change nothing in case of an error rises
+ newCfg := folder.FolderConfig{}
+ reflectme.Copy((*fc).GetConfig(), &newCfg)
+
+ // Only update some fields
+ dirty := false
+ for _, fieldName := range folder.FolderConfigUpdatableFields {
+ valNew, err := reflectme.GetField(cfg, fieldName)
+ if err == nil {
+ valCur, err := reflectme.GetField(newCfg, fieldName)
+ if err == nil && valNew != valCur {
+ err = reflectme.SetField(&newCfg, fieldName, valNew)
+ if err != nil {
+ return nil, err
+ }
+ dirty = true
+ }
+ }
+ }
+
+ if !dirty {
+ return &newCfg, nil
+ }
+
+ fld, err := (*fc).Update(newCfg)
+ if err != nil {
+ return fld, err
+ }
+
+ // Save config on disk
+ err = f.SaveConfig()
+
+ // Send event to notified changes
+ // TODO emit folder change event
+
+ return fld, err
+}
+
// RegisterEventChange requests registration for folder event change
func (f *Folders) RegisterEventChange(id string, cb *folder.EventCB, data *folder.EventCBData) error {
diff --git a/lib/syncthing/folder-st.go b/lib/syncthing/folder-st.go
index f25a505..74aa4bb 100644
--- a/lib/syncthing/folder-st.go
+++ b/lib/syncthing/folder-st.go
@@ -143,6 +143,15 @@ func (f *STFolder) Remove() error {
return err2
}
+// Update update some fields of a folder
+func (f *STFolder) Update(cfg folder.FolderConfig) (*folder.FolderConfig, error) {
+ if f.fConfig.ID != cfg.ID {
+ return nil, fmt.Errorf("Invalid id")
+ }
+ f.fConfig = cfg
+ return &f.fConfig, nil
+}
+
// RegisterEventChange requests registration for folder event change
func (f *STFolder) RegisterEventChange(cb *folder.EventCB, data *folder.EventCBData) error {
f.eventChangeCB = cb