From 32791ffed5bdfaa698e90f9c067dc6e8ababbfc3 Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Wed, 29 Nov 2017 11:06:15 +0100 Subject: [PATCH 01/16] Fixed /exec input stream and /signal. Signed-off-by: Sebastien Douheret --- .vscode/settings.json | 2 +- Makefile | 2 +- glide.yaml | 2 +- lib/agent/apiv1-exec.go | 159 ++++++++++++++++++++++++++++++++++++------------ lib/agent/apiv1.go | 2 +- lib/agent/xdsserver.go | 48 +++++++++++++++ lib/xaapiv1/exec.go | 12 ++++ lib/xdsconfig/config.go | 2 +- 8 files changed, 184 insertions(+), 45 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 7ef453d..f5c711f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -40,7 +40,7 @@ "iosk", "CIFS", "IPROJECT", "unregister", "conv", "PATHMAP", "nospace", "graphx", "Truthy", "darkviolet", "dwnl", "topnav", "leftbar", "urfave", "unmarshall", "sebd", "priv", "evts", "gdbserver", "tabset", "pageview", - "subpath", "prebuild", "reflectme", "franciscocpg" + "subpath", "prebuild", "reflectme", "franciscocpg", "xsapiv", "xaapiv" ], // codelyzer "tslint.rulesDirectory": "./webapp/node_modules/codelyzer", diff --git a/Makefile b/Makefile index 802aede..f448d72 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ vendor: tools/glide glide.yaml vendor/debug: vendor (cd vendor/github.com/iotbzh && \ - rm -rf xds-common && ln -s ../../../../xds-common && \ + rm -rf xds-common && ln -s ../../../../xds-common \ rm -rf xds-server && ln -s ../../../../xds-server ) .PHONY: tools/glide diff --git a/glide.yaml b/glide.yaml index 0569d76..cb7a769 100644 --- a/glide.yaml +++ b/glide.yaml @@ -28,6 +28,6 @@ import: - package: github.com/iotbzh/xds-server version: 5c1d023f41472660952ee559e2484cd6bbe688d3 subpackages: - - lib/xsapiv1 + - xsapiv1 - package: github.com/franciscocpg/reflectme version: ^0.1.9 diff --git a/lib/agent/apiv1-exec.go b/lib/agent/apiv1-exec.go index 3cb4d23..5fdfb9d 100644 --- a/lib/agent/apiv1-exec.go +++ b/lib/agent/apiv1-exec.go @@ -1,37 +1,22 @@ package agent import ( - "encoding/json" - "io/ioutil" "net/http" "github.com/franciscocpg/reflectme" "github.com/gin-gonic/gin" - "github.com/iotbzh/xds-agent/lib/apiv1" + "github.com/iotbzh/xds-agent/lib/xaapiv1" common "github.com/iotbzh/xds-common/golib" + "github.com/iotbzh/xds-server/lib/xsapiv1" uuid "github.com/satori/go.uuid" ) // ExecCmd executes remotely a command func (s *APIService) execCmd(c *gin.Context) { - s._execRequest("/exec", c) -} - -// execSignalCmd executes remotely a command -func (s *APIService) execSignalCmd(c *gin.Context) { - s._execRequest("/signal", c) -} - -func (s *APIService) _execRequest(cmd string, c *gin.Context) { - data, err := c.GetRawData() - if err != nil { - common.APIError(c, err.Error()) - } - args := apiv1.ExecArgs{} - // XXX - we cannot use c.BindJSON, so directly unmarshall it - // (see https://github.com/gin-gonic/gin/issues/1078) - if err := json.Unmarshal(data, &args); err != nil { + args := xaapiv1.ExecArgs{} + if err := c.BindJSON(&args); err != nil { + s.Log.Warningf("/exec invalid args, err=%v", err) common.APIError(c, "Invalid arguments") return } @@ -70,17 +55,36 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) { return } - // Forward XDSServer WS events to client WS - // TODO removed static event name list and get it from XDSServer - evtList := []string{ - apiv1.ExecInEvent, - apiv1.ExecOutEvent, - apiv1.ExecInferiorInEvent, - apiv1.ExecInferiorOutEvent, + // Forward input events from client to XDSServer through WS + // TODO use XDSServer events names definition + evtInList := []string{ + xaapiv1.ExecInEvent, + xaapiv1.ExecInferiorInEvent, + } + for _, evName := range evtInList { + evN := evName + err := (*sock).On(evN, func(stdin string) { + if s.LogLevelSilly { + s.Log.Debugf("EXEC EVENT IN (%s) <<%v>>", evN, stdin) + } + svr.EventEmit(evN, stdin) + }) + if err != nil { + msgErr := "Error while registering WS for " + evN + " event" + s.Log.Errorf(msgErr, ", err: %v", err) + common.APIError(c, msgErr) + return + } } + // Forward output events from XDSServer to client through WS + // TODO use XDSServer events names definition var fwdFuncID []uuid.UUID - for _, evName := range evtList { + evtOutList := []string{ + xaapiv1.ExecOutEvent, + xaapiv1.ExecInferiorOutEvent, + } + for _, evName := range evtOutList { evN := evName fwdFunc := func(pData interface{}, evData interface{}) error { sid := pData.(string) @@ -94,6 +98,10 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) { // Add sessionID to event Data reflectme.SetField(evData, "sessionID", sid) + if s.LogLevelSilly { + s.Log.Debugf("EXEC EVENT OUT (%s) <<%v>>", evN, evData) + } + // Forward event to Client/Dashboard (*so).Emit(evN, evData) return nil @@ -108,9 +116,12 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) { // Handle Exit event separately to cleanup registered listener var exitFuncID uuid.UUID - exitFunc := func(pData interface{}, evData interface{}) error { - evN := apiv1.ExecExitEvent - sid := pData.(string) + exitFunc := func(privD interface{}, evData interface{}) error { + evN := xaapiv1.ExecExitEvent + + pData := privD.(map[string]string) + sid := pData["sessID"] + prjID := pData["prjID"] // Add sessionID to event Data reflectme.SetField(evData, "sessionID", sid) @@ -123,32 +134,100 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) { s.Log.Infof("%s not emitted: WS closed (sid:%s)", evN, sid) } + prj := s.projects.Get(prjID) + if prj != nil { + evD := evData.(map[string]interface{}) + cmdIDData, cmdIDExist := evD["cmdID"] + svr := (*prj).GetServer() + if svr != nil && cmdIDExist { + svr.CommandDelete(cmdIDData.(string)) + } else { + s.Log.Infof("%s: cannot retrieve server for sid=%s, prjID=%s, evD=%v", evN, sid, prjID, evD) + } + } else { + s.Log.Infof("%s: cannot retrieve project for sid=%s, prjID=%s", evN, sid, prjID) + } + // cleanup listener - for i, evName := range evtList { + for i, evName := range evtOutList { svr.EventOff(evName, fwdFuncID[i]) } svr.EventOff(evN, exitFuncID) return nil } - exitFuncID, err = svr.EventOn(apiv1.ExecExitEvent, sess.ID, exitFunc) + + prjCfg := (*prj).GetProject() + privData := map[string]string{"sessID": sess.ID, "prjID": prjCfg.ID} + exitFuncID, err = svr.EventOn(xaapiv1.ExecExitEvent, privData, exitFunc) if err != nil { common.APIError(c, err.Error()) return } // Forward back command to right server - response, err := svr.SendCommand(cmd, data) - if err != nil { + res := xsapiv1.ExecResult{} + xsArgs := &xsapiv1.ExecArgs{ + ID: args.ID, + SdkID: args.SdkID, + CmdID: args.CmdID, + Cmd: args.Cmd, + Args: args.Args, + Env: args.Env, + RPath: args.RPath, + TTY: args.TTY, + TTYGdbserverFix: args.TTYGdbserverFix, + ExitImmediate: args.ExitImmediate, + CmdTimeout: args.CmdTimeout, + } + if err := svr.CommandExec(xsArgs, &res); err != nil { common.APIError(c, err.Error()) return } - // Decode response - body, err := ioutil.ReadAll(response.Body) - if err != nil { - common.APIError(c, "Cannot read response body") + // Add command to running commands list + if err := svr.CommandAdd(res.CmdID, xsArgs); err != nil { + common.APIError(c, err.Error()) + return + } + + c.JSON(http.StatusOK, xaapiv1.ExecResult{Status: res.Status, CmdID: res.CmdID}) +} + +// execSignalCmd executes remotely the signal command +func (s *APIService) execSignalCmd(c *gin.Context) { + + args := xaapiv1.ExecSignalArgs{} + if err := c.BindJSON(&args); err != nil { + s.Log.Warningf("/signal invalid args, err=%v", err) + common.APIError(c, "Invalid arguments") return } - c.JSON(http.StatusOK, string(body)) + + // Retrieve on which xds-server the command is running + var svr *XdsServer + var dataCmd interface{} + for _, svr = range s.xdsServers { + dataCmd = svr.CommandGet(args.CmdID) + if dataCmd != nil { + break + } + } + if dataCmd == nil { + common.APIError(c, "Cannot retrieve XDS Server for this cmdID") + return + } + + // Forward back command to right server + res := xsapiv1.ExecSigResult{} + xsArgs := &xsapiv1.ExecSignalArgs{ + CmdID: args.CmdID, + Signal: args.Signal, + } + if err := svr.CommandSignal(xsArgs, &res); err != nil { + common.APIError(c, err.Error()) + return + } + + c.JSON(http.StatusOK, xaapiv1.ExecSignalResult{Status: res.Status, CmdID: res.CmdID}) } diff --git a/lib/agent/apiv1.go b/lib/agent/apiv1.go index 36e5a54..1051f2a 100644 --- a/lib/agent/apiv1.go +++ b/lib/agent/apiv1.go @@ -84,7 +84,7 @@ func (s *APIService) AddXdsServer(cfg xdsconfig.XDSServerConf) (*XdsServer, erro cfg.APIBaseURL = apiBaseURL } if cfg.APIPartialURL == "" { - cfg.APIPartialURL = "/server/" + strconv.Itoa(s.serverIndex) + cfg.APIPartialURL = "/servers/" + strconv.Itoa(s.serverIndex) s.serverIndex = s.serverIndex + 1 } diff --git a/lib/agent/xdsserver.go b/lib/agent/xdsserver.go index 620bae9..bca4b66 100644 --- a/lib/agent/xdsserver.go +++ b/lib/agent/xdsserver.go @@ -42,6 +42,7 @@ type XdsServer struct { ioSock *sio_client.Client logOut io.Writer apiRouter *gin.RouterGroup + cmdList map[string]interface{} } // EventCB Event emitter callback @@ -72,6 +73,7 @@ func NewXdsServer(ctx *Context, conf xdsconfig.XDSServerConf) *XdsServer { sockEvents: make(map[string][]*caller), sockEventsLock: &sync.Mutex{}, logOut: ctx.Log.Out, + cmdList: make(map[string]interface{}), } } @@ -172,6 +174,16 @@ func (xs *XdsServer) FolderUpdate(fld *xsapiv1.FolderConfig, resFld *xsapiv1.Fol return xs.client.Put("/folders/"+fld.ID, fld, resFld) } +// CommandExec Send POST request to execute a command +func (xs *XdsServer) CommandExec(args *xsapiv1.ExecArgs, res *xsapiv1.ExecResult) error { + return xs.client.Post("/exec", args, res) +} + +// CommandSignal Send POST request to send a signal to a command +func (xs *XdsServer) CommandSignal(args *xsapiv1.ExecSignalArgs, res *xsapiv1.ExecSigResult) error { + return xs.client.Post("/signal", args, res) +} + // SetAPIRouterGroup . func (xs *XdsServer) SetAPIRouterGroup(r *gin.RouterGroup) { xs.apiRouter = r @@ -259,6 +271,15 @@ func (xs *XdsServer) EventRegister(evName string, id string) error { nil) } +// EventEmit Emit a event to XDS Server through WS +func (xs *XdsServer) EventEmit(message string, args ...interface{}) error { + if xs.ioSock == nil { + return fmt.Errorf("Io.Socket not initialized") + } + + return xs.ioSock.Emit(message, args...) +} + // EventOn Register a callback on events reception func (xs *XdsServer) EventOn(evName string, privData interface{}, f EventCB) (uuid.UUID, error) { if xs.ioSock == nil { @@ -404,6 +425,33 @@ func (xs *XdsServer) FolderToProject(fPrj xsapiv1.FolderConfig) xaapiv1.ProjectC return pPrj } +// CommandAdd Add a new command to the list of running commands +func (xs *XdsServer) CommandAdd(cmdID string, data interface{}) error { + if xs.CommandGet(cmdID) != nil { + return fmt.Errorf("command id already exist") + } + xs.cmdList[cmdID] = data + return nil +} + +// CommandDelete Delete a command from the command list +func (xs *XdsServer) CommandDelete(cmdID string) error { + if xs.CommandGet(cmdID) == nil { + return fmt.Errorf("unknown command id") + } + delete(xs.cmdList, cmdID) + return nil +} + +// CommandGet Retrieve a command data +func (xs *XdsServer) CommandGet(cmdID string) interface{} { + d, exist := xs.cmdList[cmdID] + if exist { + return d + } + return nil +} + /*** ** Private functions ***/ diff --git a/lib/xaapiv1/exec.go b/lib/xaapiv1/exec.go index b96be79..8438e7f 100644 --- a/lib/xaapiv1/exec.go +++ b/lib/xaapiv1/exec.go @@ -16,6 +16,18 @@ type ( CmdTimeout int `json:"timeout"` // command completion timeout in Second } + // ExecResult JSON result of /exec command + ExecResult struct { + Status string `json:"status"` // status OK + CmdID string `json:"cmdID"` // command unique ID + } + + // ExecSignalResult JSON result of /signal command + ExecSignalResult struct { + Status string `json:"status"` // status OK + CmdID string `json:"cmdID"` // command unique ID + } + // ExecInMsg Message used to received input characters (stdin) ExecInMsg struct { CmdID string `json:"cmdID"` diff --git a/lib/xdsconfig/config.go b/lib/xdsconfig/config.go index 56a9cf9..1cc48c5 100644 --- a/lib/xdsconfig/config.go +++ b/lib/xdsconfig/config.go @@ -8,9 +8,9 @@ import ( "os" "github.com/Sirupsen/logrus" - "github.com/urfave/cli" common "github.com/iotbzh/xds-common/golib" uuid "github.com/satori/go.uuid" + "github.com/urfave/cli" ) // Config parameters (json format) of /config command -- 2.16.6 From e3b0261be7cacf2653703c3543c33a83c3be16e4 Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Wed, 29 Nov 2017 16:02:35 +0100 Subject: [PATCH 02/16] Fixed XDS server connection config - dashboard Signed-off-by: Sebastien Douheret --- webapp/src/app/pages/config/config-xds/config-xds.component.html | 4 ++-- webapp/src/app/pages/config/config-xds/config-xds.component.scss | 4 ++++ webapp/src/app/pages/config/config-xds/config-xds.component.ts | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/webapp/src/app/pages/config/config-xds/config-xds.component.html b/webapp/src/app/pages/config/config-xds/config-xds.component.html index ebfaa36..e4bd0d5 100644 --- a/webapp/src/app/pages/config/config-xds/config-xds.component.html +++ b/webapp/src/app/pages/config/config-xds/config-xds.component.html @@ -16,7 +16,7 @@
- +
@@ -25,7 +25,7 @@
diff --git a/webapp/src/app/pages/config/config-xds/config-xds.component.scss b/webapp/src/app/pages/config/config-xds/config-xds.component.scss index 027f0fc..42e04ee 100644 --- a/webapp/src/app/pages/config/config-xds/config-xds.component.scss +++ b/webapp/src/app/pages/config/config-xds/config-xds.component.scss @@ -24,3 +24,7 @@ nb-card.inline-form-card nb-card-body { //vertical-align: middle; margin-top: 33%; } + +.form-control:disabled { + font-weight: lighter; +} diff --git a/webapp/src/app/pages/config/config-xds/config-xds.component.ts b/webapp/src/app/pages/config/config-xds/config-xds.component.ts index 396115b..e62cd37 100644 --- a/webapp/src/app/pages/config/config-xds/config-xds.component.ts +++ b/webapp/src/app/pages/config/config-xds/config-xds.component.ts @@ -20,7 +20,7 @@ export class ConfigXdsComponent { // TODO: cleanup agentStatus$: Observable; applying = false; xdsServerUrl = ''; - server: IXDServerCfg; + server: IXDServerCfg = { id: '', url: '', connRetry: 10, connected: false }; configFormChanged = false; @@ -35,6 +35,10 @@ export class ConfigXdsComponent { }); } + isApplyBtnEnable(): boolean { + return this.xdsServerUrl !== '' && (!this.server.connected || this.configFormChanged); + } + onSubmit() { if (!this.configFormChanged && this.server.connected) { return; -- 2.16.6 From fce0932dba3ca1b2c436400774821ef14fe32fe5 Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Wed, 29 Nov 2017 17:45:39 +0100 Subject: [PATCH 03/16] Check go version and print error if not >1.8.1 xds-common lib uses os.Executable function that has been introduced in go v1.8.1. --- Makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f448d72..99eee7c 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,14 @@ PACKAGE_DIR := $(ROOT_SRCDIR)/package export GOPATH := $(shell go env GOPATH):$(ROOT_GOPRJ) export PATH := $(PATH):$(LOCAL_TOOLSDIR) +# Check Go version +GOVERSION := $(shell go version |grep -o '[0-9\.]*'|head -n 1) +GOVERMAJ := $(shell echo $(GOVERSION) |cut -f1 -d.) +GOVERMIN := $(shell echo $(GOVERSION) |cut -f2 -d.) +CHECKGOVER := $(shell [ $(GOVERMAJ) -gt 1 -o \( $(GOVERMAJ) -eq 1 -a $(GOVERMIN) -ge 8 \) ] && echo true) +CHECKERRMSG := "ERROR: Go version 1.8.1 or higher is requested (current detected version: $(GOVERSION))." + + VERBOSE_1 := -v VERBOSE_2 := -v -x @@ -70,7 +78,7 @@ endif all: tools/syncthing build .PHONY: build -build: vendor xds webapp +build: checkgover vendor xds webapp xds: scripts tools/syncthing/copytobin @echo "### Build XDS agent (version $(VERSION), subversion $(SUB_VERSION)) - $(BUILD_MODE)"; @@ -166,6 +174,11 @@ tools/syncthing/copytobin: @mkdir -p $(LOCAL_BINDIR) @cp -f $(LOCAL_TOOLSDIR)/syncthing$(EXT) $(LOCAL_TOOLSDIR)/syncthing-inotify$(EXT) $(LOCAL_BINDIR) +.PHONY: +checkgover: + @test "$(CHECKGOVER)" = "true" || { echo $(CHECKERRMSG); exit 1; } + + .PHONY: help help: @echo "Main supported rules:" -- 2.16.6 From 0f2773364006751bb5a59cf53caea3b62146cc8d Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Wed, 29 Nov 2017 21:43:37 +0100 Subject: [PATCH 04/16] Fixed webapp build in production mode Signed-off-by: Sebastien Douheret --- Makefile | 16 ++- scripts/install.sh | 12 +- .../components/tiny-mce/tiny-mce.component.ts | 2 + .../build-settings-modal.component.ts | 143 --------------------- .../config/config-xds/config-xds.component.html | 2 +- .../config-xds/downloadXdsAgent.component.ts | 38 ------ 6 files changed, 19 insertions(+), 194 deletions(-) delete mode 100644 webapp/src/app/pages/build/settings-modal/build-settings-modal.component.ts delete mode 100644 webapp/src/app/pages/config/config-xds/downloadXdsAgent.component.ts diff --git a/Makefile b/Makefile index 99eee7c..e84775a 100644 --- a/Makefile +++ b/Makefile @@ -61,11 +61,13 @@ ifeq ($(filter 1,$(RELEASE) $(REL)),) # disable compiler optimizations and inlining GO_GCFLAGS=-N -l BUILD_MODE="Debug mode" + WEBAPP_BUILD_RULE=build else # optimized code without debug info GO_LDFLAGS=-s -w GO_GCFLAGS= BUILD_MODE="Release mode" + WEBAPP_BUILD_RULE=build:prod endif ifeq ($(SUB_VERSION), ) @@ -108,10 +110,10 @@ distclean: clean cd $(ROOT_SRCDIR) && rm -rf $(LOCAL_BINDIR) ./tools ./glide.lock ./vendor ./*.zip ./webapp/node_modules ./webapp/dist webapp: webapp/install - (cd webapp && npm run build) + cd webapp && npm run $(WEBAPP_BUILD_RULE) webapp/debug: - (cd webapp && npm run watch) + cd webapp && npm run watch webapp/install: (cd webapp && npm install) @@ -128,10 +130,12 @@ uninstall: export DESTDIR=$(DESTDIR) && export DESTDIR_WWW=$(DESTDIR_WWW) && $(ROOT_SRCDIR)/scripts/install.sh uninstall package: clean tools/syncthing vendor build - @mkdir -p $(PACKAGE_DIR)/xds-agent $(PACKAGE_DIR)/scripts - @cp -a $(LOCAL_BINDIR)/* $(PACKAGE_DIR)/xds-agent - @cp -r $(ROOT_SRCDIR)/conf.d $(ROOT_SRCDIR)/scripts $(PACKAGE_DIR)/xds-agent - cd $(PACKAGE_DIR) && zip -r $(ROOT_SRCDIR)/$(PACKAGE_ZIPFILE) ./xds-agent + @mkdir -p $(PACKAGE_DIR)/xds-agent/www $(PACKAGE_DIR)/scripts + @cp -a $(LOCAL_BINDIR)/* $(PACKAGE_DIR)/xds-agent/ + @cp -a webapp/dist/* $(PACKAGE_DIR)/xds-agent/www/ + @cp -r $(ROOT_SRCDIR)/conf.d $(ROOT_SRCDIR)/scripts $(PACKAGE_DIR)/xds-agent/ + @cd $(PACKAGE_DIR) && zip -r $(ROOT_SRCDIR)/$(PACKAGE_ZIPFILE) ./xds-agent + @echo "### Package $(PACKAGE_ZIPFILE) has been successfuly built - $(BUILD_MODE)" .PHONY: package-all package-all: diff --git a/scripts/install.sh b/scripts/install.sh index 357c5e8..6432e73 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -8,17 +8,17 @@ DESTDIR_WWW=${DESTDIR_WWW:-${DESTDIR}/www} ROOT_SRCDIR=$(cd $(dirname "$0")/.. && pwd) install() { - mkdir -p ${DESTDIR} && cp ${ROOT_SRCDIR}/bin/* ${DESTDIR} || exit 1 - mkdir -p ${DESTDIR_WWW} && cp -a ${ROOT_SRCDIR}/webapp/dist/* ${DESTDIR_WWW} || exit 1 + mkdir -p "${DESTDIR}" && cp "${ROOT_SRCDIR}/bin/*" "${DESTDIR}" || exit 1 + mkdir -p "${DESTDIR_WWW}" && cp -a "${ROOT_SRCDIR}/webapp/dist/*" "${DESTDIR_WWW}" || exit 1 - cp ${ROOT_SRCDIR}/conf.d/etc/xds-agent /etc/ || exit 1 - cp ${ROOT_SRCDIR}/conf.d/etc/default/xds-agent /etc/default/ || exit 1 + cp "${ROOT_SRCDIR}/conf.d/etc/xds-agent" /etc/ || exit 1 + cp "${ROOT_SRCDIR}/conf.d/etc/default/xds-agent" /etc/default/ || exit 1 FILE=/etc/profile.d/xds-agent.sh - sed -e "s;%%XDS_INSTALL_BIN_DIR%%;${DESTDIR};g" ${ROOT_SRCDIR}/conf.d/${FILE} > ${FILE} || exit 1 + sed -e "s;%%XDS_INSTALL_BIN_DIR%%;${DESTDIR};g" "${ROOT_SRCDIR}/conf.d/${FILE}" > ${FILE} || exit 1 FILE=/usr/lib/systemd/user/xds-agent.service - sed -e "s;/opt/AGL/xds/agent;${DESTDIR};g" ${ROOT_SRCDIR}/conf.d/${FILE} > ${FILE} || exit 1 + sed -e "s;/opt/AGL/xds/agent;${DESTDIR};g" "${ROOT_SRCDIR}/conf.d/${FILE}" > ${FILE} || exit 1 echo "" echo "To enable xds-agent service, execute: systemctl --user enable xds-agent" diff --git a/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts b/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts index c54685b..5b391ae 100644 --- a/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts +++ b/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts @@ -1,3 +1,4 @@ +/* MODS_XDS: not used for now import { Component, OnDestroy, AfterViewInit, Output, EventEmitter, ElementRef } from '@angular/core'; @Component({ @@ -31,3 +32,4 @@ export class TinyMCEComponent implements OnDestroy, AfterViewInit { tinymce.remove(this.editor); } } +*/ diff --git a/webapp/src/app/pages/build/settings-modal/build-settings-modal.component.ts b/webapp/src/app/pages/build/settings-modal/build-settings-modal.component.ts deleted file mode 100644 index fd1b904..0000000 --- a/webapp/src/app/pages/build/settings-modal/build-settings-modal.component.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Component, Input, ViewChild, OnInit } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { FormControl, FormGroup, Validators, ValidationErrors, FormBuilder, ValidatorFn, AbstractControl } from '@angular/forms'; - -// Import RxJs required methods -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/filter'; -import 'rxjs/add/operator/debounceTime'; - -import { AlertService, IAlert } from '../../../@core-xds/services/alert.service'; -import { ProjectService, IProject, ProjectType, ProjectTypes } from '../../../@core-xds/services/project.service'; -import { XDSConfigService } from '../../../@core-xds/services/xds-config.service'; - - -@Component({ - selector: 'xds-build-settings-modal', - templateUrl: 'build-settings-modal.component.html', - styleUrls: ['build-settings-modal.component.scss'], -}) -export class BuildSettingsModalComponent implements OnInit { - // @Input('server-id') serverID: string; - private serverID: string; - - cancelAction = false; - userEditedLabel = false; - projectTypes = ProjectTypes; - - addProjectForm: FormGroup; - typeCtrl: FormControl; - pathCliCtrl: FormControl; - pathSvrCtrl: FormControl; - - constructor( - private alert: AlertService, - private projectSvr: ProjectService, - private XdsConfigSvr: XDSConfigService, - private fb: FormBuilder, - private activeModal: NgbActiveModal, - ) { - // Define types (first one is special/placeholder) - this.projectTypes.unshift({ value: ProjectType.UNSET, display: '--Select a type--' }); - - this.typeCtrl = new FormControl(this.projectTypes[0].value, this.validatorProjType); - this.pathCliCtrl = new FormControl('', this.validatorProjPath); - this.pathSvrCtrl = new FormControl({ value: '', disabled: true }, this.validatorProjPath); - - this.addProjectForm = fb.group({ - type: this.typeCtrl, - pathCli: this.pathCliCtrl, - pathSvr: this.pathSvrCtrl, - label: ['', Validators.nullValidator], - }); - } - - - ngOnInit() { - // Update server ID - this.serverID = this.XdsConfigSvr.getCurServer().id; - this.XdsConfigSvr.onCurServer().subscribe(svr => this.serverID = svr.id); - - // Auto create label name - this.pathCliCtrl.valueChanges - .debounceTime(100) - .filter(n => n) - .map(n => { - const last = n.split('/'); - let nm = n; - if (last.length > 0) { - nm = last.pop(); - if (nm === '' && last.length > 0) { - nm = last.pop(); - } - } - return 'Project_' + nm; - }) - .subscribe(value => { - if (value && !this.userEditedLabel) { - this.addProjectForm.patchValue({ label: value }); - } - }); - - // Handle disabling of Server path - this.typeCtrl.valueChanges - .debounceTime(500) - .subscribe(valType => { - const dis = (valType === String(ProjectType.SYNCTHING)); - this.pathSvrCtrl.reset({ value: '', disabled: dis }); - }); - } - - closeModal() { - this.activeModal.close(); - } - - onKeyLabel(event: any) { - this.userEditedLabel = (this.addProjectForm.value.label !== ''); - } - - onChangeLocalProject(e) { - } - - onSubmit() { - if (this.cancelAction) { - return; - } - - const formVal = this.addProjectForm.value; - - const type = formVal['type'].value; - this.projectSvr.add({ - serverId: this.serverID, - label: formVal['label'], - pathClient: formVal['pathCli'], - pathServer: formVal['pathSvr'], - type: formVal['type'], - // FIXME: allow to set defaultSdkID from New Project config panel - }) - .subscribe(prj => { - this.alert.info('Project ' + prj.label + ' successfully created.'); - this.closeModal(); - - // Reset Value for the next creation - this.addProjectForm.reset(); - const selectedType = this.projectTypes[0].value; - this.addProjectForm.patchValue({ type: selectedType }); - - }, - err => { - this.alert.error(err, 60); - this.closeModal(); - }); - } - - private validatorProjType(g: FormGroup): ValidationErrors | null { - return (g.value !== ProjectType.UNSET) ? null : { validatorProjType: { valid: false } }; - } - - private validatorProjPath(g: FormGroup): ValidationErrors | null { - return (g.disabled || g.value !== '') ? null : { validatorProjPath: { valid: false } }; - } - -} diff --git a/webapp/src/app/pages/config/config-xds/config-xds.component.html b/webapp/src/app/pages/config/config-xds/config-xds.component.html index e4bd0d5..a2506ce 100644 --- a/webapp/src/app/pages/config/config-xds/config-xds.component.html +++ b/webapp/src/app/pages/config/config-xds/config-xds.component.html @@ -10,7 +10,7 @@
- +
diff --git a/webapp/src/app/pages/config/config-xds/downloadXdsAgent.component.ts b/webapp/src/app/pages/config/config-xds/downloadXdsAgent.component.ts deleted file mode 100644 index 556316c..0000000 --- a/webapp/src/app/pages/config/config-xds/downloadXdsAgent.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'xds-dwnl-agent', - template: ``, - /* FIXME SEB: to be reworked - template: ` - - - `, - styles: [` - .fa-size-x2 { - font-size: 20px; - } - `], - */ -}) - -export class DwnlAgentComponent { - - public url_OS_Linux = 'https://en.opensuse.org/LinuxAutomotive#Installation_AGL_XDS'; - public url_OS_Other = 'https://github.com/iotbzh/xds-agent#how-to-install-on-other-platform'; -} -- 2.16.6 From b5f2398c5cfb44bc18b6d1ab7c59be0ef090d8cf Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Wed, 29 Nov 2017 18:09:17 +0100 Subject: [PATCH 05/16] Used xdsserver api v1.0.0-rc1 --- Makefile | 4 ++-- glide.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index e84775a..466017f 100644 --- a/Makefile +++ b/Makefile @@ -71,9 +71,9 @@ else endif ifeq ($(SUB_VERSION), ) - PACKAGE_ZIPFILE := xds-agent_$(ARCH)-v$(VERSION).zip + PACKAGE_ZIPFILE := xds-agent_$(ARCH)-$(VERSION).zip else - PACKAGE_ZIPFILE := xds-agent_$(ARCH)-v$(VERSION)_$(SUB_VERSION).zip + PACKAGE_ZIPFILE := xds-agent_$(ARCH)-$(VERSION)_$(SUB_VERSION).zip endif diff --git a/glide.yaml b/glide.yaml index cb7a769..65ea68f 100644 --- a/glide.yaml +++ b/glide.yaml @@ -26,8 +26,8 @@ import: subpackages: - golib/common - package: github.com/iotbzh/xds-server - version: 5c1d023f41472660952ee559e2484cd6bbe688d3 + version: v1.0.0-rc1 subpackages: - - xsapiv1 + - lib/xsapiv1 - package: github.com/franciscocpg/reflectme version: ^0.1.9 -- 2.16.6 From cd8d64e86de540aea78a253c5fcc7826e8f15456 Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Thu, 30 Nov 2017 00:11:34 +0100 Subject: [PATCH 06/16] Fixed build page when no project exists Signed-off-by: Sebastien Douheret --- webapp/src/app/pages/build/build.component.html | 14 ++--- webapp/src/app/pages/build/build.component.ts | 71 ++++++++++++++-------- .../settings/project-select-dropdown.component.ts | 4 +- .../config/config-xds/config-xds.component.ts | 2 +- .../app/pages/dashboard/dashboard.component.html | 5 +- 5 files changed, 58 insertions(+), 38 deletions(-) diff --git a/webapp/src/app/pages/build/build.component.html b/webapp/src/app/pages/build/build.component.html index 1ce9484..6c8df72 100644 --- a/webapp/src/app/pages/build/build.component.html +++ b/webapp/src/app/pages/build/build.component.html @@ -27,7 +27,7 @@ - + Settings @@ -35,19 +35,19 @@ - + Clean - + Pre-Build - + Build - + Populate @@ -57,10 +57,10 @@ - Content deploy... +
   Under construction...
