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 2017/10/04 13:49:07 UTC
metron git commit: METRON-1161 Add ability to edit parser command
line options in the management UI (merrimanr) closes apache/metron#737
Repository: metron
Updated Branches:
refs/heads/master 6ffff0299 -> d69101a8d
METRON-1161 Add ability to edit parser command line options in the management UI (merrimanr) closes apache/metron#737
Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/d69101a8
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/d69101a8
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/d69101a8
Branch: refs/heads/master
Commit: d69101a8d10620b04e90ef7f9c1885847bf0111e
Parents: 6ffff02
Author: merrimanr <me...@gmail.com>
Authored: Wed Oct 4 08:48:51 2017 -0500
Committer: merrimanr <me...@apache.org>
Committed: Wed Oct 4 08:48:51 2017 -0500
----------------------------------------------------------------------
.../src/app/model/sensor-parser-config.ts | 12 ++
...sensor-parser-config-readonly.component.html | 1 +
...sor-parser-config-readonly.component.spec.ts | 3 +-
.../sensor-parser-config-readonly.component.ts | 11 ++
.../sensor-parser-config.component.html | 17 ++
.../sensor-parser-config.component.ts | 18 +-
.../sensor-parser-config.module.ts | 3 +-
.../sensor-raw-json.component.ts | 19 +--
.../sensor-storm-settings.component.html | 104 ++++++++++++
.../sensor-storm-settings.component.scss | 36 ++++
.../sensor-storm-settings.component.spec.ts | 168 +++++++++++++++++++
.../sensor-storm-settings.component.ts | 95 +++++++++++
.../sensor-storm-settings.module.ts | 29 ++++
13 files changed, 487 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/model/sensor-parser-config.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/model/sensor-parser-config.ts b/metron-interface/metron-config/src/app/model/sensor-parser-config.ts
index c0d907d..a2cd4ae 100644
--- a/metron-interface/metron-config/src/app/model/sensor-parser-config.ts
+++ b/metron-interface/metron-config/src/app/model/sensor-parser-config.ts
@@ -25,9 +25,21 @@ export class SensorParserConfig {
invalidWriterClassName: string;
parserConfig: {};
fieldTransformations: FieldTransformer[];
+ numWorkers: number;
+ numAckers: number;
+ spoutParallelism: number;
+ spoutNumTasks: number;
+ parserParallelism: number;
+ parserNumTasks: number;
+ errorWriterParallelism: number;
+ errorWriterNumTasks: number;
+ spoutConfig: {};
+ stormConfig: {};
constructor() {
this.parserConfig = {};
this.fieldTransformations = [];
+ this.spoutConfig = {};
+ this.stormConfig = {};
}
}
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html
index d988dd1..365a8af 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html
@@ -39,6 +39,7 @@
<div *ngSwitchDefault class="row">
<div *ngIf="item.label!=''" class="col-xs-6 form-label" [ngClass]="{'form-value font-weight-bold': item.boldTitle}">{{ item.label }}</div>
+ <div *ngIf="item.model == 'sensorParserConfig'" class="col-xs-6 px-0 pull-left form-value">{{ sensorParserConfig[item.value] ? sensorParserConfig[item.value] : "-" }}</div>
<div *ngIf="item.model == 'sensorParserConfigHistory'" class="col-xs-6 px-0 pull-left form-value">{{ sensorParserConfigHistory[item.value] ? sensorParserConfigHistory[item.value] : "-" }}</div>
<div *ngIf="item.model == 'kafkaTopic'" class="col-xs-6 px-0 pull-left form-value">{{ kafkaTopic[item.value] ? kafkaTopic[item.value] : "-" }}</div>
<div *ngIf="item.model == 'topologyStatus'" class="col-xs-6 px-0 pull-left form-value">{{ getTopologyStatus(item.value) }}</div>
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
index dbbec12..5afa953 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
@@ -301,7 +301,8 @@ describe('Component: SensorParserConfigReadonly', () => {
}));
it('should have metadata defined ', async(() => {
- expect(component.editViewMetaData.length).toEqual(24);
+ // the expected value refers to the number of fields that should be visible in the readonly view
+ expect(component.editViewMetaData.length).toEqual(32);
}));
it('should have sensorsService with parserName and grokPattern defined and kafkaService defined', async(() => {
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
index b2cfef1..f28a206 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
@@ -31,6 +31,7 @@ import {RiskLevelRule} from '../../model/risk-level-rule';
import {HdfsService} from '../../service/hdfs.service';
import {RestError} from '../../model/rest-error';
import {GrokValidationService} from '../../service/grok-validation.service';
+import {SensorParserConfig} from '../../model/sensor-parser-config';
@Component({
selector: 'metron-config-sensor-parser-readonly',
@@ -43,6 +44,7 @@ export class SensorParserConfigReadonlyComponent implements OnInit {
startStopInProgress: boolean = false;
kafkaTopic: KafkaTopic = new KafkaTopic();
sensorParserConfigHistory: SensorParserConfigHistory = new SensorParserConfigHistory();
+ sensorParserConfig: SensorParserConfig = new SensorParserConfig();
topologyStatus: TopologyStatus = new TopologyStatus();
sensorEnrichmentConfig: SensorEnrichmentConfig = new SensorEnrichmentConfig();
grokStatement: string = '';
@@ -68,6 +70,14 @@ export class SensorParserConfigReadonlyComponent implements OnInit {
{label: 'THROUGHPUT', model: 'topologyStatus', value: 'throughput'},
{label: 'EMITTED(10 MIN)', model: 'topologyStatus', value: 'emitted'},
{label: 'ACKED(10 MIN)', model: 'topologyStatus', value: 'acked'},
+ {label: 'NUM WORKERS', model: 'sensorParserConfig', value: 'numWorkers'},
+ {label: 'NUM ACKERS', model: 'sensorParserConfig', value: 'numAckers'},
+ {label: 'SPOUT PARALLELISM', model: 'sensorParserConfig', value: 'spoutParallelism'},
+ {label: 'SPOUT NUM TASKS', model: 'sensorParserConfig', value: 'spoutNumTasks'},
+ {label: 'PARSER PARALLELISM', model: 'sensorParserConfig', value: 'parserParallelism'},
+ {label: 'PARSER NUM TASKS', model: 'sensorParserConfig', value: 'parserNumTasks'},
+ {label: 'ERROR WRITER PARALLELISM', model: 'sensorParserConfig', value: 'errorWriterParallelism'},
+ {label: 'ERROR NUM TASKS', model: 'sensorParserConfig', value: 'errorWriterNumTasks'},
{type: 'SPACER', model: '', value: ''},
@@ -102,6 +112,7 @@ export class SensorParserConfigReadonlyComponent implements OnInit {
this.sensorParserConfigHistoryService.get(this.selectedSensorName).subscribe(
(results: SensorParserConfigHistory) => {
this.sensorParserConfigHistory = results;
+ this.sensorParserConfig = this.sensorParserConfigHistory.config;
this.setGrokStatement();
this.setTransformsConfigKeys();
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html
index 33e8fd5..186e221 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html
@@ -34,6 +34,10 @@
[(sensorEnrichmentConfig)]="sensorEnrichmentConfig"
(hideThreatTriage)="hidePane(pane.THREATTRIAGE)"></metron-config-sensor-threat-triage>
+ <metron-config-sensor-storm-settings [hidden]="!showStormSettings" [showStormSettings]="showStormSettings" (hideStormSettings)="hidePane(pane.STORMSETTINGS)"
+ [(sensorParserConfig)]="sensorParserConfig"
+ (onStormSettingsChanged)="onStormSettingsChanged()"></metron-config-sensor-storm-settings>
+
<div class="metron-slider-pane-edit fill load-right-to-left dialog1x" style="overflow: auto" >
<div style="height:100%">
@@ -105,6 +109,19 @@
</div>
</div>
+ <div class="form-group" [ngClass]="{'panel-selected': showStormSettings }">
+ <label attr.for="stellar">STORM SETTINGS</label>
+ <div class="input-group">
+ <div class="form-control" style="resize: none;" readonly>Select</div>
+ <span class="input-group-btn">
+ <button class="btn btn-default" type="button" (click)="showPane(pane.STORMSETTINGS)" readonly>
+ <i class="fa fa-columns" aria-hidden="true"></i>
+ <i class="fa fa-angle-double-right" style="padding-left: 3px" aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </div>
+
<div [hidden]="!showAdvancedParserConfiguration">
<div class="form-group">
<div class="form-seperator-edit"></div>
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts
index a4192f1..679d057 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts
@@ -34,7 +34,7 @@ import {HdfsService} from '../../service/hdfs.service';
import {GrokValidationService} from '../../service/grok-validation.service';
export enum Pane {
- GROK, RAWJSON, FIELDSCHEMA, THREATTRIAGE
+ GROK, RAWJSON, FIELDSCHEMA, THREATTRIAGE, STORMSETTINGS
}
export enum KafkaStatus {
@@ -62,6 +62,7 @@ export class SensorParserConfigComponent implements OnInit {
showRawJson: boolean = false;
showFieldSchema: boolean = false;
showThreatTriage: boolean = false;
+ showStormSettings: boolean = false;
configValid = false;
sensorNameValid = false;
@@ -291,13 +292,6 @@ export class SensorParserConfigComponent implements OnInit {
}
onSave() {
- let sensorParserConfigSave: SensorParserConfig = new SensorParserConfig();
- sensorParserConfigSave.parserConfig = {};
- sensorParserConfigSave.sensorTopic = this.sensorParserConfig.sensorTopic;
- sensorParserConfigSave.parserClassName = this.sensorParserConfig.parserClassName;
- sensorParserConfigSave.parserConfig = this.sensorParserConfig.parserConfig;
- sensorParserConfigSave.fieldTransformations = this.sensorParserConfig.fieldTransformations;
-
if (!this.indexingConfigurations.hdfs.index) {
this.indexingConfigurations.hdfs.index = this.sensorParserConfig.sensorTopic;
}
@@ -307,7 +301,7 @@ export class SensorParserConfigComponent implements OnInit {
if (!this.indexingConfigurations.solr.index) {
this.indexingConfigurations.solr.index = this.sensorParserConfig.sensorTopic;
}
- this.sensorParserConfigService.post(sensorParserConfigSave).subscribe(
+ this.sensorParserConfigService.post(this.sensorParserConfig).subscribe(
sensorParserConfig => {
if (this.isGrokParser(sensorParserConfig)) {
this.hdfsService.post(this.sensorParserConfig.parserConfig['grokPath'], this.grokStatement).subscribe(
@@ -326,7 +320,7 @@ export class SensorParserConfigComponent implements OnInit {
this.metronAlerts.showErrorMessage(this.getMessagePrefix() + msg + error.message);
});
this.metronAlerts.showSuccessMessage(this.getMessagePrefix() + ' Sensor ' + sensorParserConfig.sensorTopic);
- this.sensorParserConfigService.dataChangedSource.next([sensorParserConfigSave]);
+ this.sensorParserConfigService.dataChangedSource.next([this.sensorParserConfig]);
this.goBack();
}, (error: RestError) => {
this.metronAlerts.showErrorMessage('Unable to save sensor config: ' + error.message);
@@ -409,12 +403,16 @@ export class SensorParserConfigComponent implements OnInit {
this.showFieldSchema = (pane === Pane.FIELDSCHEMA) ? visibilty : false;
this.showRawJson = (pane === Pane.RAWJSON) ? visibilty : false;
this.showThreatTriage = (pane === Pane.THREATTRIAGE) ? visibilty : false;
+ this.showStormSettings = (pane === Pane.STORMSETTINGS) ? visibilty : false;
}
onRawJsonChanged(): void {
this.sensorFieldSchema.createFieldSchemaRows();
}
+ onStormSettingsChanged(): void {
+ }
+
onAdvancedConfigFormClose(): void {
this.showAdvancedParserConfiguration = false;
}
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.module.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.module.ts
index 68e22f8..54e431e 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.module.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.module.ts
@@ -26,10 +26,11 @@ import {SensorGrokModule} from '../sensor-grok/sensor-grok.module';
import {SensorFieldSchemaModule} from '../sensor-field-schema/sensor-field-schema.module';
import {SensorRawJsonModule} from '../sensor-raw-json/sensor-raw-json.module';
import {SensorThreatTriageModule} from '../sensor-threat-triage/sensor-threat-triage.module';
+import {SensorStormSettingsModule} from '../sensor-storm-settings/sensor-storm-settings.module';
@NgModule ({
imports: [ routing, ReactiveFormsModule, SharedModule, NumberSpinnerModule, AdvancedConfigFormModule,
- SensorGrokModule, SensorFieldSchemaModule, SensorRawJsonModule, SensorThreatTriageModule ],
+ SensorGrokModule, SensorFieldSchemaModule, SensorRawJsonModule, SensorThreatTriageModule, SensorStormSettingsModule ],
declarations: [ SensorParserConfigComponent ]
})
export class SensorParserConfigModule { }
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-raw-json/sensor-raw-json.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-raw-json/sensor-raw-json.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-raw-json/sensor-raw-json.component.ts
index 38d9e90..4b56b62 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-raw-json/sensor-raw-json.component.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-raw-json/sensor-raw-json.component.ts
@@ -64,23 +64,8 @@ export class SensorRawJsonComponent implements OnChanges {
onSave() {
let newParsedSensorParserConfig = JSON.parse(this.newSensorParserConfig);
- this.sensorParserConfig.sensorTopic = newParsedSensorParserConfig.sensorTopic;
- this.sensorParserConfig.parserConfig = newParsedSensorParserConfig.parserConfig;
- this.sensorParserConfig.parserClassName = newParsedSensorParserConfig.parserClassName;
- this.sensorParserConfig.fieldTransformations = newParsedSensorParserConfig.fieldTransformations;
-
- if (newParsedSensorParserConfig.writerClassName != null) {
- this.sensorParserConfig.writerClassName = newParsedSensorParserConfig.writerClassName;
- }
- if (newParsedSensorParserConfig.errorWriterClassName != null) {
- this.sensorParserConfig.errorWriterClassName = newParsedSensorParserConfig.errorWriterClassName;
- }
- if (newParsedSensorParserConfig.filterClassName != null) {
- this.sensorParserConfig.filterClassName = newParsedSensorParserConfig.filterClassName;
- }
- if (newParsedSensorParserConfig.invalidWriterClassName != null) {
- this.sensorParserConfig.invalidWriterClassName = newParsedSensorParserConfig.invalidWriterClassName;
- }
+ Object.keys(newParsedSensorParserConfig).filter(key => newParsedSensorParserConfig[key])
+ .forEach(key => this.sensorParserConfig[key] = newParsedSensorParserConfig[key]);
let newParsedSensorEnrichmentConfig = JSON.parse(this.newSensorEnrichmentConfig);
this.sensorEnrichmentConfig.enrichment = Object.assign(new EnrichmentConfig(), newParsedSensorEnrichmentConfig.enrichment);
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.html b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.html
new file mode 100644
index 0000000..0e33324
--- /dev/null
+++ b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.html
@@ -0,0 +1,104 @@
+<!--
+ Licensed to the Apache Software
+ Foundation (ASF) under one or more contributor license agreements. See the
+ NOTICE file distributed with this work for additional information regarding
+ copyright ownership. The ASF licenses this file to You under the Apache License,
+ Version 2.0 (the "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+ the specific language governing permissions and limitations under the License.
+ -->
+<div class="metron-slider-pane-edit fill load-left-to-right dialog2x">
+
+ <div class="form-group">
+ <div class="form-title">Configure Storm Settings</div>
+ <i class="fa fa-times pull-right close-button" aria-hidden="true" (click)="onCancel()"></i>
+ </div>
+
+
+ <form role="form" class="enrichments-form">
+ <div class="form-group">
+ <label attr.for="numWorkers">NUM WORKERS</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="numWorkers" [(ngModel)]="newSensorParserConfig.numWorkers" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <div><label *ngIf="!newSensorParserConfig.numWorkers"><span class="warning-text"> This uses Storm defaults if not set </span></label></div>
+ <label *ngIf="newSensorParserConfig.numWorkers !== sensorParserConfig.numWorkers"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="numAckers">NUM ACKERS</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="numAckers" [(ngModel)]="newSensorParserConfig.numAckers" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <div><label *ngIf="!newSensorParserConfig.numAckers"><span class="warning-text"> This uses Storm defaults if not set </span></label></div>
+ <label *ngIf="newSensorParserConfig.numAckers !== sensorParserConfig.numAckers"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="spoutParallelism">SPOUT PARALLELISM</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="spoutParallelism" [(ngModel)]="newSensorParserConfig.spoutParallelism" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.spoutParallelism !== sensorParserConfig.spoutParallelism"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="spoutNumTasks">SPOUT NUM TASKS</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="spoutNumTasks" [(ngModel)]="newSensorParserConfig.spoutNumTasks" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.spoutNumTasks !== sensorParserConfig.spoutNumTasks"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="parserParallelism">PARSER PARALLELISM</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="parserParallelism" [(ngModel)]="newSensorParserConfig.parserParallelism" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.parserParallelism !== sensorParserConfig.parserParallelism"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="parserNumTasks">PARSER NUM TASKS</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="parserNumTasks" [(ngModel)]="newSensorParserConfig.parserNumTasks" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.parserNumTasks !== sensorParserConfig.parserNumTasks"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="errorWriterParallelism">ERROR WRITER PARALLELISM</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="errorWriterParallelism" [(ngModel)]="newSensorParserConfig.errorWriterParallelism" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.errorWriterParallelism !== sensorParserConfig.errorWriterParallelism"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="errorWriterNumTasks">ERROR WRITER NUM TASKS</label>
+ <div style="width: 25%">
+ <metron-config-number-spinner name="errorWriterNumTasks" [(ngModel)]="newSensorParserConfig.errorWriterNumTasks" [min]="1"> </metron-config-number-spinner>
+ </div>
+ <label *ngIf="newSensorParserConfig.errorWriterNumTasks !== sensorParserConfig.errorWriterNumTasks"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="newSpoutConfig">SPOUT CONFIG</label>
+ <metron-config-ace-editor [(ngModel)]="newSpoutConfig" [ngModelOptions]="{standalone: true}" [type]="'JSON'" [placeHolder]="'Enter Spout Config'"> </metron-config-ace-editor>
+ <label *ngIf="hasSpoutConfigChanged()"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+ <div class="form-group">
+ <label attr.for="newStormConfig">STORM CONFIG</label>
+ <metron-config-ace-editor [(ngModel)]="newStormConfig" [ngModelOptions]="{standalone: true}" [type]="'JSON'" [placeHolder]="'Enter Storm Config'"> </metron-config-ace-editor>
+ <label *ngIf="hasStormConfigChanged()"><span class="warning-text"> This change requires a parser topology restart </span></label>
+ </div>
+
+ <div class="form-group">
+ <div class="form-seperator-edit"></div>
+ <div class="button-row">
+ <button type="submit" class="btn form-enable-disable-button" (click)="onSave()">SAVE</button>
+ <button class="btn form-enable-disable-button" (click)="onCancel()" >CANCEL</button>
+ </div>
+ </div>
+
+ </form>
+
+</div>
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.scss b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.scss
new file mode 100644
index 0000000..3a9f5e3
--- /dev/null
+++ b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.scss
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+textarea
+{
+ height: auto;
+}
+
+.form-group
+{
+ padding-left: 25px;
+ padding-right: 20px;
+ padding-bottom: 10px;
+}
+
+.button-row {
+ padding-top: 10px;
+}
+
+.form-enable-disable-button {
+ width: 16%;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.spec.ts b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.spec.ts
new file mode 100644
index 0000000..02f1fd9
--- /dev/null
+++ b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.spec.ts
@@ -0,0 +1,168 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {async, TestBed, ComponentFixture} from '@angular/core/testing';
+import {SensorStormSettingsComponent} from './sensor-storm-settings.component';
+import {SharedModule} from '../../shared/shared.module';
+import {SimpleChanges, SimpleChange} from '@angular/core';
+import {SensorParserConfig} from '../../model/sensor-parser-config';
+import {SensorStormSettingsModule} from './sensor-storm-settings.module';
+import '../../rxjs-operators';
+
+describe('Component: SensorStormSettingsComponent', () => {
+
+ let fixture: ComponentFixture<SensorStormSettingsComponent>;
+ let component: SensorStormSettingsComponent;
+ let sensorParserConfig: SensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.sensorTopic = 'bro';
+ sensorParserConfig.parserClassName = 'org.apache.metron.parsers.bro.BasicBroParser';
+ sensorParserConfig.parserConfig = {};
+ sensorParserConfig.numWorkers = 2;
+ sensorParserConfig.numAckers = 2;
+ sensorParserConfig.spoutParallelism = 2;
+ sensorParserConfig.spoutNumTasks = 2;
+ sensorParserConfig.parserParallelism = 2;
+ sensorParserConfig.parserNumTasks = 2;
+ sensorParserConfig.errorWriterParallelism = 2;
+ sensorParserConfig.errorWriterNumTasks = 2;
+ sensorParserConfig.spoutConfig = {'spoutConfigProp': 'spoutConfigValue1'};
+ sensorParserConfig.stormConfig = {'stormConfigProp': 'stormConfigValue1'};
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [SharedModule, SensorStormSettingsModule],
+ });
+
+ fixture = TestBed.createComponent(SensorStormSettingsComponent);
+ component = fixture.componentInstance;
+ }));
+
+ it('should create an instance', () => {
+ expect(component).toBeDefined();
+ });
+
+ it('should create an instance', () => {
+ spyOn(component, 'init');
+ let changes: SimpleChanges = {'showStormSettings': new SimpleChange(false, true)};
+
+ component.ngOnChanges(changes);
+ expect(component.init).toHaveBeenCalled();
+
+ changes = {'showStormSettings': new SimpleChange(true, false)};
+ component.ngOnChanges(changes);
+ expect(component.init['calls'].count()).toEqual(1);
+
+ fixture.destroy();
+ });
+
+ it('should initialise the fields', () => {
+
+ component.init();
+ expect(component.newSensorParserConfig).toEqual(new SensorParserConfig());
+
+ component.sensorParserConfig = sensorParserConfig;
+ component.init();
+ expect(component.newSensorParserConfig).toEqual(sensorParserConfig);
+ expect(component.newSpoutConfig).toEqual('{\n\t"spoutConfigProp": "spoutConfigValue1"\n}');
+ expect(component.newStormConfig).toEqual('{\n\t"stormConfigProp": "stormConfigValue1"\n}');
+
+ fixture.destroy();
+ });
+
+ it('should save the fields', () => {
+ spyOn(component.hideStormSettings, 'emit');
+ spyOn(component.onStormSettingsChanged, 'emit');
+ component.sensorParserConfig = sensorParserConfig;
+ component.init();
+ component.newSensorParserConfig.numWorkers = 3;
+ component.newSensorParserConfig.numAckers = 3;
+ component.newSensorParserConfig.spoutParallelism = 3;
+ component.newSensorParserConfig.spoutNumTasks = 3;
+ component.newSensorParserConfig.parserParallelism = 3;
+ component.newSensorParserConfig.parserNumTasks = 3;
+ component.newSensorParserConfig.errorWriterParallelism = 3;
+ component.newSensorParserConfig.errorWriterNumTasks = 3;
+ component.newSpoutConfig = '{"spoutConfigProp": "spoutConfigValue2"}';
+ component.newStormConfig = '{"stormConfigProp": "stormConfigValue2"}';
+ component.onSave();
+ expect(component.sensorParserConfig.numWorkers).toEqual(3);
+ expect(component.sensorParserConfig.numAckers).toEqual(3);
+ expect(component.sensorParserConfig.spoutParallelism).toEqual(3);
+ expect(component.sensorParserConfig.spoutNumTasks).toEqual(3);
+ expect(component.sensorParserConfig.parserParallelism).toEqual(3);
+ expect(component.sensorParserConfig.parserNumTasks).toEqual(3);
+ expect(component.sensorParserConfig.errorWriterParallelism).toEqual(3);
+ expect(component.sensorParserConfig.errorWriterNumTasks).toEqual(3);
+ expect(component.sensorParserConfig.spoutConfig).toEqual({'spoutConfigProp': 'spoutConfigValue2'});
+ expect(component.sensorParserConfig.stormConfig).toEqual({'stormConfigProp': 'stormConfigValue2'});
+ expect(component.hideStormSettings.emit).toHaveBeenCalled();
+ expect(component.onStormSettingsChanged.emit).toHaveBeenCalled();
+ });
+
+ it('hasSpoutConfigChanged should properly detect changes', () => {
+ let sensorParserConfigWithSpoutConfig = new SensorParserConfig();
+ sensorParserConfigWithSpoutConfig.spoutConfig = {};
+ component.sensorParserConfig = sensorParserConfigWithSpoutConfig;
+ component.newSpoutConfig = '{}';
+ expect(component.hasSpoutConfigChanged()).toEqual(false);
+
+ sensorParserConfigWithSpoutConfig.spoutConfig = {'field': 'value'};
+ component.sensorParserConfig = sensorParserConfigWithSpoutConfig;
+ component.newSpoutConfig = '{ "field" : "value" }';
+ expect(component.hasSpoutConfigChanged()).toEqual(false);
+
+ sensorParserConfigWithSpoutConfig.spoutConfig = {'field': 'value'};
+ component.sensorParserConfig = sensorParserConfigWithSpoutConfig;
+ component.newSpoutConfig = '{"field": "value2"}';
+ expect(component.hasSpoutConfigChanged()).toEqual(true);
+
+ component.newSpoutConfig = '{"field": "value2", }';
+ expect(component.hasSpoutConfigChanged()).toEqual(true);
+ });
+
+ it('hasStormConfigChanged should properly detect changes', () => {
+ let sensorParserConfigWithStormConfig = new SensorParserConfig();
+ sensorParserConfigWithStormConfig.stormConfig = {};
+ component.sensorParserConfig = sensorParserConfigWithStormConfig;
+ component.newStormConfig = '{}';
+ expect(component.hasStormConfigChanged()).toEqual(false);
+
+ sensorParserConfigWithStormConfig.stormConfig = {'field': 'value'};
+ component.sensorParserConfig = sensorParserConfigWithStormConfig;
+ component.newStormConfig = '{ "field" : "value" }';
+ expect(component.hasStormConfigChanged()).toEqual(false);
+
+ sensorParserConfigWithStormConfig.stormConfig = {'field': 'value'};
+ component.sensorParserConfig = sensorParserConfigWithStormConfig;
+ component.newStormConfig = '{"field": "value2"}';
+ expect(component.hasStormConfigChanged()).toEqual(true);
+
+ component.newSpoutConfig = '{"field": "value2", }';
+ expect(component.hasStormConfigChanged()).toEqual(true);
+ });
+
+ it('should hide panel', () => {
+ spyOn(component.hideStormSettings, 'emit');
+
+ component.onCancel();
+
+ expect(component.hideStormSettings.emit).toHaveBeenCalled();
+
+ fixture.destroy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.ts
new file mode 100644
index 0000000..a393da8
--- /dev/null
+++ b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.component.ts
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Component, Input, EventEmitter, Output, OnChanges, SimpleChanges} from '@angular/core';
+import {SensorParserConfig} from '../../model/sensor-parser-config';
+
+declare var ace: any;
+
+@Component({
+ selector: 'metron-config-sensor-storm-settings',
+ templateUrl: './sensor-storm-settings.component.html',
+ styleUrls: ['./sensor-storm-settings.component.scss']
+})
+
+export class SensorStormSettingsComponent implements OnChanges {
+
+ @Input() showStormSettings: boolean;
+ @Input() sensorParserConfig: SensorParserConfig;
+
+ @Output() hideStormSettings: EventEmitter<boolean> = new EventEmitter<boolean>();
+ @Output() onStormSettingsChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
+
+ newSensorParserConfig: SensorParserConfig = new SensorParserConfig();
+ newSpoutConfig: string = '{}';
+ newStormConfig: string = '{}';
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes['showStormSettings'] && changes['showStormSettings'].currentValue) {
+ this.init();
+ }
+ }
+
+ init(): void {
+ if (this.sensorParserConfig) {
+ this.newSensorParserConfig = Object.assign(new SensorParserConfig(), this.sensorParserConfig);
+ this.newSpoutConfig = JSON.stringify(this.sensorParserConfig.spoutConfig, null, '\t');
+ this.newStormConfig = JSON.stringify(this.sensorParserConfig.stormConfig, null, '\t');
+ }
+ }
+
+ onSave() {
+ this.sensorParserConfig.numWorkers = this.newSensorParserConfig.numWorkers;
+ this.sensorParserConfig.numAckers = this.newSensorParserConfig.numAckers;
+ this.sensorParserConfig.spoutParallelism = this.newSensorParserConfig.spoutParallelism;
+ this.sensorParserConfig.spoutNumTasks = this.newSensorParserConfig.spoutNumTasks;
+ this.sensorParserConfig.parserParallelism = this.newSensorParserConfig.parserParallelism;
+ this.sensorParserConfig.parserNumTasks = this.newSensorParserConfig.parserNumTasks;
+ this.sensorParserConfig.errorWriterParallelism = this.newSensorParserConfig.errorWriterParallelism;
+ this.sensorParserConfig.errorWriterNumTasks = this.newSensorParserConfig.errorWriterNumTasks;
+ this.sensorParserConfig.spoutConfig = JSON.parse(this.newSpoutConfig);
+ this.sensorParserConfig.stormConfig = JSON.parse(this.newStormConfig);
+ this.hideStormSettings.emit(true);
+ this.onStormSettingsChanged.emit(true);
+ }
+
+ onCancel(): void {
+ this.hideStormSettings.emit(true);
+ }
+
+ hasSpoutConfigChanged(): boolean {
+ try {
+ // serialize/deserialize to ignore formatting differences
+ return JSON.stringify(JSON.parse(this.newSpoutConfig), null, '\t') !==
+ JSON.stringify(this.sensorParserConfig.spoutConfig, null, '\t');
+ } catch (err) {
+ // malformed json means it is being edited
+ return true;
+ }
+ }
+
+ hasStormConfigChanged(): boolean {
+ try {
+ // serialize/deserialize to ignore formatting differences
+ return JSON.stringify(JSON.parse(this.newStormConfig), null, '\t') !==
+ JSON.stringify(this.sensorParserConfig.stormConfig, null, '\t');
+ } catch (err) {
+ // malformed json means it is being edited
+ return true;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/d69101a8/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.module.ts b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.module.ts
new file mode 100644
index 0000000..910e3aa
--- /dev/null
+++ b/metron-interface/metron-config/src/app/sensors/sensor-storm-settings/sensor-storm-settings.module.ts
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { NgModule } from '@angular/core';
+import {SharedModule} from '../../shared/shared.module';
+import {SensorStormSettingsComponent} from './sensor-storm-settings.component';
+import {AceEditorModule} from '../../shared/ace-editor/ace-editor.module';
+import {NumberSpinnerModule} from '../../shared/number-spinner/number-spinner.module';
+
+@NgModule ({
+ imports: [ SharedModule, AceEditorModule, NumberSpinnerModule ],
+ declarations: [ SensorStormSettingsComponent ],
+ exports: [ SensorStormSettingsComponent ]
+})
+export class SensorStormSettingsModule {}