You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by rm...@apache.org on 2018/08/17 15:34:52 UTC

[37/51] [abbrv] metron git commit: METRON-1713 PCAP UI - Add a way to kill a pcap job (tiborm via merrimanr) closes apache/metron#1143

METRON-1713 PCAP UI - Add a way to kill a pcap job (tiborm via merrimanr) closes apache/metron#1143


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/14dcb2d9
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/14dcb2d9
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/14dcb2d9

Branch: refs/heads/master
Commit: 14dcb2d90581835d8206c65918c24e8cb04bfd06
Parents: 5b3e2c3
Author: tiborm <ti...@gmail.com>
Authored: Thu Aug 9 08:33:21 2018 -0500
Committer: rmerriman <me...@gmail.com>
Committed: Thu Aug 9 08:33:21 2018 -0500

----------------------------------------------------------------------
 .../pcap/pcap-panel/pcap-panel.component.html   |   7 +-
 .../pcap/pcap-panel/pcap-panel.component.scss   |  33 +++++
 .../pcap-panel/pcap-panel.component.spec.ts     | 130 +++++++++++++++++++
 .../app/pcap/pcap-panel/pcap-panel.component.ts |  42 +++++-
 .../src/app/pcap/service/pcap.service.ts        |  10 +-
 5 files changed, 215 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/14dcb2d9/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
index 950f49c..0dda268 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
@@ -15,8 +15,11 @@
   <div class="panel-header">
     <app-pcap-filters [queryRunning]="queryRunning" (search)="onSearch($event)"></app-pcap-filters>
   </div>
-  <div *ngIf="queryRunning" class="progress pcap-progress-background">
-    <div class="progress-bar progress-bar-animated pcap-progress" role="progressbar" attr.aria-valuenow="{{progressWidth}}" aria-valuemin="0" aria-valuemax="100" [ngStyle]="{'width': progressWidth + '%'}">{{progressWidth}}%</div>
+  <div *ngIf="queryRunning" class="pcap-progress-wrapper">
+    <div class="progress pcap-progress-background">
+      <div class="progress-bar progress-bar-animated pcap-progress" role="progressbar" attr.aria-valuenow="{{progressWidth}}" aria-valuemin="0" aria-valuemax="100" [ngStyle]="{'width': progressWidth + '%'}">{{progressWidth}}%</div>
+    </div>
+    <button data-qe-id="pcap-cancel-query-button" class="pcap-cancel-query-button btn btn-primary btn-sm" (click)="cancelQuery()" [disabled]="!queryId"></button>
   </div>
   <div *ngIf="errorMsg" class="alert alert-danger" role="alert" data-qe-id="error">
     {{ errorMsg }}