- Content debug... +
   Under construction...
diff --git a/webapp/src/app/pages/build/build.component.ts b/webapp/src/app/pages/build/build.component.ts index 99b7e54..681efe2 100644 --- a/webapp/src/app/pages/build/build.component.ts +++ b/webapp/src/app/pages/build/build.component.ts @@ -31,6 +31,7 @@ export class BuildComponent implements OnInit, AfterViewChecked { public buildIsCollapsed = false; public cmdOutput: string; public cmdInfo: string; + public curPrj: IProject; private startTime: Map = new Map(); @@ -42,11 +43,13 @@ export class BuildComponent implements OnInit, AfterViewChecked { private modalService: NgbModal, ) { this.cmdOutput = ''; - this.cmdInfo = ''; // TODO: to be remove (only for debug) - + this.cmdInfo = ''; // TODO: to be remove (only for debug) } ngOnInit() { + // Retreive current project + this.prjSvr.curProject$.subscribe(p => this.curPrj = p); + // Command output data tunneling this.xdsSvr.CmdOutput$.subscribe(data => { this.cmdOutput += data.stdout; @@ -76,66 +79,82 @@ export class BuildComponent implements OnInit, AfterViewChecked { this.cmdOutput = ''; } + isSetupValid(): boolean { + return (typeof this.curPrj !== 'undefined'); + } + settingsShow() { + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } + const activeModal = this.modalService.open(BuildSettingsModalComponent, { size: 'lg', container: 'nb-layout' }); activeModal.componentInstance.modalHeader = 'Large Modal'; } clean() { - const curPrj = this.prjSvr.getCurrent(); + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } this._exec( - curPrj.uiSettings.cmdClean, - curPrj.uiSettings.subpath, + this.curPrj.uiSettings.cmdClean, + this.curPrj.uiSettings.subpath, [], - curPrj.uiSettings.envVars.join(' ')); + this.curPrj.uiSettings.envVars.join(' ')); } preBuild() { - const curPrj = this.prjSvr.getCurrent(); + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } this._exec( - curPrj.uiSettings.cmdPrebuild, - curPrj.uiSettings.subpath, + this.curPrj.uiSettings.cmdPrebuild, + this.curPrj.uiSettings.subpath, [], - curPrj.uiSettings.envVars.join(' ')); + this.curPrj.uiSettings.envVars.join(' ')); } build() { - const curPrj = this.prjSvr.getCurrent(); + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } this._exec( - curPrj.uiSettings.cmdBuild, - curPrj.uiSettings.subpath, + this.curPrj.uiSettings.cmdBuild, + this.curPrj.uiSettings.subpath, [], - curPrj.uiSettings.envVars.join(' '), + this.curPrj.uiSettings.envVars.join(' '), ); } populate() { - const curPrj = this.prjSvr.getCurrent(); + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } this._exec( - curPrj.uiSettings.cmdPopulate, - curPrj.uiSettings.subpath, + this.curPrj.uiSettings.cmdPopulate, + this.curPrj.uiSettings.subpath, [], // args - curPrj.uiSettings.envVars.join(' '), + this.curPrj.uiSettings.envVars.join(' '), ); } execCmd() { - const curPrj = this.prjSvr.getCurrent(); + if (!this.isSetupValid()) { + return this.alertSvr.warning('Please select first a valid project.', true); + } this._exec( - curPrj.uiSettings.cmdArgs.join(' '), - curPrj.uiSettings.subpath, + this.curPrj.uiSettings.cmdArgs.join(' '), + this.curPrj.uiSettings.subpath, [], - curPrj.uiSettings.envVars.join(' '), + this.curPrj.uiSettings.envVars.join(' '), ); } private _exec(cmd: string, dir: string, args: string[], env: string) { - this.curProject = this.prjSvr.getCurrent(); - const prjID = this.curProject.id; - - if (!this.curProject) { + if (!this.isSetupValid()) { return this.alertSvr.warning('No active project', true); } + const prjID = this.curPrj.id; this.cmdOutput += this._outputHeader(); diff --git a/webapp/src/app/pages/build/settings/project-select-dropdown.component.ts b/webapp/src/app/pages/build/settings/project-select-dropdown.component.ts index a83ec0a..a99dc6b 100644 --- a/webapp/src/app/pages/build/settings/project-select-dropdown.component.ts +++ b/webapp/src/app/pages/build/settings/project-select-dropdown.component.ts @@ -28,7 +28,9 @@ export class ProjectSelectDropdownComponent implements OnInit { } select() { - this.projectSvr.setCurrentById(this.curPrj.id); + if (this.curPrj) { + this.projectSvr.setCurrentById(this.curPrj.id); + } } } diff --git a/webapp/src/app/pages/config/config-xds/config-xds.component.ts b/webapp/src/app/pages/config/config-xds/config-xds.component.ts index e62cd37..bd46145 100644 --- a/webapp/src/app/pages/config/config-xds/config-xds.component.ts +++ b/webapp/src/app/pages/config/config-xds/config-xds.component.ts @@ -20,7 +20,7 @@ export class ConfigXdsComponent { // TODO: cleanup agentStatus$: Observable; applying = false; xdsServerUrl = ''; - server: IXDServerCfg = { id: '', url: '', connRetry: 10, connected: false }; + server: IXDServerCfg = { id: '', url: 'http://localhost:8000', connRetry: 10, connected: false }; configFormChanged = false; diff --git a/webapp/src/app/pages/dashboard/dashboard.component.html b/webapp/src/app/pages/dashboard/dashboard.component.html index 9160019..ed6cfdb 100644 --- a/webapp/src/app/pages/dashboard/dashboard.component.html +++ b/webapp/src/app/pages/dashboard/dashboard.component.html @@ -1,10 +1,9 @@
- Dashboard page... -
--->
-- 2.16.6 From 680b5c22e986a8421c63d7b99b5f6a4dd04fde30 Mon Sep 17 00:00:00 2001 From: Sebastien Douheret Date: Thu, 30 Nov 2017 01:28:14 +0100 Subject: [PATCH 07/16] Added Help menu with doc link and About modal. --- .../@theme/components/footer/footer.component.ts | 2 - .../@theme/components/header/header.component.html | 3 +- .../@theme/components/header/header.component.ts | 31 ++++++++- .../about/about-modal/about-modal.component.ts | 81 ++++++++++++++++++++++ webapp/src/app/pages/about/about.module.ts | 17 +++++ webapp/src/app/pages/pages.module.ts | 2 + 6 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 webapp/src/app/pages/about/about-modal/about-modal.component.ts create mode 100644 webapp/src/app/pages/about/about.module.ts diff --git a/webapp/src/app/@theme/components/footer/footer.component.ts b/webapp/src/app/@theme/components/footer/footer.component.ts index 8e1e825..1e3d704 100644 --- a/webapp/src/app/@theme/components/footer/footer.component.ts +++ b/webapp/src/app/@theme/components/footer/footer.component.ts @@ -6,8 +6,6 @@ import { Component } from '@angular/core'; template: ` Created by IoT.bzh 2017 -    - (powered by akveo/ngx-admin)