Skip to content

Commit dcf2ea3

Browse files
[CYB-208] OCSF parser config support (#85)
* OCSF support parser config support * switched from field selection to a text field * Java tests fix * Karma tests fix * parsers base path fix * minor refactoring to address the Observable subscription issues * Hidden objects with unknown types
1 parent 75e903c commit dcf2ea3

File tree

45 files changed

+118711
-182
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+118711
-182
lines changed

flink-cyber/flink-cyber-api/src/main/java/com/cloudera/cyber/indexing/MappingColumnDto.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cloudera.cyber.indexing;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnore;
34
import com.fasterxml.jackson.annotation.JsonProperty;
45
import lombok.AllArgsConstructor;
56
import lombok.Data;
@@ -26,6 +27,7 @@ public class MappingColumnDto {
2627
@JsonProperty("is_map")
2728
private Boolean isMap;
2829

30+
@JsonIgnore
2931
public String getKafkaName() {
3032
final String properName = kafkaName == null ? name : kafkaName;
3133
if (getIsMap()) {
@@ -38,6 +40,7 @@ public String getKafkaName() {
3840
}
3941
}
4042

43+
@JsonIgnore
4144
public String getRawKafkaName(){
4245
return kafkaName;
4346
}

flink-cyber/flink-indexing/flink-indexing-hive/src/main/java/com/cloudera/cyber/indexing/hive/util/AvroSchemaUtil.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
import org.apache.flink.types.Row;
1515

1616
import java.time.Instant;
17-
import java.util.*;
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
21+
import java.util.Set;
1822

19-
public class AvroSchemaUtil {
23+
public final class AvroSchemaUtil {
2024

2125
//method that converts from flink Schema to avro Schema
2226
public static Schema convertToAvro(List<TableColumnDto> tableColumnList) {

flink-cyber/flink-indexing/flink-indexing-hive/src/main/java/com/cloudera/cyber/indexing/hive/util/FlinkSchemaUtil.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package com.cloudera.cyber.indexing.hive.util;
22

33
import com.cloudera.cyber.indexing.TableColumnDto;
4-
import java.util.ArrayList;
5-
import java.util.List;
6-
import java.util.Optional;
7-
import java.util.stream.Collectors;
84
import org.apache.flink.table.api.DataTypes;
95
import org.apache.flink.table.api.Schema;
106
import org.apache.flink.table.catalog.Column;
117
import org.apache.flink.table.catalog.ResolvedSchema;
128
import org.apache.flink.table.types.DataType;
139

14-
public class FlinkSchemaUtil {
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Optional;
13+
import java.util.stream.Collectors;
14+
15+
public final class FlinkSchemaUtil {
1516

1617
public static Schema buildSchema(ResolvedSchema resolvedSchema) {
1718
return Schema.newBuilder()

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/.eslintrc.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@
107107
},
108108
{
109109
"selector": "memberLike",
110-
"format": ["camelCase"],
110+
"format": [
111+
"camelCase",
112+
"snake_case"
113+
],
111114
"leadingUnderscore": "forbid"
112115
},
113116
{
@@ -133,6 +136,15 @@
133136
"type": "attribute"
134137
}
135138
],
139+
"@typescript-eslint/ban-types": [
140+
"error",
141+
{
142+
"extendDefaults": true,
143+
"types": {
144+
"{}": false
145+
}
146+
}
147+
],
136148
"@angular-eslint/no-empty-lifecycle-method": "error"
137149
}
138150
},

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/chain-page.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
<app-indexing-form
4444
(fieldSetUpdated)="updateAllFields($event)"></app-indexing-form>
4545
</nz-tab>
46+
<nz-tab class="ocsf-tab" nzTitle="OCSF builder">
47+
<app-ocsf-form></app-ocsf-form>
48+
</nz-tab>
4649
</nz-tabset>
4750
</div>
4851
<div nz-col nzSpan="14">

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/chain-page.models.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,17 @@ export interface ChainDetailsModel {
5959
name: string;
6060
parsers: ParserModel[];
6161
}
62+
63+
export interface IndexTableMapping {
64+
table_name: string;
65+
ignore_fields?: string[]
66+
column_mapping: IndexingColumnMapping[]
67+
}
68+
69+
export interface IndexingColumnMapping {
70+
name: string;
71+
kafka_name?: string;
72+
path?: string;
73+
transformation?: string;
74+
is_map?: boolean;
75+
}

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/chain-page.module.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ import {NzLayoutModule} from "ng-zorro-antd/layout";
5252
import {NzAutocompleteModule} from "ng-zorro-antd/auto-complete";
5353
import {NzCheckboxModule} from "ng-zorro-antd/checkbox";
5454
import {MonacoEditorModule} from "ngx-monaco-editor-v2";
55+
import {OcsfFormComponent} from './components/ocsf-form/ocsf-form.component';
56+
import {MatCardModule} from "@angular/material/card";
57+
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
58+
import {NzDividerModule} from "ng-zorro-antd/divider";
59+
import {NzSwitchModule} from "ng-zorro-antd/switch";
60+
import {OcsfObjectFormComponent} from './components/ocsf-form/ocsf-object-form/ocsf-object-form.component';
5561

5662
@NgModule({
5763
declarations: [
@@ -66,6 +72,8 @@ import {MonacoEditorModule} from "ngx-monaco-editor-v2";
6672
AutofocusDirective,
6773
MultiInputComponent,
6874
IndexingFormComponent,
75+
OcsfFormComponent,
76+
OcsfObjectFormComponent,
6977
],
7078
entryComponents: [ ChainViewComponent ],
7179
imports: [
@@ -95,6 +103,10 @@ import {MonacoEditorModule} from "ngx-monaco-editor-v2";
95103
NzLayoutModule,
96104
NzAutocompleteModule,
97105
NzCheckboxModule,
106+
MatCardModule,
107+
MatProgressSpinnerModule,
108+
NzDividerModule,
109+
NzSwitchModule,
98110
],
99111
providers: [
100112
NzMessageService,

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/components/live-view/live-view.effects.spec.ts

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {LiveViewEffects} from './live-view.effects';
3131
import {SampleDataType} from './models/sample-data.model';
3232
import {LiveViewService} from './services/live-view.service';
3333
import {EntryParsingResultModel} from "./models/live-view.model";
34+
import {provideMockStore} from "@ngrx/store/testing";
3435

3536
describe('live-view.effects', () => {
3637

@@ -46,11 +47,24 @@ describe('live-view.effects', () => {
4647
}
4748
};
4849

49-
const testResult:EntryParsingResultModel[] =
50-
[
50+
const selectedPipeline = 'foo-pipeline';
51+
const chainListPageInitialState = {
52+
items: [],
53+
createModalVisible: false,
54+
deleteModalVisible: false,
55+
deleteItem: null,
56+
loading: false,
57+
error: '',
58+
pipelines: null,
59+
pipelineRenameModalVisible: false,
60+
selectedPipeline: selectedPipeline
61+
};
62+
63+
const testResult: EntryParsingResultModel[] =
64+
[
5165
{
5266
output: 'output result',
53-
log: { type: '', message: 'log result', stackTrace: '' },
67+
log: {type: '', message: 'log result', stackTrace: ''},
5468
}
5569
];
5670

@@ -63,12 +77,20 @@ describe('live-view.effects', () => {
6377
TestBed.configureTestingModule({
6478
providers: [
6579
LiveViewEffects,
66-
{ provide: LiveViewService, useValue: jasmine.createSpyObj('LiveViewService', {
80+
{
81+
provide: LiveViewService, useValue: jasmine.createSpyObj('LiveViewService', {
6782
execute: of({results: testResult})
68-
}) },
69-
{ provide: NzMessageService, useValue: jasmine.createSpyObj('NzMessageService', ['create']) },
70-
71-
provideMockActions(() => actions$)],
83+
})
84+
},
85+
{provide: NzMessageService, useValue: jasmine.createSpyObj('NzMessageService', ['create'])},
86+
87+
provideMockActions(() => actions$),
88+
provideMockStore({
89+
initialState: {
90+
'chain-list-page': chainListPageInitialState
91+
},
92+
selectors: []
93+
})],
7294
});
7395

7496
liveViewEffects = TestBed.inject(LiveViewEffects) as jasmine.SpyObj<LiveViewEffects>;
@@ -80,16 +102,16 @@ describe('live-view.effects', () => {
80102
const testSubscriber = jasmine.createSpy('executionTriggeredSpy');
81103
liveViewEffects.execute$.subscribe(testSubscriber);
82104

83-
actions$.next(executionTriggered({ ...testPayload }));
105+
actions$.next(executionTriggered({...testPayload}));
84106

85-
expect(fakeLiveViewService.execute).toHaveBeenCalledWith(testPayload.sampleData, testPayload.chainConfig);
107+
expect(fakeLiveViewService.execute).toHaveBeenCalledWith(testPayload.sampleData, testPayload.chainConfig, selectedPipeline);
86108
});
87109

88110
it('should dispatch liveViewRefreshedSuccessfully if liveViewService execute successfully', () => {
89111
const testSubscriber = jasmine.createSpy('executionTriggeredSpy');
90112
liveViewEffects.execute$.subscribe(testSubscriber);
91113

92-
actions$.next(executionTriggered({ ...testPayload }));
114+
actions$.next(executionTriggered({...testPayload}));
93115

94116
expect(testSubscriber).toHaveBeenCalledWith({
95117
liveViewResult: {
@@ -103,9 +125,9 @@ describe('live-view.effects', () => {
103125
const testSubscriber = jasmine.createSpy('executionTriggeredSpy');
104126
liveViewEffects.execute$.subscribe(testSubscriber);
105127

106-
fakeLiveViewService.execute.and.returnValue(throwError({ message: 'something went wrong' }));
128+
fakeLiveViewService.execute.and.returnValue(throwError({message: 'something went wrong'}));
107129

108-
actions$.next(executionTriggered({ ...testPayload }));
130+
actions$.next(executionTriggered({...testPayload}));
109131

110132
expect(testSubscriber).toHaveBeenCalledWith({
111133
error: {
@@ -116,11 +138,11 @@ describe('live-view.effects', () => {
116138
});
117139

118140
it('should show error message if liveViewService execution fail', () => {
119-
fakeLiveViewService.execute.and.returnValue(throwError({ message: 'something went wrong' }));
141+
fakeLiveViewService.execute.and.returnValue(throwError({message: 'something went wrong'}));
120142

121143
liveViewEffects.execute$.subscribe();
122144

123-
actions$.next(executionTriggered({ ...testPayload }));
145+
actions$.next(executionTriggered({...testPayload}));
124146

125147
expect(fakeMessageService.create).toHaveBeenCalledWith('error', 'something went wrong');
126148
});
@@ -130,24 +152,27 @@ describe('live-view.effects', () => {
130152

131153
liveViewEffects.persistingSampleData$.subscribe();
132154

133-
actions$.next(sampleDataInputChanged({ sampleData: { type: SampleDataType.MANUAL, source: 'testing persistance' } }));
155+
actions$.next(sampleDataInputChanged({sampleData: {type: SampleDataType.MANUAL, source: 'testing persistance'}}));
134156

135157
expect(localStorage.setItem).toHaveBeenCalledWith(
136158
LiveViewConsts.SAMPLE_DATA_STORAGE_KEY,
137-
JSON.stringify({ type: SampleDataType.MANUAL, source: 'testing persistance' })
159+
JSON.stringify({type: SampleDataType.MANUAL, source: 'testing persistance'})
138160
);
139161
});
140162

141163
it('should restore sample data input from local storage on liveViewInitialized action', () => {
142164
const testSubscriber = jasmine.createSpy('sampleDataRestoredSpy');
143165
liveViewEffects.restoreSampleDataFromLocalStore.subscribe(testSubscriber);
144166

145-
spyOn(localStorage, 'getItem').and.returnValue(JSON.stringify({ type: SampleDataType.MANUAL, source: 'persisted state' }));
167+
spyOn(localStorage, 'getItem').and.returnValue(JSON.stringify({
168+
type: SampleDataType.MANUAL,
169+
source: 'persisted state'
170+
}));
146171

147172
actions$.next(liveViewInitialized());
148173

149174
expect(testSubscriber).toHaveBeenCalledWith({
150-
sampleData: { type: SampleDataType.MANUAL, source: 'persisted state' },
175+
sampleData: {type: SampleDataType.MANUAL, source: 'persisted state'},
151176
type: sampleDataRestored.type
152177
});
153178
});
@@ -157,7 +182,7 @@ describe('live-view.effects', () => {
157182

158183
liveViewEffects.persistingOnOffToggle$.subscribe();
159184

160-
actions$.next(onOffToggleChanged({ value: true }));
185+
actions$.next(onOffToggleChanged({value: true}));
161186

162187
expect(localStorage.setItem).toHaveBeenCalledWith(
163188
LiveViewConsts.FEATURE_TOGGLE_STORAGE_KEY,
@@ -175,7 +200,7 @@ describe('live-view.effects', () => {
175200

176201
expect(testSubscriber).toHaveBeenCalledWith({
177202
value: true,
178-
type: onOffToggleRestored .type
203+
type: onOffToggleRestored.type
179204
});
180205
});
181206

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/components/live-view/live-view.effects.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
import {Injectable} from '@angular/core';
1414
import {Actions, createEffect, ofType} from '@ngrx/effects';
15-
import {Action} from '@ngrx/store';
15+
import {Action, Store} from '@ngrx/store';
1616
import {NzMessageService} from 'ng-zorro-antd/message';
1717
import {Observable, of} from 'rxjs';
18-
import {catchError, map, switchMap, tap} from 'rxjs/operators';
18+
import {catchError, map, switchMap, tap, withLatestFrom} from 'rxjs/operators';
1919

2020
import {
2121
executionTriggered,
@@ -30,6 +30,7 @@ import {
3030
} from './live-view.actions';
3131
import {LiveViewConsts} from './live-view.consts';
3232
import {LiveViewService} from './services/live-view.service';
33+
import {ChainListPageState, getSelectedPipeline} from "../../../chain-list-page/chain-list-page.reducers";
3334

3435
@Injectable()
3536
export class LiveViewEffects {
@@ -38,8 +39,9 @@ export class LiveViewEffects {
3839
ofType(
3940
executionTriggered.type,
4041
),
41-
switchMap(({ sampleData, chainConfig }) => {
42-
return this._liveViewService.execute(sampleData, chainConfig).pipe(
42+
withLatestFrom(this._store$.select(getSelectedPipeline)),
43+
switchMap(([{sampleData, chainConfig}, selectedPipeline]) => {
44+
return this._liveViewService.execute(sampleData, chainConfig, selectedPipeline).pipe(
4345
map(liveViewResult => liveViewRefreshedSuccessfully({ liveViewResult })),
4446
catchError(( error: { message: string }) => {
4547
this._messageService.create('error', error.message);
@@ -89,6 +91,7 @@ export class LiveViewEffects {
8991

9092
constructor(
9193
private _actions$: Actions<LiveViewActionsType>,
94+
private _store$: Store<ChainListPageState>,
9295
private _liveViewService: LiveViewService,
9396
private _messageService: NzMessageService,
9497
) {}

flink-cyber/metron-parser-chain/parser-chains-config-service/frontend/parser-chains-client/src/app/chain-page/components/live-view/services/live-view.service.spec.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
* limitations governing your use of the file.
1111
*/
1212

13-
import { HttpClient } from '@angular/common/http';
14-
import { HttpClientTestingModule } from '@angular/common/http/testing';
13+
import {HttpClient, HttpParams} from '@angular/common/http';
14+
import {HttpClientTestingModule} from '@angular/common/http/testing';
1515
import {TestBed} from '@angular/core/testing';
1616

17-
import { SampleDataType } from '../models/sample-data.model';
17+
import {SampleDataType} from '../models/sample-data.model';
1818

19-
import { LiveViewService } from './live-view.service';
19+
import {LiveViewService} from './live-view.service';
2020

2121
describe('LiveViewService', () => {
2222
let service: LiveViewService;
@@ -40,16 +40,17 @@ describe('LiveViewService', () => {
4040
spyOn(http, 'post');
4141

4242
service.execute(
43-
{ type: SampleDataType.MANUAL, source: 'test sample input' },
44-
{ id: '456', name: 'gdf', parsers: [] }
43+
{type: SampleDataType.MANUAL, source: 'test sample input'},
44+
{id: '456', name: 'gdf', parsers: []}
4545
);
4646

4747
expect(http.post).toHaveBeenCalledWith(
4848
LiveViewService.BASE_URL,
4949
{
50-
sampleData: { type: SampleDataType.MANUAL, source: ['test sample input'] },
51-
chainConfig: { id: '456', name: 'gdf', parsers: [] }
52-
}
50+
sampleData: {type: SampleDataType.MANUAL, source: ['test sample input']},
51+
chainConfig: {id: '456', name: 'gdf', parsers: []}
52+
},
53+
{params: new HttpParams()}
5354
);
5455
});
5556
});

0 commit comments

Comments
 (0)