diff options
author | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-10-11 00:24:02 +0200 |
---|---|---|
committer | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-10-11 00:24:02 +0200 |
commit | 4695555e178bcabe54c5bf82117c9c4cef5440b5 (patch) | |
tree | 96a8721de74347450b2e4922004b1bf01e415dfa /webapp | |
parent | 882944a748d123c8715eca88536299d8570858f9 (diff) |
Fixed Syncthing folder status events and exec command.
Diffstat (limited to 'webapp')
-rw-r--r-- | webapp/src/app/config/config.component.ts | 1 | ||||
-rw-r--r-- | webapp/src/app/services/config.service.ts | 120 | ||||
-rw-r--r-- | webapp/src/app/services/syncthing.service.ts | 352 | ||||
-rw-r--r-- | webapp/src/app/services/xdsagent.service.ts | 6 |
4 files changed, 4 insertions, 475 deletions
diff --git a/webapp/src/app/config/config.component.ts b/webapp/src/app/config/config.component.ts index 101596f..6377844 100644 --- a/webapp/src/app/config/config.component.ts +++ b/webapp/src/app/config/config.component.ts @@ -102,7 +102,6 @@ export class ConfigComponent implements OnInit { xdsAgentRestartConn() { let url = this.xdsServerUrl; this.xdsAgentSvr.setServerUrl(this.curServerID, url); - this.configSvr.loadProjects(); } } diff --git a/webapp/src/app/services/config.service.ts b/webapp/src/app/services/config.service.ts index 090df7b..bbe2fb8 100644 --- a/webapp/src/app/services/config.service.ts +++ b/webapp/src/app/services/config.service.ts @@ -1,25 +1,13 @@ -import { Injectable, OnInit } from '@angular/core'; -import { Http, Headers, RequestOptionsArgs, Response } from '@angular/http'; -import { Location } from '@angular/common'; +import { Injectable } from '@angular/core'; import { CookieService } from 'ngx-cookie'; import { Observable } from 'rxjs/Observable'; -import { Subscriber } from 'rxjs/Subscriber'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -// Import RxJs required methods -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/observable/throw'; -import 'rxjs/add/operator/mergeMap'; - - -import { XDSAgentService, IXDSProjectConfig } from "../services/xdsagent.service"; import { AlertService, IAlert } from "../services/alert.service"; import { UtilsService } from "../services/utils.service"; export interface IConfig { projectsRootDir: string; - //SEB projects: IProject[]; } @Injectable() @@ -29,21 +17,15 @@ export class ConfigService { private confSubject: BehaviorSubject<IConfig>; private confStore: IConfig; - // SEB cleanup private AgentConnectObs = null; - // SEB cleanup private stConnectObs = null; constructor(private _window: Window, private cookie: CookieService, - private xdsAgentSvr: XDSAgentService, private alert: AlertService, private utils: UtilsService, ) { this.load(); this.confSubject = <BehaviorSubject<IConfig>>new BehaviorSubject(this.confStore); this.Conf$ = this.confSubject.asObservable(); - - // force to load projects - this.loadProjects(); } // Load config @@ -71,107 +53,7 @@ export class ConfigService { this.cookie.putObject("xds-config", cfg); } - loadProjects() { - /* SEB - // Setup connection with local XDS agent - if (this.AgentConnectObs) { - try { - this.AgentConnectObs.unsubscribe(); - } catch (err) { } - this.AgentConnectObs = null; - } - - let cfg = this.confStore.xdsAgent; - this.AgentConnectObs = this.xdsAgentSvr.connect(cfg.retry, cfg.URL) - .subscribe((sts) => { - //console.log("Agent sts", sts); - // FIXME: load projects from local XDS Agent and - // not directly from local syncthing - this._loadProjectFromLocalST(); - - }, error => { - if (error.indexOf("XDS local Agent not responding") !== -1) { - let url_OS_Linux = "https://en.opensuse.org/LinuxAutomotive#Installation_AGL_XDS"; - let url_OS_Other = "https://github.com/iotbzh/xds-agent#how-to-install-on-other-platform"; - let msg = `<span><strong>` + error + `<br></strong> - You may need to install and execute XDS-Agent: <br> - On Linux machine <a href="` + url_OS_Linux + `" target="_blank"><span - class="fa fa-external-link"></span></a> - <br> - On Windows machine <a href="` + url_OS_Other + `" target="_blank"><span - class="fa fa-external-link"></span></a> - <br> - On MacOS machine <a href="` + url_OS_Other + `" target="_blank"><span - class="fa fa-external-link"></span></a> - `; - this.alert.error(msg); - } else { - this.alert.error(error); - } - }); - */ - } - - /* SEB - private _loadProjectFromLocalST() { - // Remove previous subscriber if existing - if (this.stConnectObs) { - try { - this.stConnectObs.unsubscribe(); - } catch (err) { } - this.stConnectObs = null; - } - - // FIXME: move this code and all logic about syncthing inside XDS Agent - // Setup connection with local SyncThing - let retry = this.confStore.localSThg.retry; - let url = this.confStore.localSThg.URL; - this.stConnectObs = this.stSvr.connect(retry, url).subscribe((sts) => { - this.confStore.localSThg.ID = sts.ID; - this.confStore.localSThg.tilde = sts.tilde; - if (this.confStore.projectsRootDir === "") { - this.confStore.projectsRootDir = sts.tilde; - } - - // Rebuild projects definition from local and remote syncthing - this.confStore.projects = []; - - this.xdsServerSvr.getProjects().subscribe(remotePrj => { - this.stSvr.getProjects().subscribe(localPrj => { - remotePrj.forEach(rPrj => { - let lPrj = localPrj.filter(item => item.id === rPrj.id); - if (lPrj.length > 0 || rPrj.type === ProjectType.NATIVE_PATHMAP) { - this._addProject(rPrj, true); - } - }); - this.confSubject.next(Object.assign({}, this.confStore)); - }), error => this.alert.error('Could not load initial state of local projects.'); - }), error => this.alert.error('Could not load initial state of remote projects.'); - - }, error => { - if (error.indexOf("Syncthing local daemon not responding") !== -1) { - let msg = "<span><strong>" + error + "<br></strong>"; - msg += "Please check that local XDS-Agent is running.<br>"; - msg += "</span>"; - this.alert.error(msg); - } else { - this.alert.error(error); - } - }); - } - - set syncToolURL(url: string) { - this.confStore.localSThg.URL = url; - this.save(); - } - */ - set projectsRootDir(p: string) { - /* SEB - if (p.charAt(0) === '~') { - p = this.confStore.localSThg.tilde + p.substring(1); - } - */ this.confStore.projectsRootDir = p; this.save(); } diff --git a/webapp/src/app/services/syncthing.service.ts b/webapp/src/app/services/syncthing.service.ts deleted file mode 100644 index 1561cbf..0000000 --- a/webapp/src/app/services/syncthing.service.ts +++ /dev/null @@ -1,352 +0,0 @@ -import { Injectable } from '@angular/core'; -/* -import { Http, Headers, RequestOptionsArgs, Response } from '@angular/http'; -import { CookieService } from 'ngx-cookie'; -import { Location } from '@angular/common'; -import { Observable } from 'rxjs/Observable'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; - -// Import RxJs required methods -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/observable/throw'; -import 'rxjs/add/observable/of'; -import 'rxjs/add/observable/timer'; -import 'rxjs/add/operator/retryWhen'; - -export interface ISyncThingProject { - id: string; - path: string; - serverSyncThingID: string; - label?: string; -} - -export interface ISyncThingStatus { - ID: string; - baseURL: string; - connected: boolean; - connectionRetry: number; - tilde: string; - rawStatus: any; -} - -// Private interfaces of Syncthing -const ISTCONFIG_VERSION = 20; - -interface ISTFolderDeviceConfiguration { - deviceID: string; - introducedBy: string; -} -interface ISTFolderConfiguration { - id: string; - label: string; - path: string; - type?: number; - devices?: ISTFolderDeviceConfiguration[]; - rescanIntervalS?: number; - ignorePerms?: boolean; - autoNormalize?: boolean; - minDiskFreePct?: number; - versioning?: { type: string; params: string[] }; - copiers?: number; - pullers?: number; - hashers?: number; - order?: number; - ignoreDelete?: boolean; - scanProgressIntervalS?: number; - pullerSleepS?: number; - pullerPauseS?: number; - maxConflicts?: number; - disableSparseFiles?: boolean; - disableTempIndexes?: boolean; - fsync?: boolean; - paused?: boolean; -} - -interface ISTDeviceConfiguration { - deviceID: string; - name?: string; - address?: string[]; - compression?: string; - certName?: string; - introducer?: boolean; - skipIntroductionRemovals?: boolean; - introducedBy?: string; - paused?: boolean; - allowedNetwork?: string[]; -} - -interface ISTGuiConfiguration { - enabled: boolean; - address: string; - user?: string; - password?: string; - useTLS: boolean; - apiKey?: string; - insecureAdminAccess?: boolean; - theme: string; - debugging: boolean; - insecureSkipHostcheck?: boolean; -} - -interface ISTOptionsConfiguration { - listenAddresses: string[]; - globalAnnounceServer: string[]; - // To be completed ... -} - -interface ISTConfiguration { - version: number; - folders: ISTFolderConfiguration[]; - devices: ISTDeviceConfiguration[]; - gui: ISTGuiConfiguration; - options: ISTOptionsConfiguration; - ignoredDevices: string[]; -} - -// Default settings -const DEFAULT_GUI_PORT = 8384; -const DEFAULT_GUI_API_KEY = "1234abcezam"; -const DEFAULT_RESCAN_INTERV = 0; // 0: use syncthing-inotify to detect changes - -*/ - -@Injectable() -export class SyncthingService { - - /* SEB A SUP - public Status$: Observable<ISyncThingStatus>; - - private baseRestUrl: string; - private apikey: string; - private localSTID: string; - private stCurVersion: number; - private connectionMaxRetry: number; - private _status: ISyncThingStatus = { - ID: null, - baseURL: "", - connected: false, - connectionRetry: 0, - tilde: "", - rawStatus: null, - }; - private statusSubject = <BehaviorSubject<ISyncThingStatus>>new BehaviorSubject(this._status); - - constructor(private http: Http, private _window: Window, private cookie: CookieService) { - this._status.baseURL = 'http://localhost:' + DEFAULT_GUI_PORT; - this.baseRestUrl = this._status.baseURL + '/rest'; - this.apikey = DEFAULT_GUI_API_KEY; - this.stCurVersion = -1; - this.connectionMaxRetry = 10; // 10 seconds - - this.Status$ = this.statusSubject.asObservable(); - } - - connect(retry: number, url?: string): Observable<ISyncThingStatus> { - if (url) { - this._status.baseURL = url; - this.baseRestUrl = this._status.baseURL + '/rest'; - } - this._status.connected = false; - this._status.ID = null; - this._status.connectionRetry = 0; - this.connectionMaxRetry = retry || 3600; // 1 hour - return this.getStatus(); - } - - getID(): Observable<string> { - if (this._status.ID != null) { - return Observable.of(this._status.ID); - } - return this.getStatus().map(sts => sts.ID); - } - - getStatus(): Observable<ISyncThingStatus> { - return this._get('/system/status') - .map((status) => { - this._status.ID = status["myID"]; - this._status.tilde = status["tilde"]; - console.debug('ST local ID', this._status.ID); - - this._status.rawStatus = status; - - return this._status; - }); - } - - getProjects(): Observable<ISTFolderConfiguration[]> { - return this._getConfig() - .map((conf) => conf.folders); - } - - addProject(prj: ISyncThingProject): Observable<ISTFolderConfiguration> { - return this.getID() - .flatMap(() => this._getConfig()) - .flatMap((stCfg) => { - let newDevID = prj.serverSyncThingID; - - // Add new Device if needed - let dev = stCfg.devices.filter(item => item.deviceID === newDevID); - if (dev.length <= 0) { - stCfg.devices.push( - { - deviceID: newDevID, - name: "Builder_" + newDevID.slice(0, 15), - address: ["dynamic"], - } - ); - } - - // Add or update Folder settings - let label = prj.label || ""; - let scanInterval = parseInt(this.cookie.get("st-rescanInterval"), 10) || DEFAULT_RESCAN_INTERV; - let folder: ISTFolderConfiguration = { - id: prj.id, - label: label, - path: prj.path, - devices: [{ deviceID: newDevID, introducedBy: "" }], - autoNormalize: true, - rescanIntervalS: scanInterval, - }; - - let idx = stCfg.folders.findIndex(item => item.id === prj.id); - if (idx === -1) { - stCfg.folders.push(folder); - } else { - let newFld = Object.assign({}, stCfg.folders[idx], folder); - stCfg.folders[idx] = newFld; - } - - // Set new config - return this._setConfig(stCfg); - }) - .flatMap(() => this._getConfig()) - .map((newConf) => { - let idx = newConf.folders.findIndex(item => item.id === prj.id); - return newConf.folders[idx]; - }); - } - - deleteProject(id: string): Observable<ISTFolderConfiguration> { - let delPrj: ISTFolderConfiguration; - return this._getConfig() - .flatMap((conf: ISTConfiguration) => { - let idx = conf.folders.findIndex(item => item.id === id); - if (idx === -1) { - throw new Error("Cannot delete project: not found"); - } - delPrj = Object.assign({}, conf.folders[idx]); - conf.folders.splice(idx, 1); - return this._setConfig(conf); - }) - .map(() => delPrj); - } - - // - // --- Private functions --- - // - private _getConfig(): Observable<ISTConfiguration> { - return this._get('/system/config'); - } - - private _setConfig(cfg: ISTConfiguration): Observable<any> { - return this._post('/system/config', cfg); - } - - private _attachAuthHeaders(options?: any) { - options = options || {}; - let headers = options.headers || new Headers(); - // headers.append('Authorization', 'Basic ' + btoa('username:password')); - headers.append('Accept', 'application/json'); - headers.append('Content-Type', 'application/json'); - if (this.apikey !== "") { - headers.append('X-API-Key', this.apikey); - - } - options.headers = headers; - return options; - } - - private _checkAlive(): Observable<boolean> { - if (this._status.connected) { - return Observable.of(true); - } - - return this.http.get(this.baseRestUrl + '/system/version', this._attachAuthHeaders()) - .map((r) => this._status.connected = true) - .retryWhen((attempts) => { - this._status.connectionRetry = 0; - return attempts.flatMap(error => { - this._status.connected = false; - if (++this._status.connectionRetry >= this.connectionMaxRetry) { - return Observable.throw("Syncthing local daemon not responding (url=" + this._status.baseURL + ")"); - } else { - return Observable.timer(1000); - } - }); - }); - } - - private _getAPIVersion(): Observable<number> { - if (this.stCurVersion !== -1) { - return Observable.of(this.stCurVersion); - } - - return this.http.get(this.baseRestUrl + '/system/config', this._attachAuthHeaders()) - .map((res: Response) => { - let conf: ISTConfiguration = res.json(); - this.stCurVersion = (conf && conf.version) || -1; - return this.stCurVersion; - }) - .catch(this._handleError); - } - - private _checkAPIVersion(): Observable<number> { - return this._getAPIVersion().map(ver => { - if (ver !== ISTCONFIG_VERSION) { - throw new Error("Unsupported Syncthing version api (" + ver + - " != " + ISTCONFIG_VERSION + ") !"); - } - return ver; - }); - } - - private _get(url: string): Observable<any> { - return this._checkAlive() - .flatMap(() => this._checkAPIVersion()) - .flatMap(() => this.http.get(this.baseRestUrl + url, this._attachAuthHeaders())) - .map((res: Response) => res.json()) - .catch(this._handleError); - } - - private _post(url: string, body: any): Observable<any> { - return this._checkAlive() - .flatMap(() => this._checkAPIVersion()) - .flatMap(() => this.http.post(this.baseRestUrl + url, JSON.stringify(body), this._attachAuthHeaders())) - .map((res: Response) => { - if (res && res.status && res.status === 200) { - return res; - } - throw new Error(res.toString()); - - }) - .catch(this._handleError); - } - - private _handleError(error: Response | any) { - // In a real world app, you might use a remote logging infrastructure - let errMsg: string; - if (this._status) { - this._status.connected = false; - } - if (error instanceof Response) { - const body = error.json() || 'Server error'; - const err = body.error || JSON.stringify(body); - errMsg = `${error.status} - ${error.statusText || ''} ${err}`; - } else { - errMsg = error.message ? error.message : error.toString(); - } - return Observable.throw(errMsg); - } - */ -} diff --git a/webapp/src/app/services/xdsagent.service.ts b/webapp/src/app/services/xdsagent.service.ts index e570399..fd84ccb 100644 --- a/webapp/src/app/services/xdsagent.service.ts +++ b/webapp/src/app/services/xdsagent.service.ts @@ -305,7 +305,7 @@ export class XDSAgentService { id: prjID, rpath: dir, cmd: cmd, - sdkid: sdkid || "", + sdkID: sdkid || "", args: args || [], env: env || [], }); @@ -317,7 +317,7 @@ export class XDSAgentService { { id: prjID, rpath: dir, - sdkid: sdkid, + sdkID: sdkid, args: args || [], env: env || [], }); @@ -382,7 +382,7 @@ export class XDSAgentService { if (err instanceof Response) { const body = err.json() || 'Agent error'; e = body.error || JSON.stringify(body); - if (!e || e === "") { + if (!e || e === "" || e === '{"isTrusted":true}') { e = `${err.status} - ${err.statusText || 'Unknown error'}`; } } else if (typeof err === "object") { |