Use xds-common go library.
authorSebastien Douheret <sebastien.douheret@iot.bzh>
Mon, 26 Jun 2017 16:54:13 +0000 (18:54 +0200)
committerSebastien Douheret <sebastien.douheret@iot.bzh>
Mon, 26 Jun 2017 16:54:13 +0000 (18:54 +0200)
16 files changed:
glide.yaml
lib/apiv1/agent.go
lib/apiv1/config.go
lib/apiv1/exec.go
lib/apiv1/folders.go
lib/apiv1/make.go
lib/apiv1/sdks.go
lib/common/error.go [deleted file]
lib/common/execPipeWs.go [deleted file]
lib/common/filepath.go [deleted file]
lib/common/httpclient.go [deleted file]
lib/crosssdk/sdks.go
lib/model/folder.go
lib/syncthing/st.go
lib/xdsconfig/config.go
lib/xdsconfig/fileconfig.go

index ba6438d..aecb56c 100644 (file)
@@ -9,6 +9,10 @@ import:
 - package: github.com/gin-contrib/static
 - package: github.com/syncthing/syncthing
   version: =0.14.28
+  subpackages:
+  - lib/sync
+  - lib/config
+  - lib/protocol
 - package: github.com/codegangsta/cli
   version: ^1.19.1
 - package: github.com/Sirupsen/logrus
@@ -17,3 +21,6 @@ import:
 - package: github.com/zhouhui8915/go-socket.io-client
 - package: github.com/satori/go.uuid
   version: ^1.1.0