http://git-wip-us.apache.org/repos/asf/metron/blob/14dcb2d9/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.scss b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.scss
index 8989bf9..523f5ce 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.scss
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.scss
@@ -31,4 +31,37 @@
 
 .progress-bar {
   width: 0;
+  height: 34px;
+  line-height: 34px;
+  vertical-align: middle;
+  font-size: 0.875rem;
+}
+
+.pcap-progress-wrapper {
+  position: relative;
+  padding-right: 55px;
+}
+
+.pcap-cancel-query-button {
+  position: absolute;
+  top: 0;
+  right: 0;
+  padding-top: 6px;
+  padding-bottom: 6px;
+  background: $icon-button-background;
+  min-width: 42px;
+  padding-left: 0;
+  padding-right: 0;
+  border: 1px solid $blue-chill !important;
+  cursor: pointer;
+
+  &:focus {
+    box-shadow: none;
+  }
+
+  &::before {
+    font-family: "FontAwesome";
+    content: '\f00d';
+    color: $piction-blue;
+  }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/14dcb2d9/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
index 0804b79..9dacc7f 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
@@ -50,6 +50,9 @@ class FakePcapService {
     return '';
   }
   submitRequest() {}
+  cancelQuery() {
+    return defer(() => Promise.resolve());
+  }
 }
 
 describe('PcapPanelComponent', () => {
@@ -327,6 +330,133 @@ describe('PcapPanelComponent', () => {
     expect(fixture.debugElement.query(By.css('app-pcap-list'))).toBeDefined();
   }));
 
+  it('should render a cancel button only if a query runs', () => {
+    component.queryRunning = false;
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'))).toBeFalsy();
+
+    component.queryRunning = true;
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'))).toBeDefined();
+  });
+
+  it('should hide the progress bar if the user clicks on the cancel button', fakeAsync(() => {
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeDefined();
+
+    const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
+    const cancelBtnEl = cancelBtn.nativeElement;
+
+    cancelBtnEl.click();
+    tick();
+    fixture.detectChanges();
+
+    expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeFalsy();
+  }));
+
+  it('should hide the progress bar if the cancellation request fails', fakeAsync(() => {
+    const restError = new RestError();
+    pcapService.cancelQuery = jasmine.createSpy('cancelQuery').and.returnValue(
+      defer(() => Promise.reject(restError))
+    );
+
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeDefined();
+
+    const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
+    const cancelBtnEl = cancelBtn.nativeElement;
+
+    cancelBtnEl.click();
+    tick();
+    fixture.detectChanges();
+
+    expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeFalsy();
+  }));
+
+  it('should show an error message if the cancellation request fails', fakeAsync(() => {
+    const restError = new RestError();
+    restError.message = 'cancellation error';
+    pcapService.cancelQuery = jasmine.createSpy('cancelQuery').and.returnValue(
+      defer(() => Promise.reject(restError))
+    );
+
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('[data-qe-id="error"]'))).toBeFalsy();
+
+    const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
+    const cancelBtnEl = cancelBtn.nativeElement;
+
+    cancelBtnEl.click();
+    tick();
+    fixture.detectChanges();
+
+    expect(
+      fixture.debugElement.query(By.css('[data-qe-id="error"]'))
+        .nativeElement
+        .textContent.trim()
+    ).toBe(`Response message: ${restError.message}. Something went wrong with the cancellation!`);
+  }));
+
+  it('cancel button should be disabled till we get back a queryId', fakeAsync(() => {
+    component.queryRunning = true;
+    component.queryId = '';
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]')).nativeElement.disabled).toBeTruthy();
+  }));
+
+  it('cancel button should be enabled when we have a queryId', fakeAsync(() => {
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+    expect(fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]')).nativeElement.disabled).toBeFalsy();
+  }));
+
+  it('queryId should be emptied if the cancellation request fails', fakeAsync(() => {
+    const restError = new RestError();
+    restError.message = 'cancellation error';
+    pcapService.cancelQuery = jasmine.createSpy('cancelQuery').and.returnValue(
+      defer(() => Promise.reject(restError))
+    );
+
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+
+    const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
+    const cancelBtnEl = cancelBtn.nativeElement;
+
+    cancelBtnEl.click();
+    tick();
+    fixture.detectChanges();
+
+    expect(component.queryId).toBeFalsy();
+  }));
+
+  it('queryId should be emptied if the cancellation success', fakeAsync(() => {
+    pcapService.cancelQuery = jasmine.createSpy('cancelQuery').and.returnValue(
+      defer(() => Promise.resolve())
+    );
+
+    component.queryRunning = true;
+    component.queryId = 'testid';
+    fixture.detectChanges();
+
+    const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
+    const cancelBtnEl = cancelBtn.nativeElement;
+
+    cancelBtnEl.click();
+    tick();
+    fixture.detectChanges();
+
+    expect(component.queryId).toBeFalsy();
+  }));
+
   it('should handle get packet 404', fakeAsync(() => {
     const searchResponse = new PcapStatusResponse();
     searchResponse.jobId = '42';

http://git-wip-us.apache.org/repos/asf/metron/blob/14dcb2d9/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
index 8e4ced0..b11d9df 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
@@ -15,7 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, Input } from '@angular/core';
+import { Component, Input, OnDestroy } from '@angular/core';
 
 import { PcapService } from '../service/pcap.service';
 import { PcapStatusResponse } from '../model/pcap-status-response';
@@ -30,13 +30,16 @@ import {RestError} from "../../model/rest-error";
   templateUrl: './pcap-panel.component.html',
   styleUrls: ['./pcap-panel.component.scss']
 })
