Skip to content

Commit

Permalink
Merging parallel actions branch. Implements Parallelizable Actions fu…
Browse files Browse the repository at this point in the history
…nctionality as well as UI components.
  • Loading branch information
emrodas10 committed May 17, 2019
2 parents 40a0002 + 96e551f commit e705358
Show file tree
Hide file tree
Showing 24 changed files with 242 additions and 117 deletions.
5 changes: 5 additions & 0 deletions api_gateway/client/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@
<link rel="stylesheet" href="client/dist/styles.742a6a1aa8c96b0fb631.css"></head>
<body>
<main-component>Loading...</main-component>
<<<<<<< HEAD
<script type="text/javascript" src="client/dist/runtime.0cd64862052be0d1bb28.js"></script><script type="text/javascript" src="client/dist/polyfills.f6ae3e8b63939c618130.js"></script><script type="text/javascript" src="client/dist/scripts.88dd31992d945374bfe1.js"></script><script type="text/javascript" src="client/dist/main.30a81b2dca2a1ab05959.js"></script></body>
</html>
=======
<script type="text/javascript" src="client/dist/runtime.0cd64862052be0d1bb28.js"></script><script type="text/javascript" src="client/dist/polyfills.f6ae3e8b63939c618130.js"></script><script type="text/javascript" src="client/dist/scripts.88dd31992d945374bfe1.js"></script><script type="text/javascript" src="client/dist/main.1e3e45e9b22e673a52bf.js"></script></body>
</html>
>>>>>>> 96e551f13925e76de1e8fb835aaed0999ef25b1b

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions api_gateway/client/src/app/execution/execution.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ <h1>Execution Control</h1>
<i class="fa fa-play"></i>
Execute Workflow
</button>
<button *ngIf="selectedWorkflow && selectedWorkflow.referenced_variables.length > 0" (click)="openVariableModal()" title="Edit Environment Variables" class="btn btn-outline-primary mx-1">
<button *ngIf="selectedWorkflow && selectedWorkflow.referenced_variables.length > 0" (click)="openVariableModal()" title="Edit Workflow Variables" class="btn btn-outline-primary mx-1">
<i class="fa fa-cog"></i>
Edit Environment Variables
Edit Workflow Variables
</button>
</div>
<div class="col col-lg-4 my-1 my-lg-none">
Expand Down Expand Up @@ -87,7 +87,7 @@ <h5 class="modal-title" id="nodeStatusModalTitle">Action Statuses for {{loadedWo
[sortType]="'multi'" [headerHeight]="50" [footerHeight]="50" [rowHeight]="undefined" [sorts]="[{prop: 'started_at', dir: 'desc'}]"
[limit]="10">
<!-- Column Templates -->
<ngx-datatable-column name="ID" prop="node_id" [flexGrow]="2"></ngx-datatable-column>
<ngx-datatable-column name="ID" prop="node_id" [flexGrow]="3"></ngx-datatable-column>
<ngx-datatable-column name="App Name" prop="app_name" [flexGrow]="1"></ngx-datatable-column>
<ngx-datatable-column name="Action Name" prop="name" [flexGrow]="1"></ngx-datatable-column>
<ngx-datatable-column name="Started At" prop="started_at" [flexGrow]="1">
Expand All @@ -110,7 +110,7 @@ <h5 class="modal-title" id="nodeStatusModalTitle">Action Statuses for {{loadedWo
{{getFriendlyArguments(row.arguments)}}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column name="Result" [sortable]="false" [flexGrow]="3">
<ngx-datatable-column name="Result" [sortable]="false" [flexGrow]="4">
<ng-template let-row="row" ngx-datatable-cell-template>
{{getFriendlyJSON(row.result)}}
</ng-template>
Expand Down
15 changes: 14 additions & 1 deletion api_gateway/client/src/app/execution/execution.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ExecutionService {
addWorkflowToQueue(workflow_id: string, execution_id: string = null, variables: EnvironmentVariable[] = []): Promise<WorkflowStatus> {
let data: any = { workflow_id };
if (execution_id) data.execution_id = execution_id;
if (variables.length > 0) data.environment_variables = classToPlain(variables);
if (variables.length > 0) data.workflow_variables = classToPlain(variables);

return this.http.post('api/workflowqueue', data)
.toPromise()
Expand All @@ -44,6 +44,19 @@ export class ExecutionService {
.catch(this.utils.handleResponseError);
}

/**
* For a given executing workflow, asyncronously perform some action to change its status.
* Only returns success
* @param executionId Execution ID to act upon
* @param action Action to take (e.g. abort, resume, pause)
*/
performWorkflowTrigger(executionId: string, trigger: string, data = {}): Promise<void> {
return this.http.patch(`api/workflowqueue/${ executionId }`, { status: 'trigger', trigger_id: trigger, trigger_data: data})
.toPromise()
.then(() => null)
.catch(this.utils.handleResponseError);
}

/**
* Asyncronously gets an array of workflow statuses from the server.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class ExecutionVariableModalComponent {
if (form.value[variable.id] && form.value[variable.id] != '') {
let newV = new EnvironmentVariable();
newV.id = variable.id;
newV.name = variable.name;
newV.value = form.value[variable.id];
variables.push(newV);
}
Expand Down
8 changes: 6 additions & 2 deletions api_gateway/client/src/app/models/playbook/action.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Type, Expose } from 'class-transformer';
import { Type, Expose, Exclude } from 'class-transformer';

import { Argument } from './argument';
import { GraphPosition } from './graphPosition';
import { ConditionalExpression } from './conditionalExpression';
import { ExecutionElement } from './executionElement';
import { ActionType } from '../api/actionApi';

export class Action extends ExecutionElement {

@Exclude()
action_type: ActionType = ActionType.ACTION;

// _workflow_id: number;
@Expose({ name: 'label' })
name: string;
Expand Down
4 changes: 4 additions & 0 deletions api_gateway/client/src/app/models/playbook/condition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { Type, Expose, Exclude } from 'class-transformer';
import { Argument } from './argument';
import { ExecutionElement } from './executionElement';
import { GraphPosition } from './graphPosition';
import { ActionType } from '../api/actionApi';

export class Condition extends ExecutionElement {

@Exclude()
action_type: ActionType = ActionType.CONDITION;

@Expose({ name: 'label' })
name: string = 'Label';
Expand Down
34 changes: 34 additions & 0 deletions api_gateway/client/src/app/models/playbook/trigger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Type, Expose, Exclude } from 'class-transformer';
import { Argument } from './argument';
import { ExecutionElement } from './executionElement';
import { GraphPosition } from './graphPosition';
import { ActionType } from '../api/actionApi';

export class Trigger extends ExecutionElement {

@Exclude()
action_type: ActionType = ActionType.TRIGGER;

@Expose({ name: 'label' })
name: string = 'Label';

app_name: string = 'Builtin';

app_version: string;

@Expose({ name: 'name' })
action_name: string = 'Trigger';

@Type(() => GraphPosition)
position: GraphPosition;

@Exclude()
@Type(() => Argument)
arguments: Argument[] = [];

trigger_schema: object = {};

get all_errors(): string[] {
return this.errors.concat(...this.arguments.map(argument => argument.all_errors))
}
}
63 changes: 15 additions & 48 deletions api_gateway/client/src/app/models/playbook/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ConditionalExpression } from './conditionalExpression';
import { Argument } from './argument';
import { Condition } from './condition';
import { ActionType } from '../api/actionApi';
import { Trigger } from './trigger';

export class Workflow extends ExecutionElement {
// _playbook_id: number;
Expand Down Expand Up @@ -50,6 +51,12 @@ export class Workflow extends ExecutionElement {
@Type(() => Condition)
conditions?: Condition[] = [];

/**
* Array of triggers between actions.
*/
@Type(() => Trigger)
triggers?: Trigger[] = [];

/**
* Array of environment variables.
*/
Expand All @@ -72,36 +79,20 @@ export class Workflow extends ExecutionElement {
*/
is_valid: boolean;

get nodes(): (Action | Condition)[] {
return [].concat(this.actions, this.conditions);
get nodes(): (Action | Condition | Trigger)[] {
return [].concat(this.actions, this.conditions, this.triggers);
}

/**
* Array of errors returned from the server for this Argument and any of its descendants
*/
get all_errors(): string[] {
return this.errors
.concat(...this.actions.map(action => action.all_errors))
.concat(...this.branches.map(branch => branch.all_errors))
return this.errors.concat(...this.nodes.map(action => action.all_errors))
}

get all_arguments(): Argument[] {
let allArgs: Argument[] = [];
const getExpressionArguments = (expression: ConditionalExpression) => {
expression.conditions.forEach(condition => {
allArgs = allArgs.concat(condition.arguments);
//condition.transforms.forEach(transform => allArgs = allArgs.concat(transform.arguments));
})
expression.child_expressions.forEach(getExpressionArguments);
}

this.actions.forEach(action => {
allArgs = allArgs.concat(action.arguments);
})
this.branches.forEach(branch => {
if (branch.condition) getExpressionArguments(branch.condition);
})

this.nodes.forEach(action => allArgs = allArgs.concat(action.arguments));
return allArgs;
}

Expand All @@ -110,41 +101,17 @@ export class Workflow extends ExecutionElement {
return this.environment_variables.filter(variable => this.all_arguments.some(arg => arg.value == variable.id));
}

listBranchCounters() : Select2OptionData[] {
return this.branches.map(branch => {
const sourceAction = this.findActionById(branch.source_id);
const destAction = this.findActionById(branch.destination_id);
return { id: branch.id, text: `${ (sourceAction || { name: null}).name } > ${ (destAction || { name: null}).name }` }
})
}

findActionById(id: string) : Action {
return this.actions.find(action => action.id == id)
}

deleteVariable(deletedVariable: EnvironmentVariable) {
this.environment_variables = this.environment_variables.filter(variable => variable.id !== deletedVariable.id);
this.all_arguments
.filter(arg => arg.value == deletedVariable.id)
.forEach(arg => arg.value = '');
this.all_arguments.filter(arg => arg.value == deletedVariable.id).forEach(arg => arg.value = '');
}

getNextActionName(actionName: string, actionType: ActionType = ActionType.ACTION) : string {
let numActions;
// switch (actionType) {
// case ActionType.CONDITION:
// numActions = this.conditions.filter(a => a.action_name === actionName && a.name).length;
// break;
// default:
// numActions = this.actions.filter(a => a.action_name === actionName && a.name).length;
// }

numActions = this.nodes.filter(a => a.action_name === actionName && a.name).length;

getNextActionName(actionName: string) : string {
let numActions = this.nodes.filter(a => a.action_name === actionName && a.name).length;
return numActions ? `${actionName}_${ ++numActions }` : actionName;
}

getPreviousActions(action: Action | Condition): (Action | Condition)[] {
getPreviousActions(action: Action | Condition | Trigger): (Action | Condition | Trigger)[] {
return this.branches
.filter(b => b.destination_id == action.id)
.map(b => this.nodes.find(a => a.id == b.source_id))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ export class PlaybookArgumentComponent implements OnChanges {
*/
ngOnChanges(): void {
this.initParameterSchema();
this.initBranchCounterSelect();
this.initTypeSelector();
this.initUserSelect();
this.initRoleSelect();
Expand Down Expand Up @@ -154,10 +153,6 @@ export class PlaybookArgumentComponent implements OnChanges {
}
}

initBranchCounterSelect(): void {
this.branchCounters = this.loadedWorkflow.listBranchCounters();
}

/**
* Event fired on the select2 change for users/roles. Updates the value based on the event value.
* @param $event JS Event Fired
Expand Down
2 changes: 1 addition & 1 deletion api_gateway/client/src/app/playbook/playbook.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ <h4 class="mb-3">Welcome to WALKOFF</h4>
tedious tasks slowing them down.
</p>
<p>
Use the <b>Create New...</b> link above to create your first workflow or
Use the <b>Create New</b> link above to create your first workflow or
visit the <a href="https://nsacyber.github.io/WALKOFF/" target="_blank"><b>website</b></a> for additional
documentation.
</p>
Expand Down
18 changes: 18 additions & 0 deletions api_gateway/client/src/app/playbook/playbook.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,19 @@ export class PlaybookService {
return this.executionService.addWorkflowToQueue(workflowId, executionId);
}

/**
* For a given executing workflow, asyncronously perform some action to change its status.
* Only returns success
* @param executionId Execution ID to act upon
* @param action Action to take (e.g. abort, resume, pause)
*/
performWorkflowTrigger(executionId: string, trigger: string, data = {}): Promise<void> {
return this.http.patch(`api/workflowqueue/${ executionId }`, { status: 'trigger', trigger_id: trigger, trigger_data: data})
.toPromise()
.then(() => null)
.catch(this.utils.handleResponseError);
}

/**
* Returns an array of all globals within the DB.
*/
Expand Down Expand Up @@ -263,6 +276,11 @@ export class PlaybookService {
id_: '7a1c6838-1b14-4ddc-7d84-935fcbc260ca',
name: 'Condition',
node_type: ActionType.CONDITION,
},
{
id_: '21f7c721-448f-da7b-fea9-9b781824e7d3',
name: 'Trigger',
node_type: ActionType.TRIGGER,
}
]
}].concat(data);
Expand Down
Loading

0 comments on commit e705358

Please sign in to comment.