+- package: github.com/iotbzh/xds-common
+  subpackages:
+  - golib/common
index b693608..651f246 100644 (file)
@@ -8,7 +8,7 @@ import (
        "path/filepath"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-agent/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 type XDSAgentTarball struct {
index 326b6fa..662ec8e 100644 (file)
@@ -5,7 +5,7 @@ import (
        "sync"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
        "github.com/iotbzh/xds-server/lib/xdsconfig"
 )
 
index 4994b27..654ff64 100644 (file)
@@ -7,7 +7,7 @@ import (
        "time"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 // ExecArgs JSON parameters of /exec command
index b4d2ac0..44bda24 100644 (file)
@@ -5,7 +5,7 @@ import (
        "strconv"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
        "github.com/iotbzh/xds-server/lib/xdsconfig"
 )
 
index 77f9ec3..5cd98c6 100644 (file)
@@ -9,7 +9,7 @@ import (
        "strconv"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 // MakeArgs is the parameters (json format) of /make command
index 5ae2b03..52af506 100644 (file)
@@ -5,7 +5,7 @@ import (
        "strconv"
 
        "github.com/gin-gonic/gin"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 // getSdks returns all SDKs configuration
diff --git a/lib/common/error.go b/lib/common/error.go
deleted file mode 100644 (file)
index 6873d82..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package common
-
-import (
-       "fmt"
-
-       "github.com/gin-gonic/gin"
-)
-
-// APIError returns an uniform json formatted error
-func APIError(c *gin.Context, format string, args ...interface{}) {
-       errMsg := fmt.Sprintf(format, args...)
-       c.JSON(500, gin.H{
-               "status": "error",
-               "error":  errMsg,
-       })
-}
diff --git a/lib/common/execPipeWs.go b/lib/common/execPipeWs.go
deleted file mode 100644 (file)
index 9bb4517..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-package common
-
-import (
-       "bufio"
-       "fmt"
-       "io"
-       "os"
-       "strings"
-       "time"
-
-       "syscall"
-
-       "github.com/Sirupsen/logrus"
-       "github.com/googollee/go-socket.io"
-)
-
-// EmitOutputCB is the function callback used to emit data
-type EmitOutputCB func(sid string, cmdID int, stdout, stderr string, data *map[string]interface{})
-
-// EmitExitCB is the function callback used to emit exit proc code
-type EmitExitCB func(sid string, cmdID int, code int, err error, data *map[string]interface{})
-
-// Inspired by :
-// https://github.com/gorilla/websocket/blob/master/examples/command/main.go
-
-// ExecPipeWs executes a command and redirect stdout/stderr into a WebSocket
-func ExecPipeWs(cmd []string, env []string, so *socketio.Socket, sid string, cmdID int,
-       cmdExecTimeout int, log *logrus.Logger, eoCB EmitOutputCB, eeCB EmitExitCB, data *map[string]interface{}) error {
-
-       outr, outw, err := os.Pipe()
-       if err != nil {
-               return fmt.Errorf("Pipe stdout error: " + err.Error())
-       }
-
-       // XXX - do we need to pipe stdin one day ?
-       inr, inw, err := os.Pipe()
-       if err != nil {
-               outr.Close()
-               outw.Close()
-               return fmt.Errorf("Pipe stdin error: " + err.Error())
-       }
-
-       bashArgs := []string{"/bin/bash", "-c", strings.Join(cmd, " ")}
-       proc, err := os.StartProcess("/bin/bash", bashArgs, &os.ProcAttr{
-               Files: []*os.File{inr, outw, outw},
-               Env:   append(os.Environ(), env...),
-       })
-       if err != nil {
-               outr.Close()
-               outw.Close()
-               inr.Close()
-               inw.Close()
-               return fmt.Errorf("Process start error: " + err.Error())
-       }
-
-       go func() {
-               defer outr.Close()
-               defer outw.Close()
-               defer inr.Close()
-               defer inw.Close()
-
-               stdoutDone := make(chan struct{})
-               go cmdPumpStdout(so, outr, stdoutDone, sid, cmdID, log, eoCB, data)
-
-               // Blocking function that poll input or wait for end of process
-               cmdPumpStdin(so, inw, proc, sid, cmdID, cmdExecTimeout, log, eeCB, data)
-
-               // Some commands will exit when stdin is closed.
-               inw.Close()
-
-               defer outr.Close()
-
-               if status, err := proc.Wait(); err == nil {
-                       // Other commands need a bonk on the head.
-                       if !status.Exited() {
-                               if err := proc.Signal(os.Interrupt); err != nil {
-                                       log.Errorln("Proc interrupt:", err)
-                               }
-
-                               select {
-                               case <-stdoutDone:
-                               case <-time.After(time.Second):
-                                       // A bigger bonk on the head.
-                                       if err := proc.Signal(os.Kill); err != nil {
-                                               log.Errorln("Proc term:", err)
-                                       }
-                                       <-stdoutDone
-                               }
-                       }
-               }
-       }()
-
-       return nil
-}
-
-func cmdPumpStdin(so *socketio.Socket, w io.Writer, proc *os.Process,
-       sid string, cmdID int, tmo int, log *logrus.Logger, exitFuncCB EmitExitCB,
-       data *map[string]interface{}) {
-       /* XXX - code to add to support stdin through WS
-       for {
-               _, message, err := so. ?? ReadMessage()
-               if err != nil {
-                       break
-               }
-               message = append(message, '\n')
-               if _, err := w.Write(message); err != nil {
-                       break
-               }
-       }
-       */
-
-       // Monitor process exit
-       type DoneChan struct {
-               status int
-               err    error
-       }
-       done := make(chan DoneChan, 1)
-       go func() {
-               status := 0
-               sts, err := proc.Wait()
-               if !sts.Success() {
-                       s := sts.Sys().(syscall.WaitStatus)
-                       status = s.ExitStatus()
-               }
-               done <- DoneChan{status, err}
-       }()
-
-       // Wait cmd complete
-       select {
-       case dC := <-done:
-               exitFuncCB(sid, cmdID, dC.status, dC.err, data)
-       case <-time.After(time.Duration(tmo) * time.Second):
-               exitFuncCB(sid, cmdID, -99,
-                       fmt.Errorf("Exit Timeout for command ID %v", cmdID), data)
-       }
-}
-
-func cmdPumpStdout(so *socketio.Socket, r io.Reader, done chan struct{},
-       sid string, cmdID int, log *logrus.Logger, emitFuncCB EmitOutputCB, data *map[string]interface{}) {
-       defer func() {
-       }()
-
-       sc := bufio.NewScanner(r)
-       for sc.Scan() {
-               emitFuncCB(sid, cmdID, string(sc.Bytes()), "", data)
-       }
-       if sc.Err() != nil {
-               log.Errorln("scan:", sc.Err())
-       }
-       close(done)
-}
diff --git a/lib/common/filepath.go b/lib/common/filepath.go
deleted file mode 100644 (file)
index 8101c5a..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-package common
-
-import (
-       "fmt"
-       "os"
-       "os/user"
-       "path"
-       "path/filepath"
-       "regexp"
-       "strings"
-)
-
-// 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
-}
-
-// ResolveEnvVar Resolved environment variable regarding the syntax ${MYVAR}
-// or $MYVAR following by a slash or a backslash
-func ResolveEnvVar(s string) (string, error) {
-       if s == "" {
-               return s, nil
-       }
-
-       // Resolved tilde : ~/
-       if len(s) > 2 && s[:2] == "~/" {
-               if usr, err := user.Current(); err == nil {
-                       s = filepath.Join(usr.HomeDir, s[2:])
-               }
-       }
-
-       // Resolved ${MYVAR}
-       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])
-               }
-
-               rer := regexp.MustCompile("\\${" + v[1] + "}")
-               res = rer.ReplaceAllString(res, val)
-       }
-
-       // Resolved $MYVAR following by a slash (or a backslash for Windows)
-       // TODO
-       //re := regexp.MustCompile("\\$([^\\/])+/")
-
-       return path.Clean(res), nil
-}
-
-// PathNormalize
-func PathNormalize(p string) string {
-       sep := string(filepath.Separator)
-       if sep != "/" {
-               return p
-       }
-       // Replace drive like C: by C/
-       res := p
-       if p[1:2] == ":" {
-               res = p[0:1] + sep + p[2:]
-       }
-       res = strings.Replace(res, "\\", "/", -1)
-       return filepath.Clean(res)
-}
diff --git a/lib/common/httpclient.go b/lib/common/httpclient.go
deleted file mode 100644 (file)
index 72132bf..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-package common
-
-import (
-       "bytes"
-       "crypto/tls"
-       "encoding/json"
-       "errors"
-       "fmt"
-       "io/ioutil"
-       "net/http"
-       "strings"
-
-       "github.com/Sirupsen/logrus"
-)
-
-type HTTPClient struct {
-       httpClient http.Client
-       endpoint   string
-       apikey     string
-       username   string
-       password   string
-       id         string
-       csrf       string
-       conf       HTTPClientConfig
-       logger     *logrus.Logger
-}
-
-type HTTPClientConfig struct {
-       URLPrefix           string
-       HeaderAPIKeyName    string
-       Apikey              string
-       HeaderClientKeyName string
-       CsrfDisable         bool
-}
-
-const (
-       logError   = 1
-       logWarning = 2
-       logInfo    = 3
-       logDebug   = 4
-)
-
-// Inspired by syncthing/cmd/cli
-
-const insecure = false
-
-// HTTPNewClient creates a new HTTP client to deal with Syncthing
-func HTTPNewClient(baseURL string, cfg HTTPClientConfig) (*HTTPClient, error) {
-
-       // Create w new Http client
-       httpClient := http.Client{
-               Transport: &http.Transport{
-                       TLSClientConfig: &tls.Config{
-                               InsecureSkipVerify: insecure,
-                       },
-               },
-       }
-       client := HTTPClient{
-               httpClient: httpClient,
-               endpoint:   baseURL,
-               apikey:     cfg.Apikey,
-               conf:       cfg,
-               /* TODO - add user + pwd support
-               username:   c.GlobalString("username"),
-               password:   c.GlobalString("password"),
-               */
-       }
-
-       if client.apikey == "" {
-               if err := client.getCidAndCsrf(); err != nil {
-                       return nil, err
-               }
-       }
-       return &client, nil
-}
-
-// SetLogger Define the logger to use
-func (c *HTTPClient) SetLogger(log *logrus.Logger) {
-       c.logger = log
-}
-
-func (c *HTTPClient) log(level int, format string, args ...interface{}) {
-       if c.logger != nil {
-               switch level {
-               case logError:
-                       c.logger.Errorf(format, args...)
-                       break
-               case logWarning:
-                       c.logger.Warningf(format, args...)
-                       break
-               case logInfo:
-                       c.logger.Infof(format, args...)
-                       break
-               default:
-                       c.logger.Debugf(format, args...)
-                       break
-               }
-       }
-}
-
-// Send request to retrieve Client id and/or CSRF token
-func (c *HTTPClient) getCidAndCsrf() error {
-       request, err := http.NewRequest("GET", c.endpoint, nil)
-       if err != nil {
-               return err
-       }
-       if _, err := c.handleRequest(request); err != nil {
-               return err
-       }
-       if c.id == "" {
-               return errors.New("Failed to get device ID")
-       }
-       if !c.conf.CsrfDisable && c.csrf == "" {
-               return errors.New("Failed to get CSRF token")
-       }
-       return nil
-}
-
-// GetClientID returns the id
-func (c *HTTPClient) GetClientID() string {
-       return c.id
-}
-
-// formatURL Build full url by concatenating all parts
-func (c *HTTPClient) formatURL(endURL string) string {
-       url := c.endpoint
-       if !strings.HasSuffix(url, "/") {
-               url += "/"
-       }
-       url += strings.TrimLeft(c.conf.URLPrefix, "/")
-       if !strings.HasSuffix(url, "/") {
-               url += "/"
-       }
-       return url + strings.TrimLeft(endURL, "/")
-}
-
-// HTTPGet Send a Get request to client and return an error object
-func (c *HTTPClient) HTTPGet(url string, data *[]byte) error {
-       _, err := c.HTTPGetWithRes(url, data)
-       return err
-}
-
-// HTTPGetWithRes Send a Get request to client and return both response and error
-func (c *HTTPClient) HTTPGetWithRes(url string, data *[]byte) (*http.Response, error) {
-       request, err := http.NewRequest("GET", c.formatURL(url), nil)
-       if err != nil {
-               return nil, err
-       }
-       res, err := c.handleRequest(request)
-       if err != nil {
-               return res, err
-       }
-       if res.StatusCode != 200 {
-               return res, errors.New(res.Status)
-       }
-
-       *data = c.responseToBArray(res)
-
-       return res, nil
-}
-
-// HTTPPost Send a POST request to client and return an error object
-func (c *HTTPClient) HTTPPost(url string, body string) error {
-       _, err := c.HTTPPostWithRes(url, body)
-       return err
-}
-
-// HTTPPostWithRes Send a POST request to client and return both response and error
-func (c *HTTPClient) HTTPPostWithRes(url string, body string) (*http.Response, error) {
-       request, err := http.NewRequest("POST", c.formatURL(url), bytes.NewBufferString(body))
-       if err != nil {
-               return nil, err
-       }
-       res, err := c.handleRequest(request)
-       if err != nil {
-               return res, err
-       }
-       if res.StatusCode != 200 {
-               return res, errors.New(res.Status)
-       }
-       return res, nil
-}
-
-func (c *HTTPClient) responseToBArray(response *http.Response) []byte {
-       defer response.Body.Close()
-       bytes, err := ioutil.ReadAll(response.Body)
-       if err != nil {
-               // TODO improved error reporting
-               fmt.Println("ERROR: " + err.Error())
-       }
-       return bytes
-}
-
-func (c *HTTPClient) handleRequest(request *http.Request) (*http.Response, error) {
-       if c.conf.HeaderAPIKeyName != "" && c.apikey != "" {
-               request.Header.Set(c.conf.HeaderAPIKeyName, c.apikey)
-       }
-       if c.conf.HeaderClientKeyName != "" && c.id != "" {
-               request.Header.Set(c.conf.HeaderClientKeyName, c.id)
-       }
-       if c.username != "" || c.password != "" {
-               request.SetBasicAuth(c.username, c.password)
-       }
-       if c.csrf != "" {
-               request.Header.Set("X-CSRF-Token-"+c.id[:5], c.csrf)
-       }
-
-       c.log(logDebug, "HTTP %s %v", request.Method, request.URL)
-
-       response, err := c.httpClient.Do(request)
-       if err != nil {
-               return nil, err
-       }
-
-       // Detect client ID change
-       cid := response.Header.Get(c.conf.HeaderClientKeyName)
-       if cid != "" && c.id != cid {
-               c.id = cid
-       }
-
-       // Detect CSR token change
-       for _, item := range response.Cookies() {
-               if item.Name == "CSRF-Token-"+c.id[:5] {
-                       c.csrf = item.Value
-                       goto csrffound
-               }
-       }
-       // OK CSRF found
-csrffound:
-
-       if response.StatusCode == 404 {
-               return nil, errors.New("Invalid endpoint or API call")
-       } else if response.StatusCode == 401 {
-               return nil, errors.New("Invalid username or password")
-       } else if response.StatusCode == 403 {
-               if c.apikey == "" {
-                       // Request a new Csrf for next requests
-                       c.getCidAndCsrf()
-                       return nil, errors.New("Invalid CSRF token")
-               }
-               return nil, errors.New("Invalid API key")
-       } else if response.StatusCode != 200 {
-               data := make(map[string]interface{})
-               // Try to decode error field of APIError struct
-               json.Unmarshal(c.responseToBArray(response), &data)
-               if err, found := data["error"]; found {
-                       return nil, fmt.Errorf(err.(string))
-               } else {
-                       body := strings.TrimSpace(string(c.responseToBArray(response)))
-                       if body != "" {
-                               return nil, fmt.Errorf(body)
-                       }
-               }
-               return nil, errors.New("Unknown HTTP status returned: " + response.Status)
-       }
-       return response, nil
-}
index d08afc5..35a9998 100644 (file)
@@ -6,7 +6,7 @@ import (
        "sync"
 
        "github.com/Sirupsen/logrus"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
        "github.com/iotbzh/xds-server/lib/xdsconfig"
 )
 
index c73accc..56a46b1 100644 (file)
@@ -3,7 +3,7 @@ package model
 import (
        "fmt"
 
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
        "github.com/iotbzh/xds-server/lib/syncthing"
        "github.com/iotbzh/xds-server/lib/xdsconfig"
 )
index e4506a5..3380cda 100644 (file)
@@ -20,7 +20,7 @@ import (
        "regexp"
 
        "github.com/Sirupsen/logrus"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
        "github.com/iotbzh/xds-server/lib/xdsconfig"
        "github.com/syncthing/syncthing/lib/config"
 )
index 5ada35f..f2d0710 100644 (file)
@@ -7,7 +7,7 @@ import (
 
        "github.com/Sirupsen/logrus"
        "github.com/codegangsta/cli"
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 // Config parameters (json format) of /config command
index 99e5382..90c1aad 100644 (file)
@@ -8,7 +8,7 @@ import (
        "path/filepath"
        "strings"
 
-       "github.com/iotbzh/xds-server/lib/common"
+       common "github.com/iotbzh/xds-common/golib"
 )
 
 type SyncThingConf struct {