From ea3b17feb2eb2d54bbc27dc75eee60bd1fe67d27 Mon Sep 17 00:00:00 2001
From: Sebastien Douheret <sebastien.douheret@iot.bzh>
Date: Mon, 26 Jun 2017 18:54:13 +0200
Subject: Use xds-common go library.

---
 lib/common/error.go      |  16 ---
 lib/common/execPipeWs.go | 151 ----------------------------
 lib/common/filepath.go   |  73 --------------
 lib/common/httpclient.go | 257 -----------------------------------------------
 4 files changed, 497 deletions(-)
 delete mode 100644 lib/common/error.go
 delete mode 100644 lib/common/execPipeWs.go
 delete mode 100644 lib/common/filepath.go
 delete mode 100644 lib/common/httpclient.go

(limited to 'lib/common')

diff --git a/lib/common/error.go b/lib/common/error.go
deleted file mode 100644
index 6873d82..0000000
--- a/lib/common/error.go
+++ /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
index 9bb4517..0000000
--- a/lib/common/execPipeWs.go
+++ /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
index 8101c5a..0000000
--- a/lib/common/filepath.go
+++ /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
index 72132bf..0000000
--- a/lib/common/httpclient.go
+++ /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
-}
-- 
cgit