-export class PcapPanelComponent {
+export class PcapPanelComponent implements OnDestroy {
 
   @Input() pdml: Pdml = null;
   @Input() pcapRequest: PcapRequest;
   @Input() resetPaginationForSearch: boolean;
 
   statusSubscription: Subscription;
+  cancelSubscription: Subscription;
+  submitSubscription: Subscription;
+  getSubscription: Subscription;
   queryRunning: boolean = false;
   queryId: string;
   progressWidth: number = 0;
@@ -55,12 +58,13 @@ export class PcapPanelComponent {
 
   onSearch(pcapRequest) {
     this.queryRunning = true;
+    this.queryId = '';
     this.savedPcapRequest = pcapRequest;
     this.pagination.selectedPage = 1;
     this.pdml = null;
     this.progressWidth = 0;
     this.errorMsg = null;
-    this.pcapService.submitRequest(pcapRequest).subscribe((submitResponse: PcapStatusResponse) => {
+    this.submitSubscription = this.pcapService.submitRequest(pcapRequest).subscribe((submitResponse: PcapStatusResponse) => {
       let id = submitResponse.jobId;
       if (!id) {
         this.errorMsg = submitResponse.description;
@@ -104,4 +108,34 @@ export class PcapPanelComponent {
   getDownloadUrl() {
     return this.pcapService.getDownloadUrl(this.queryId, this.pagination.selectedPage);
   }
-}
\ No newline at end of file
+
+  unsubscribeAll() {
+    if (this.cancelSubscription) {
+      this.cancelSubscription.unsubscribe();
+    }
+    if (this.statusSubscription) {
+      this.statusSubscription.unsubscribe();
+    }
+    if (this.submitSubscription) {
+      this.submitSubscription.unsubscribe();
+    }
+  }
+
+  cancelQuery() {
+    this.cancelSubscription = this.pcapService.cancelQuery(this.queryId)
+      .subscribe(() => {
+        this.unsubscribeAll();
+        this.queryId = '';
+        this.queryRunning = false;
+      }, (error: any) => {
+        this.cancelSubscription.unsubscribe();
+        this.queryId = '';
+        this.errorMsg = `Response message: ${error.message}. Something went wrong with the cancellation!`;
+        this.queryRunning = false;
+      });
+  }
+
+  ngOnDestroy() {
+    this.unsubscribeAll();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/14dcb2d9/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
index 518cc92..85ed9cc 100644
--- a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
@@ -52,7 +52,7 @@ export class PcapService {
           new RequestOptions({headers: new Headers(this.defaultHeaders)}))
           .map(HttpUtil.extractData)
           .catch(HttpUtil.handleError);
-  }
+    }
     public getPackets(id: string, pageId: number): Observable<Pdml> {
         return this.http.get(`/api/v1/pcap/${id}/pdml?page=${pageId}`, new RequestOptions({headers: new Headers(this.defaultHeaders)}))
             .map(HttpUtil.extractData)
@@ -62,4 +62,12 @@ export class PcapService {
     public getDownloadUrl(id: string, pageId: number) {
       return `/api/v1/pcap/${id}/raw?page=${pageId}`;
     }
+
+    public cancelQuery(queryId: string) {
+      return this.http
+        .delete(`/api/v1/pcap/kill/${queryId}`, new RequestOptions({
+          headers: new Headers(this.defaultHeaders),
+        }))
+        .catch(HttpUtil.handleError);
+    }
 }
\ No newline at end of file