@contrail/cli 1.0.22 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/apps/deploy-app/actions-deployer.d.ts +1 -1
- package/lib/apps/deploy-app/app-deployer.d.ts +2 -2
- package/lib/apps/deploy-app/app-deployer.js +2 -8
- package/lib/apps/deploy-app/app-template-parsers.d.ts +1 -1
- package/lib/apps/deploy-app/deploy.js +1 -2
- package/lib/apps/deploy-app/workflow-definition-deployer.d.ts +2 -2
- package/lib/apps/deploy-app/workflow-definition-deployer.js +19 -15
- package/lib/cli.js +34 -9
- package/lib/colors/color-loader.js +3 -1
- package/lib/interfaces.d.ts +122 -0
- package/lib/interfaces.js +4 -0
- package/lib/workflows/workflow-template-deployer.d.ts +14 -0
- package/lib/workflows/workflow-template-deployer.js +129 -0
- package/lib/workflows/workflowCommands.d.ts +3 -0
- package/lib/workflows/workflowCommands.js +46 -0
- package/package.json +1 -1
- package/src/apps/deploy-app/actions-deployer.ts +1 -1
- package/src/apps/deploy-app/app-deployer.ts +3 -8
- package/src/apps/deploy-app/app-template-parsers.ts +1 -1
- package/src/apps/deploy-app/deploy.ts +2 -3
- package/src/apps/deploy-app/workflow-definition-deployer.ts +21 -18
- package/src/cli.ts +33 -9
- package/src/colors/color-loader.ts +3 -1
- package/src/{apps/deploy-app/interfaces.ts → interfaces.ts} +12 -6
- package/src/workflows/workflow-template-deployer.ts +159 -0
- package/src/workflows/workflowCommands.ts +54 -0
- package/src/apps/deploy-app/workflow-deployer.ts +0 -111
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { App, AppDeclaration, AppActionDeclaration } from '
|
|
1
|
+
import { App, AppDeclaration, AppActionDeclaration } from '../../interfaces';
|
|
2
2
|
export declare function getActionsForApp(app: App): Promise<any>;
|
|
3
3
|
export declare function getActionDeclarationIdentifier(actionKey: any, app: App): string;
|
|
4
4
|
export declare class ActionsDeployer {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { App, AppDeclaration } from '
|
|
1
|
+
import { App, AppDeclaration } from '../../interfaces';
|
|
2
2
|
export declare class AppDeployer {
|
|
3
|
-
deploy(appDeclaration: AppDeclaration
|
|
3
|
+
deploy(appDeclaration: AppDeclaration): Promise<void>;
|
|
4
4
|
getExistingApp(appDeclaration: AppDeclaration): Promise<App>;
|
|
5
5
|
private createNewApp;
|
|
6
6
|
updateExistingApp(appDeclaration: AppDeclaration, existingApp: any): Promise<any>;
|
|
@@ -4,9 +4,8 @@ import { Auth } from '../../auth/auth';
|
|
|
4
4
|
import { ActionsDeployer } from './actions-deployer';
|
|
5
5
|
import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
|
|
6
6
|
import { WorkflowDefinitionDeployer } from './workflow-definition-deployer';
|
|
7
|
-
import { WorkflowDeployer } from './workflow-deployer';
|
|
8
7
|
export class AppDeployer {
|
|
9
|
-
async deploy(appDeclaration
|
|
8
|
+
async deploy(appDeclaration) {
|
|
10
9
|
let app = await this.getExistingApp(appDeclaration);
|
|
11
10
|
if (!app) {
|
|
12
11
|
console.log(`%s Creating new app.`, chalk.yellow.bold('APP'));
|
|
@@ -17,12 +16,7 @@ export class AppDeployer {
|
|
|
17
16
|
app = await this.updateExistingApp(appDeclaration, app);
|
|
18
17
|
}
|
|
19
18
|
await new ActionsDeployer().deployActions(appDeclaration, app);
|
|
20
|
-
|
|
21
|
-
await new WorkflowDeployer().deployWorkflows(appDeclaration, app);
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
await new WorkflowDefinitionDeployer().deployWorkflowDefinitions(appDeclaration, app);
|
|
25
|
-
}
|
|
19
|
+
await new WorkflowDefinitionDeployer().deployWorkflowDefinitions(appDeclaration, app);
|
|
26
20
|
}
|
|
27
21
|
async getExistingApp(appDeclaration) {
|
|
28
22
|
const orgId = Auth.config.orgId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppDeclaration, TriggerKeyDefinition, ConfigPropertyElements } from '
|
|
1
|
+
import { AppDeclaration, TriggerKeyDefinition, ConfigPropertyElements } from '../../interfaces';
|
|
2
2
|
export declare class TriggerKeyDefinitionParser {
|
|
3
3
|
static buildTriggersArray(appDeclaration: AppDeclaration): Array<TriggerKeyDefinition>;
|
|
4
4
|
}
|
|
@@ -26,10 +26,9 @@ export async function deployApp(args) {
|
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
console.log(`%s Deploying Application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
|
|
29
|
-
const templateOnly = args && args.includes('--template-only');
|
|
30
29
|
try {
|
|
31
30
|
await authUser();
|
|
32
|
-
await new AppDeployer().deploy(appDeclaration
|
|
31
|
+
await new AppDeployer().deploy(appDeclaration);
|
|
33
32
|
}
|
|
34
33
|
catch (e) {
|
|
35
34
|
console.log(`%s Application Deployment Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { App, AppDeclaration,
|
|
1
|
+
import { App, AppDeclaration, WorkflowDefinition } from '../../interfaces';
|
|
2
2
|
export declare class WorkflowDefinitionDeployer {
|
|
3
3
|
deployWorkflowDefinitions(appDeclaration: AppDeclaration, app: App): Promise<void>;
|
|
4
4
|
getWorkflowDefinitionsForApp(app: App): Promise<any>;
|
|
5
|
-
deployWorkflow(workflowKey: string, workflow:
|
|
5
|
+
deployWorkflow(workflowKey: string, workflow: WorkflowDefinition, app: App, existingWorkflows: Array<any>): Promise<any>;
|
|
6
6
|
private createNewWorkflowDefinition;
|
|
7
7
|
private populateActionIds;
|
|
8
8
|
private updateWorkflowDefinition;
|
|
@@ -8,7 +8,7 @@ export class WorkflowDefinitionDeployer {
|
|
|
8
8
|
// UPSERT / DELETE BASED ON WORKFLOW IDENTIFIER
|
|
9
9
|
console.log('%s \tDeploying workflow definitions.', chalk.yellow.bold('WORKFLOW DEFINITION'));
|
|
10
10
|
for (const workflowKey of Object.keys(appDeclaration.workflows)) {
|
|
11
|
-
await this.deployWorkflow(workflowKey, appDeclaration.workflows[workflowKey], app, existingWorkflows
|
|
11
|
+
await this.deployWorkflow(workflowKey, appDeclaration.workflows[workflowKey], app, existingWorkflows);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
async getWorkflowDefinitionsForApp(app) {
|
|
@@ -17,17 +17,17 @@ export class WorkflowDefinitionDeployer {
|
|
|
17
17
|
criteria: { ownerKey: `app:${app.id}` },
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
-
async deployWorkflow(workflowKey, workflow, app, existingWorkflows
|
|
20
|
+
async deployWorkflow(workflowKey, workflow, app, existingWorkflows) {
|
|
21
21
|
console.log(`%s \tDeploying workflow definitions: ${workflowKey}`, chalk.yellow.bold('WORKFLOW DEFINITION'));
|
|
22
22
|
const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
|
|
23
23
|
const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
24
24
|
if (existingDefinition) {
|
|
25
|
-
return await this.updateWorkflowDefinition(existingDefinition, workflow, app
|
|
25
|
+
return await this.updateWorkflowDefinition(existingDefinition, workflow, app);
|
|
26
26
|
}
|
|
27
|
-
return await this.createNewWorkflowDefinition(workflowKey, workflow, app
|
|
27
|
+
return await this.createNewWorkflowDefinition(workflowKey, workflow, app);
|
|
28
28
|
}
|
|
29
|
-
async createNewWorkflowDefinition(workflowKey, workflowDeclaration, app
|
|
30
|
-
await this.populateActionIds(workflowDeclaration,
|
|
29
|
+
async createNewWorkflowDefinition(workflowKey, workflowDeclaration, app) {
|
|
30
|
+
await this.populateActionIds(workflowDeclaration, app);
|
|
31
31
|
const newObject = {
|
|
32
32
|
identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
|
|
33
33
|
name: workflowDeclaration.name,
|
|
@@ -36,6 +36,8 @@ export class WorkflowDefinitionDeployer {
|
|
|
36
36
|
workflowDefinition: workflowDeclaration.workflowDefinition,
|
|
37
37
|
public: workflowDeclaration.public,
|
|
38
38
|
isActive: workflowDeclaration.isActive,
|
|
39
|
+
messageGroupId: workflowDeclaration.messageGroupId,
|
|
40
|
+
parallelWorkerCount: workflowDeclaration.parallelWorkerCount,
|
|
39
41
|
};
|
|
40
42
|
const workflowTemplate = await new Entities().create({
|
|
41
43
|
entityName: 'event-workflow-template-definition',
|
|
@@ -44,13 +46,13 @@ export class WorkflowDefinitionDeployer {
|
|
|
44
46
|
console.log(`%s Created new workflow definition definitions: ${workflowKey}`, chalk.yellow.bold('WORKFLOW DEFINITION'));
|
|
45
47
|
return workflowTemplate;
|
|
46
48
|
}
|
|
47
|
-
async populateActionIds(
|
|
49
|
+
async populateActionIds(workflowDefinition, app) {
|
|
48
50
|
var _a;
|
|
49
51
|
let availableAppActions = await getActionsForApp(app);
|
|
50
|
-
if (!((_a =
|
|
52
|
+
if (!((_a = workflowDefinition.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
|
-
for (const path of
|
|
55
|
+
for (const path of workflowDefinition.workflowDefinition.paths) {
|
|
54
56
|
if (!(path === null || path === void 0 ? void 0 : path.actionDefinitionConfigs)) {
|
|
55
57
|
continue;
|
|
56
58
|
}
|
|
@@ -58,18 +60,20 @@ export class WorkflowDefinitionDeployer {
|
|
|
58
60
|
const actionKey = actionConfiguration.action;
|
|
59
61
|
const action = availableAppActions.find(action => action.identifier === getActionDeclarationIdentifier(actionKey, app));
|
|
60
62
|
if (!action) {
|
|
61
|
-
throw new Error(`Could not find action ${actionKey} declared in workflow definition ${
|
|
63
|
+
throw new Error(`Could not find action ${actionKey} declared in workflow definition ${workflowDefinition.name}`);
|
|
62
64
|
}
|
|
63
65
|
actionConfiguration.id = action.id;
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
|
-
async updateWorkflowDefinition(existingWorkflowDefinition,
|
|
68
|
-
await this.populateActionIds(
|
|
69
|
+
async updateWorkflowDefinition(existingWorkflowDefinition, workflowDefinition, app) {
|
|
70
|
+
await this.populateActionIds(workflowDefinition, app);
|
|
69
71
|
const updates = Object.assign(new Object(), {
|
|
70
|
-
name:
|
|
71
|
-
triggerKey:
|
|
72
|
-
workflowDefinition:
|
|
72
|
+
name: workflowDefinition.name,
|
|
73
|
+
triggerKey: workflowDefinition.triggerKey,
|
|
74
|
+
workflowDefinition: workflowDefinition.workflowDefinition,
|
|
75
|
+
messageGroupId: workflowDefinition.messageGroupId,
|
|
76
|
+
parallelWorkerCount: workflowDefinition.parallelWorkerCount,
|
|
73
77
|
});
|
|
74
78
|
const updatedWorkflowDefinition = await new Entities().update({
|
|
75
79
|
entityName: 'event-workflow-template-definition',
|
package/lib/cli.js
CHANGED
|
@@ -7,8 +7,9 @@ import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
|
7
7
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
8
8
|
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
9
9
|
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
10
|
-
import { loadColors } from './colors/color-loader';
|
|
10
|
+
import { loadColors, deleteColors } from './colors/color-loader';
|
|
11
11
|
import { listConfig, removeConfig } from './config/configCommands';
|
|
12
|
+
import { deleteWorkflowTemplate, deployWorkflowTemplate, listWorkflowTemplate } from './workflows/workflowCommands';
|
|
12
13
|
const cliUsage = require('command-line-usage');
|
|
13
14
|
/**
|
|
14
15
|
* Built using documentation here:
|
|
@@ -100,10 +101,30 @@ export async function cli(args) {
|
|
|
100
101
|
await loadColors();
|
|
101
102
|
break;
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
case 'delete': {
|
|
105
|
+
await deleteColors();
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
default: {
|
|
109
|
+
printIllegalCommand();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case 'workflow-templates': {
|
|
115
|
+
switch (command) {
|
|
116
|
+
case 'load': {
|
|
117
|
+
await deployWorkflowTemplate();
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'delete': {
|
|
121
|
+
await deleteWorkflowTemplate();
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case 'list': {
|
|
125
|
+
await listWorkflowTemplate();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
107
128
|
default: {
|
|
108
129
|
printIllegalCommand();
|
|
109
130
|
}
|
|
@@ -120,10 +141,6 @@ export async function cli(args) {
|
|
|
120
141
|
await removeConfig(args);
|
|
121
142
|
break;
|
|
122
143
|
}
|
|
123
|
-
// case 'delete': {
|
|
124
|
-
// await deleteColors();
|
|
125
|
-
// break;
|
|
126
|
-
// }
|
|
127
144
|
default: {
|
|
128
145
|
printIllegalCommand();
|
|
129
146
|
}
|
|
@@ -185,6 +202,14 @@ const helpSections = [
|
|
|
185
202
|
'. green, blue) are required.',
|
|
186
203
|
],
|
|
187
204
|
},
|
|
205
|
+
{
|
|
206
|
+
header: 'Workflow Template Commands - Domain: workflow-templates',
|
|
207
|
+
content: [
|
|
208
|
+
'deploy Deploy your workflow. Assumes a workflow.yml file.',
|
|
209
|
+
'delete Removes the workflows in the workflow.yml file.',
|
|
210
|
+
'list Lists the workflow templates in the org',
|
|
211
|
+
],
|
|
212
|
+
},
|
|
188
213
|
{
|
|
189
214
|
header: 'Type Commands - Domain: types',
|
|
190
215
|
content: [
|
|
@@ -47,7 +47,9 @@ async function getLocalColors() {
|
|
|
47
47
|
async function getExistingColors() {
|
|
48
48
|
console.log(`%s Getting Existing Colors`, chalk.yellow.bold('COLORS'));
|
|
49
49
|
try {
|
|
50
|
-
|
|
50
|
+
const result = await new Entities().get({ entityName: 'color', take: 3000 }); //, useSearch: false }); Not in EntitiesClientGetOptions yet
|
|
51
|
+
console.log("Found %s existing colors", result.length);
|
|
52
|
+
return result;
|
|
51
53
|
}
|
|
52
54
|
catch (e) {
|
|
53
55
|
throw new Error(`ERROR DOWNLOADING COLORS: ${e}`);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** Describes the derivative JSON / object represented
|
|
2
|
+
* in app.yml file.
|
|
3
|
+
*/
|
|
4
|
+
export interface AppDeclaration {
|
|
5
|
+
appIdentifier: string;
|
|
6
|
+
appName: string;
|
|
7
|
+
appDescription?: string;
|
|
8
|
+
visibility: 'private' | 'public';
|
|
9
|
+
publisher: string;
|
|
10
|
+
version: string;
|
|
11
|
+
eventWorkflowTriggerKeyMapping: string;
|
|
12
|
+
thumbnail?: string;
|
|
13
|
+
keywords?: Array<string>;
|
|
14
|
+
actions?: {
|
|
15
|
+
[key: string]: AppActionDeclaration;
|
|
16
|
+
};
|
|
17
|
+
appConfiguration: ConfigPropertyElements;
|
|
18
|
+
triggers: {
|
|
19
|
+
[key: string]: AppTriggerDeclaration;
|
|
20
|
+
};
|
|
21
|
+
workflows?: {
|
|
22
|
+
[key: string]: WorkflowDefinition | WorkflowTemplateDeclaration;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface ConfigPropertyElements {
|
|
26
|
+
[key: string]: ConfigPropertyElement;
|
|
27
|
+
}
|
|
28
|
+
export interface ConfigPropertyElement {
|
|
29
|
+
propertyType: string;
|
|
30
|
+
options?: any[];
|
|
31
|
+
label: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AppActionDeclaration {
|
|
34
|
+
handler: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
actionConfiguration?: ConfigPropertyElements;
|
|
38
|
+
}
|
|
39
|
+
export interface AppTriggerDeclaration {
|
|
40
|
+
key: string;
|
|
41
|
+
name: string;
|
|
42
|
+
external?: boolean;
|
|
43
|
+
description?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface WorkflowDefinition {
|
|
46
|
+
id?: string;
|
|
47
|
+
identifier: string;
|
|
48
|
+
name: string;
|
|
49
|
+
triggerKey: string;
|
|
50
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
51
|
+
ownerKey: string;
|
|
52
|
+
isActive: boolean;
|
|
53
|
+
public: boolean;
|
|
54
|
+
supportingAppId?: string;
|
|
55
|
+
messageGroupId?: string;
|
|
56
|
+
parallelWorkerCount?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface WorkflowTemplateDeclaration {
|
|
59
|
+
workflows?: {
|
|
60
|
+
[key: string]: WorkflowTemplate;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface WorkflowTemplate {
|
|
64
|
+
id?: string;
|
|
65
|
+
identifier: string;
|
|
66
|
+
name: string;
|
|
67
|
+
triggerKey: string;
|
|
68
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
69
|
+
isActive: boolean;
|
|
70
|
+
ownerKey?: string;
|
|
71
|
+
supportingAppId?: string;
|
|
72
|
+
messageGroupId?: string;
|
|
73
|
+
parallelWorkerCount?: number;
|
|
74
|
+
}
|
|
75
|
+
export interface WorkflowDefinitionPaths {
|
|
76
|
+
paths: WorkflowConditional[];
|
|
77
|
+
}
|
|
78
|
+
export interface WorkflowConditional {
|
|
79
|
+
conditional: string;
|
|
80
|
+
actionDefinitionConfigs: ActionDefinitionConfig[];
|
|
81
|
+
}
|
|
82
|
+
export interface ActionDefinitionConfig {
|
|
83
|
+
name: string;
|
|
84
|
+
action: string;
|
|
85
|
+
config?: {
|
|
86
|
+
[key: string]: any;
|
|
87
|
+
};
|
|
88
|
+
id?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface App {
|
|
91
|
+
id: string;
|
|
92
|
+
identifier: string;
|
|
93
|
+
name: string;
|
|
94
|
+
public: boolean;
|
|
95
|
+
description?: string;
|
|
96
|
+
publisher: string;
|
|
97
|
+
thumbnail: string;
|
|
98
|
+
eventWorkflowTriggerKeyMapping: string;
|
|
99
|
+
configProperties?: ConfigProperty[];
|
|
100
|
+
triggerKeyDefinitions?: TriggerKeyDefinition[];
|
|
101
|
+
}
|
|
102
|
+
export declare class ConfigProperty {
|
|
103
|
+
slug: string;
|
|
104
|
+
propertyType: string;
|
|
105
|
+
options?: any[];
|
|
106
|
+
label: string;
|
|
107
|
+
}
|
|
108
|
+
export interface EventWorkflowActionDefinition {
|
|
109
|
+
id?: string;
|
|
110
|
+
identifier?: string;
|
|
111
|
+
name?: string;
|
|
112
|
+
executeFunctionString?: string;
|
|
113
|
+
ownerKey?: string;
|
|
114
|
+
public?: boolean;
|
|
115
|
+
configProperties?: ConfigProperty[];
|
|
116
|
+
}
|
|
117
|
+
export declare class TriggerKeyDefinition {
|
|
118
|
+
name: string;
|
|
119
|
+
description?: string;
|
|
120
|
+
triggerKey: string;
|
|
121
|
+
external?: boolean;
|
|
122
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WorkflowTemplate, WorkflowTemplateDeclaration } from '../interfaces';
|
|
2
|
+
export declare class WorkflowTemplateDeployer {
|
|
3
|
+
deployWorkflows(wtDeclaration: WorkflowTemplateDeclaration): Promise<void>;
|
|
4
|
+
getExistingWorkflowTemplates(): Promise<any>;
|
|
5
|
+
deployWorkflowTemplate(workflowKey: string, workflow: WorkflowTemplate, existingWorkflows: Array<any>): Promise<any>;
|
|
6
|
+
private createNewWorkflowTemplate;
|
|
7
|
+
private populateActionIds;
|
|
8
|
+
private updateWorkflowTemplate;
|
|
9
|
+
deleteWorkflowTemplates(wtDeclaration: WorkflowTemplateDeclaration): Promise<void>;
|
|
10
|
+
private deleteWorkflowTemplate;
|
|
11
|
+
listExistingWorkflowTemplates(): Promise<any>;
|
|
12
|
+
}
|
|
13
|
+
export declare function getWorkflowTemplateIdentifier(workflowKey: string): string;
|
|
14
|
+
export declare function getActionByIdentifier(identifier: string): Promise<any>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export class WorkflowTemplateDeployer {
|
|
4
|
+
async deployWorkflows(wtDeclaration) {
|
|
5
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
6
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
7
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
8
|
+
console.log('%s \tDeploying workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
9
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
10
|
+
await this.deployWorkflowTemplate(workflowKey, wtDeclaration.workflows[workflowKey], existingWorkflows);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async getExistingWorkflowTemplates() {
|
|
14
|
+
return await new Entities().get({
|
|
15
|
+
entityName: 'event-workflow-template'
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async deployWorkflowTemplate(workflowKey, workflow, existingWorkflows) {
|
|
19
|
+
console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
20
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
21
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
22
|
+
if (existingTemplate) {
|
|
23
|
+
return await this.updateWorkflowTemplate(workflowKey, existingTemplate, workflow);
|
|
24
|
+
}
|
|
25
|
+
return await this.createNewWorkflowTemplate(workflowKey, workflow);
|
|
26
|
+
}
|
|
27
|
+
async createNewWorkflowTemplate(workflowKey, workflowTemplate) {
|
|
28
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
29
|
+
const newObject = {
|
|
30
|
+
identifier: getWorkflowTemplateIdentifier(workflowKey),
|
|
31
|
+
name: workflowTemplate.name,
|
|
32
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
33
|
+
workflowDefinition: workflowTemplate.workflowDefinition,
|
|
34
|
+
isActive: workflowTemplate.isActive,
|
|
35
|
+
supportingAppId: workflowTemplate.supportingAppId,
|
|
36
|
+
messageGroupId: workflowTemplate.messageGroupId,
|
|
37
|
+
parallelWorkerCount: workflowTemplate.parallelWorkerCount,
|
|
38
|
+
};
|
|
39
|
+
const newWorkflowTemplate = await new Entities().create({
|
|
40
|
+
entityName: 'event-workflow-template',
|
|
41
|
+
object: newObject,
|
|
42
|
+
});
|
|
43
|
+
console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
44
|
+
return newWorkflowTemplate;
|
|
45
|
+
}
|
|
46
|
+
async populateActionIds(workflowTemplate, workflowKey) {
|
|
47
|
+
var _a;
|
|
48
|
+
if (!((_a = workflowTemplate === null || workflowTemplate === void 0 ? void 0 : workflowTemplate.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for (const path of workflowTemplate.workflowDefinition.paths) {
|
|
52
|
+
if (!(path === null || path === void 0 ? void 0 : path.actionDefinitionConfigs)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
for (const actionConfiguration of path.actionDefinitionConfigs) {
|
|
56
|
+
const actionKey = actionConfiguration.action;
|
|
57
|
+
try {
|
|
58
|
+
const actionEntity = await getActionByIdentifier(actionKey);
|
|
59
|
+
console.log("response for action find:", actionEntity);
|
|
60
|
+
actionConfiguration.id = actionEntity.id;
|
|
61
|
+
console.log("found action id:", actionEntity.id);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
console.log(e);
|
|
65
|
+
}
|
|
66
|
+
if (!actionConfiguration.id) {
|
|
67
|
+
throw new Error(`Could not find action ${actionKey} declared in ${workflowKey}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async updateWorkflowTemplate(workflowKey, existingWorkflowTemplate, workflowTemplate) {
|
|
73
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
74
|
+
const updates = Object.assign(new Object(), {
|
|
75
|
+
name: workflowTemplate.name,
|
|
76
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
77
|
+
workflowDefinition: workflowTemplate.workflowDefinition
|
|
78
|
+
});
|
|
79
|
+
const updatedWorkflowTemplate = await new Entities().update({
|
|
80
|
+
entityName: 'event-workflow-template',
|
|
81
|
+
id: existingWorkflowTemplate.id,
|
|
82
|
+
object: updates,
|
|
83
|
+
});
|
|
84
|
+
console.log(`%s Updated existing workflow template: ${updatedWorkflowTemplate.identifier}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
85
|
+
return updatedWorkflowTemplate;
|
|
86
|
+
}
|
|
87
|
+
async deleteWorkflowTemplates(wtDeclaration) {
|
|
88
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
89
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
90
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
91
|
+
console.log('%s \tDELETING workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
92
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
93
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
94
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
95
|
+
if (existingTemplate) {
|
|
96
|
+
try {
|
|
97
|
+
await this.deleteWorkflowTemplate(identifier);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
console.log('%s \tFAILED to delete workflow template %s.', chalk.red.bold('WORKFLOW TEMPLATES'), identifier);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.log('%s \tUnable to locate workflow template %s.', chalk.yellow.bold('WORKFLOW TEMPLATES'), identifier);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async deleteWorkflowTemplate(identifier) {
|
|
109
|
+
return await new Entities().delete({
|
|
110
|
+
entityName: 'event-workflow-template',
|
|
111
|
+
id: identifier,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
async listExistingWorkflowTemplates() {
|
|
115
|
+
const templates = await this.getExistingWorkflowTemplates();
|
|
116
|
+
console.log(templates);
|
|
117
|
+
return templates;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function getWorkflowTemplateIdentifier(workflowKey) {
|
|
121
|
+
return workflowKey;
|
|
122
|
+
}
|
|
123
|
+
export async function getActionByIdentifier(identifier) {
|
|
124
|
+
const result = await new Entities().get({
|
|
125
|
+
entityName: 'event-workflow-action-definition',
|
|
126
|
+
criteria: { identifier },
|
|
127
|
+
});
|
|
128
|
+
return result.length > 0 ? result[0] : {};
|
|
129
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { authUser } from '../auth/login';
|
|
4
|
+
import { getSeparatorByPlatform } from '../common';
|
|
5
|
+
const yaml = require('js-yaml');
|
|
6
|
+
import { WorkflowTemplateDeployer } from './workflow-template-deployer';
|
|
7
|
+
export async function deleteWorkflowTemplate() {
|
|
8
|
+
let wtDeclaration;
|
|
9
|
+
try {
|
|
10
|
+
wtDeclaration = loadTemplateConfig();
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
console.log(`%s Workflow Deletion Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
await authUser();
|
|
17
|
+
await new WorkflowTemplateDeployer().deleteWorkflowTemplates(wtDeclaration);
|
|
18
|
+
}
|
|
19
|
+
export async function deployWorkflowTemplate() {
|
|
20
|
+
let wtDeclaration;
|
|
21
|
+
try {
|
|
22
|
+
wtDeclaration = loadTemplateConfig();
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
console.log(`%s Workflow Deletion Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await authUser();
|
|
29
|
+
await new WorkflowTemplateDeployer().deployWorkflows(wtDeclaration);
|
|
30
|
+
}
|
|
31
|
+
export async function listWorkflowTemplate() {
|
|
32
|
+
await authUser();
|
|
33
|
+
return await new WorkflowTemplateDeployer().listExistingWorkflowTemplates();
|
|
34
|
+
}
|
|
35
|
+
function loadTemplateConfig() {
|
|
36
|
+
const TARGET_DIR = process.cwd();
|
|
37
|
+
try {
|
|
38
|
+
const separator = getSeparatorByPlatform();
|
|
39
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + 'workflow.yml', 'utf8'));
|
|
40
|
+
console.log(doc);
|
|
41
|
+
return doc;
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Entities } from '@contrail/sdk';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { App, AppDeclaration, AppActionDeclaration, EventWorkflowActionDefinition } from '
|
|
3
|
+
import { App, AppDeclaration, AppActionDeclaration, EventWorkflowActionDefinition } from '../../interfaces';
|
|
4
4
|
import { ConfigPropertiesParser } from './app-template-parsers';
|
|
5
5
|
import { getSeparatorByPlatform } from '../../common';
|
|
6
6
|
|
|
@@ -2,13 +2,12 @@ import { Entities } from '@contrail/sdk';
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { Auth } from '../../auth/auth';
|
|
4
4
|
import { ActionsDeployer } from './actions-deployer';
|
|
5
|
-
import { App, AppDeclaration } from '
|
|
5
|
+
import { App, AppDeclaration } from '../../interfaces';
|
|
6
6
|
import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
|
|
7
7
|
import { WorkflowDefinitionDeployer } from './workflow-definition-deployer';
|
|
8
|
-
import { WorkflowDeployer } from './workflow-deployer';
|
|
9
8
|
|
|
10
9
|
export class AppDeployer {
|
|
11
|
-
public async deploy(appDeclaration: AppDeclaration
|
|
10
|
+
public async deploy(appDeclaration: AppDeclaration) {
|
|
12
11
|
let app = await this.getExistingApp(appDeclaration);
|
|
13
12
|
if (!app) {
|
|
14
13
|
console.log(`%s Creating new app.`, chalk.yellow.bold('APP'));
|
|
@@ -18,11 +17,7 @@ export class AppDeployer {
|
|
|
18
17
|
app = await this.updateExistingApp(appDeclaration, app);
|
|
19
18
|
}
|
|
20
19
|
await new ActionsDeployer().deployActions(appDeclaration, app);
|
|
21
|
-
|
|
22
|
-
await new WorkflowDeployer().deployWorkflows(appDeclaration, app);
|
|
23
|
-
} else {
|
|
24
|
-
await new WorkflowDefinitionDeployer().deployWorkflowDefinitions(appDeclaration, app);
|
|
25
|
-
}
|
|
20
|
+
await new WorkflowDefinitionDeployer().deployWorkflowDefinitions(appDeclaration, app);
|
|
26
21
|
}
|
|
27
22
|
|
|
28
23
|
public async getExistingApp(appDeclaration: AppDeclaration): Promise<App> {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppDeclaration, TriggerKeyDefinition, ConfigPropertyElements } from '
|
|
1
|
+
import { AppDeclaration, TriggerKeyDefinition, ConfigPropertyElements } from '../../interfaces';
|
|
2
2
|
|
|
3
3
|
export class TriggerKeyDefinitionParser {
|
|
4
4
|
public static buildTriggersArray(appDeclaration: AppDeclaration): Array<TriggerKeyDefinition> {
|
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import { authUser } from '../../auth/login';
|
|
4
4
|
import { AppDeployer } from './app-deployer';
|
|
5
|
-
import { AppDeclaration } from '
|
|
5
|
+
import { AppDeclaration } from '../../interfaces';
|
|
6
6
|
import { getSeparatorByPlatform } from '../../common';
|
|
7
7
|
const yaml = require('js-yaml');
|
|
8
8
|
|
|
@@ -29,10 +29,9 @@ export async function deployApp(args) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
console.log(`%s Deploying Application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
|
|
32
|
-
const templateOnly = args && args.includes('--template-only')
|
|
33
32
|
try {
|
|
34
33
|
await authUser();
|
|
35
|
-
await new AppDeployer().deploy(appDeclaration
|
|
34
|
+
await new AppDeployer().deploy(appDeclaration);
|
|
36
35
|
}
|
|
37
36
|
catch (e) {
|
|
38
37
|
console.log(`%s Application Deployment Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Entities } from '@contrail/sdk';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { App, AppDeclaration,
|
|
3
|
+
import { App, AppDeclaration, WorkflowDefinition } from '../../interfaces';
|
|
4
4
|
import { getActionDeclarationIdentifier, getActionsForApp } from './actions-deployer'
|
|
5
5
|
|
|
6
6
|
export class WorkflowDefinitionDeployer {
|
|
@@ -14,10 +14,9 @@ export class WorkflowDefinitionDeployer {
|
|
|
14
14
|
|
|
15
15
|
for (const workflowKey of Object.keys(appDeclaration.workflows)) {
|
|
16
16
|
await this.deployWorkflow(
|
|
17
|
-
workflowKey, appDeclaration.workflows[workflowKey] as
|
|
17
|
+
workflowKey, appDeclaration.workflows[workflowKey] as WorkflowDefinition,
|
|
18
18
|
app,
|
|
19
19
|
existingWorkflows,
|
|
20
|
-
appDeclaration
|
|
21
20
|
);
|
|
22
21
|
}
|
|
23
22
|
}
|
|
@@ -29,21 +28,21 @@ export class WorkflowDefinitionDeployer {
|
|
|
29
28
|
});
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
async deployWorkflow(workflowKey: string, workflow:
|
|
31
|
+
async deployWorkflow(workflowKey: string, workflow: WorkflowDefinition, app: App, existingWorkflows: Array<any>) {
|
|
33
32
|
console.log(`%s \tDeploying workflow definitions: ${workflowKey}`, chalk.yellow.bold('WORKFLOW DEFINITION'));
|
|
34
33
|
|
|
35
34
|
const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
|
|
36
35
|
const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
37
36
|
|
|
38
37
|
if (existingDefinition) {
|
|
39
|
-
return await this.updateWorkflowDefinition(existingDefinition, workflow, app
|
|
38
|
+
return await this.updateWorkflowDefinition(existingDefinition, workflow, app);
|
|
40
39
|
}
|
|
41
|
-
return await this.createNewWorkflowDefinition(workflowKey, workflow, app
|
|
40
|
+
return await this.createNewWorkflowDefinition(workflowKey, workflow, app);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
private async createNewWorkflowDefinition(workflowKey: string, workflowDeclaration:
|
|
45
|
-
await this.populateActionIds(workflowDeclaration,
|
|
46
|
-
const newObject:
|
|
43
|
+
private async createNewWorkflowDefinition(workflowKey: string, workflowDeclaration: WorkflowDefinition, app: App) {
|
|
44
|
+
await this.populateActionIds(workflowDeclaration, app);
|
|
45
|
+
const newObject: WorkflowDefinition = {
|
|
47
46
|
identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
|
|
48
47
|
name: workflowDeclaration.name,
|
|
49
48
|
ownerKey: `app:${app.id}`,
|
|
@@ -51,6 +50,8 @@ export class WorkflowDefinitionDeployer {
|
|
|
51
50
|
workflowDefinition: workflowDeclaration.workflowDefinition,
|
|
52
51
|
public: workflowDeclaration.public,
|
|
53
52
|
isActive: workflowDeclaration.isActive,
|
|
53
|
+
messageGroupId: workflowDeclaration.messageGroupId,
|
|
54
|
+
parallelWorkerCount: workflowDeclaration.parallelWorkerCount,
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
const workflowTemplate = await new Entities().create({
|
|
@@ -63,12 +64,12 @@ export class WorkflowDefinitionDeployer {
|
|
|
63
64
|
return workflowTemplate;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
private async populateActionIds(
|
|
67
|
+
private async populateActionIds(workflowDefinition: WorkflowDefinition, app: App) {
|
|
67
68
|
let availableAppActions = await getActionsForApp(app);
|
|
68
|
-
if (!
|
|
69
|
+
if (!workflowDefinition.workflowDefinition?.paths) {
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
|
-
for (const path of
|
|
72
|
+
for (const path of workflowDefinition.workflowDefinition.paths) {
|
|
72
73
|
if (!path?.actionDefinitionConfigs) {
|
|
73
74
|
continue;
|
|
74
75
|
}
|
|
@@ -78,19 +79,21 @@ export class WorkflowDefinitionDeployer {
|
|
|
78
79
|
action => action.identifier === getActionDeclarationIdentifier(actionKey, app)
|
|
79
80
|
)
|
|
80
81
|
if (!action) {
|
|
81
|
-
throw new Error(`Could not find action ${actionKey} declared in workflow definition ${
|
|
82
|
+
throw new Error(`Could not find action ${actionKey} declared in workflow definition ${workflowDefinition.name}`);
|
|
82
83
|
}
|
|
83
84
|
actionConfiguration.id = action.id;
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
private async updateWorkflowDefinition(existingWorkflowDefinition:
|
|
89
|
-
await this.populateActionIds(
|
|
89
|
+
private async updateWorkflowDefinition(existingWorkflowDefinition: WorkflowDefinition, workflowDefinition: WorkflowDefinition, app: App) {
|
|
90
|
+
await this.populateActionIds(workflowDefinition, app);
|
|
90
91
|
const updates = Object.assign(new Object(), {
|
|
91
|
-
name:
|
|
92
|
-
triggerKey:
|
|
93
|
-
workflowDefinition:
|
|
92
|
+
name: workflowDefinition.name,
|
|
93
|
+
triggerKey: workflowDefinition.triggerKey,
|
|
94
|
+
workflowDefinition: workflowDefinition.workflowDefinition,
|
|
95
|
+
messageGroupId: workflowDefinition.messageGroupId,
|
|
96
|
+
parallelWorkerCount: workflowDefinition.parallelWorkerCount,
|
|
94
97
|
});
|
|
95
98
|
|
|
96
99
|
const updatedWorkflowDefinition = await new Entities().update({
|
package/src/cli.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { MergeTypeProperties } from './types/types-properties-merger';
|
|
|
10
10
|
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
11
11
|
import { loadColors, deleteColors } from './colors/color-loader';
|
|
12
12
|
import {listConfig, removeConfig} from './config/configCommands'
|
|
13
|
-
|
|
13
|
+
import {deleteWorkflowTemplate, deployWorkflowTemplate, listWorkflowTemplate} from './workflows/workflowCommands';
|
|
14
14
|
const cliUsage = require('command-line-usage');
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -109,10 +109,30 @@ export async function cli(args) {
|
|
|
109
109
|
await loadColors();
|
|
110
110
|
break;
|
|
111
111
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
case 'delete': {
|
|
113
|
+
await deleteColors();
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
default: {
|
|
117
|
+
printIllegalCommand();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case 'workflow-templates': {
|
|
123
|
+
switch (command) {
|
|
124
|
+
case 'load': {
|
|
125
|
+
await deployWorkflowTemplate();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case 'delete': {
|
|
129
|
+
await deleteWorkflowTemplate();
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case 'list': {
|
|
133
|
+
await listWorkflowTemplate();
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
116
136
|
default: {
|
|
117
137
|
printIllegalCommand();
|
|
118
138
|
}
|
|
@@ -129,10 +149,6 @@ export async function cli(args) {
|
|
|
129
149
|
await removeConfig(args);
|
|
130
150
|
break;
|
|
131
151
|
}
|
|
132
|
-
// case 'delete': {
|
|
133
|
-
// await deleteColors();
|
|
134
|
-
// break;
|
|
135
|
-
// }
|
|
136
152
|
default: {
|
|
137
153
|
printIllegalCommand();
|
|
138
154
|
}
|
|
@@ -200,6 +216,14 @@ const helpSections = [
|
|
|
200
216
|
// 'delete Delete all colors.',
|
|
201
217
|
],
|
|
202
218
|
},
|
|
219
|
+
{
|
|
220
|
+
header: 'Workflow Template Commands - Domain: workflow-templates',
|
|
221
|
+
content: [
|
|
222
|
+
'deploy Deploy your workflow. Assumes a workflow.yml file.',
|
|
223
|
+
'delete Removes the workflows in the workflow.yml file.',
|
|
224
|
+
'list Lists the workflow templates in the org',
|
|
225
|
+
],
|
|
226
|
+
},
|
|
203
227
|
{
|
|
204
228
|
header: 'Type Commands - Domain: types',
|
|
205
229
|
content: [
|
|
@@ -62,7 +62,9 @@ async function getLocalColors() {
|
|
|
62
62
|
async function getExistingColors() {
|
|
63
63
|
console.log(`%s Getting Existing Colors`, chalk.yellow.bold('COLORS'));
|
|
64
64
|
try {
|
|
65
|
-
|
|
65
|
+
const result = await new Entities().get({ entityName: 'color', take: 3000}); //, useSearch: false }); Not in EntitiesClientGetOptions yet
|
|
66
|
+
console.log("Found %s existing colors", result.length)
|
|
67
|
+
return result;
|
|
66
68
|
} catch (e) {
|
|
67
69
|
throw new Error(`ERROR DOWNLOADING COLORS: ${e}`);
|
|
68
70
|
}
|
|
@@ -14,7 +14,7 @@ export interface AppDeclaration {
|
|
|
14
14
|
actions?: { [key: string]: AppActionDeclaration };
|
|
15
15
|
appConfiguration: ConfigPropertyElements;
|
|
16
16
|
triggers: { [key: string]: AppTriggerDeclaration };
|
|
17
|
-
workflows?: { [key: string]:
|
|
17
|
+
workflows?: { [key: string]: WorkflowDefinition|WorkflowTemplateDeclaration }
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface ConfigPropertyElements {
|
|
@@ -42,32 +42,38 @@ export interface AppTriggerDeclaration {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
export interface
|
|
45
|
+
export interface WorkflowDefinition {
|
|
46
46
|
id?: string;
|
|
47
47
|
identifier: string;
|
|
48
48
|
name: string;
|
|
49
49
|
triggerKey: string;
|
|
50
|
-
workflowDefinition:
|
|
50
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
51
51
|
ownerKey: string;
|
|
52
52
|
isActive: boolean;
|
|
53
53
|
public: boolean;
|
|
54
54
|
supportingAppId?: string;
|
|
55
|
+
messageGroupId?: string;
|
|
56
|
+
parallelWorkerCount?: number;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export interface WorkflowTemplateDeclaration {
|
|
60
|
+
workflows?: { [key: string]: WorkflowTemplate }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface WorkflowTemplate {
|
|
58
64
|
id?: string;
|
|
59
65
|
identifier: string;
|
|
60
66
|
name: string;
|
|
61
67
|
triggerKey: string;
|
|
62
|
-
workflowDefinition:
|
|
63
|
-
ownerKey: string;
|
|
68
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
64
69
|
isActive: boolean;
|
|
70
|
+
ownerKey?: string;
|
|
65
71
|
supportingAppId?: string;
|
|
66
72
|
messageGroupId?: string;
|
|
67
73
|
parallelWorkerCount?: number;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
export interface
|
|
76
|
+
export interface WorkflowDefinitionPaths {
|
|
71
77
|
paths: WorkflowConditional[]
|
|
72
78
|
}
|
|
73
79
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Entities } from '@contrail/sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { App, AppDeclaration, WorkflowTemplate, WorkflowTemplateDeclaration } from '../interfaces';
|
|
4
|
+
import { getActionDeclarationIdentifier, getActionsForApp } from '../apps/deploy-app/actions-deployer'
|
|
5
|
+
import { deleteWorkflowTemplate } from './workflowCommands';
|
|
6
|
+
|
|
7
|
+
export class WorkflowTemplateDeployer {
|
|
8
|
+
async deployWorkflows(wtDeclaration: WorkflowTemplateDeclaration) {
|
|
9
|
+
|
|
10
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
11
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
12
|
+
|
|
13
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
14
|
+
console.log('%s \tDeploying workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
15
|
+
|
|
16
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
17
|
+
await this.deployWorkflowTemplate(
|
|
18
|
+
workflowKey,
|
|
19
|
+
wtDeclaration.workflows[workflowKey] as WorkflowTemplate,
|
|
20
|
+
existingWorkflows,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async getExistingWorkflowTemplates() {
|
|
26
|
+
return await new Entities().get({
|
|
27
|
+
entityName: 'event-workflow-template'
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async deployWorkflowTemplate(workflowKey: string, workflow: WorkflowTemplate, existingWorkflows: Array<any>) {
|
|
32
|
+
console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
33
|
+
|
|
34
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
35
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
36
|
+
|
|
37
|
+
if (existingTemplate) {
|
|
38
|
+
return await this.updateWorkflowTemplate(workflowKey, existingTemplate, workflow);
|
|
39
|
+
}
|
|
40
|
+
return await this.createNewWorkflowTemplate(workflowKey, workflow);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async createNewWorkflowTemplate(workflowKey: string, workflowTemplate: WorkflowTemplate) {
|
|
44
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
45
|
+
const newObject: WorkflowTemplate = {
|
|
46
|
+
identifier: getWorkflowTemplateIdentifier(workflowKey),
|
|
47
|
+
name: workflowTemplate.name,
|
|
48
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
49
|
+
workflowDefinition: workflowTemplate.workflowDefinition,
|
|
50
|
+
isActive: workflowTemplate.isActive,
|
|
51
|
+
supportingAppId: workflowTemplate.supportingAppId,
|
|
52
|
+
messageGroupId: workflowTemplate.messageGroupId,
|
|
53
|
+
parallelWorkerCount: workflowTemplate.parallelWorkerCount,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const newWorkflowTemplate = await new Entities().create({
|
|
57
|
+
entityName: 'event-workflow-template',
|
|
58
|
+
object: newObject,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
62
|
+
|
|
63
|
+
return newWorkflowTemplate;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private async populateActionIds(workflowTemplate: WorkflowTemplate, workflowKey: string) {
|
|
67
|
+
if (!workflowTemplate?.workflowDefinition?.paths) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
for (const path of workflowTemplate.workflowDefinition.paths) {
|
|
71
|
+
if (!path?.actionDefinitionConfigs) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
for (const actionConfiguration of path.actionDefinitionConfigs) {
|
|
75
|
+
const actionKey = actionConfiguration.action;
|
|
76
|
+
try {
|
|
77
|
+
const actionEntity: any = await getActionByIdentifier(actionKey);
|
|
78
|
+
console.log("response for action find:", actionEntity)
|
|
79
|
+
actionConfiguration.id = actionEntity.id;
|
|
80
|
+
console.log("found action id:", actionEntity.id)
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.log(e)
|
|
83
|
+
}
|
|
84
|
+
if(!actionConfiguration.id) {
|
|
85
|
+
throw new Error(`Could not find action ${actionKey} declared in ${workflowKey}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private async updateWorkflowTemplate(workflowKey: string, existingWorkflowTemplate: WorkflowTemplate, workflowTemplate: WorkflowTemplate) {
|
|
92
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
93
|
+
const updates = Object.assign(new Object(), {
|
|
94
|
+
name: workflowTemplate.name,
|
|
95
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
96
|
+
workflowDefinition: workflowTemplate.workflowDefinition
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const updatedWorkflowTemplate = await new Entities().update({
|
|
100
|
+
entityName: 'event-workflow-template',
|
|
101
|
+
id: existingWorkflowTemplate.id,
|
|
102
|
+
object: updates,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(`%s Updated existing workflow template: ${updatedWorkflowTemplate.identifier}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
106
|
+
|
|
107
|
+
return updatedWorkflowTemplate;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public async deleteWorkflowTemplates(wtDeclaration: WorkflowTemplateDeclaration) {
|
|
111
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
112
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
113
|
+
|
|
114
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
115
|
+
console.log('%s \tDELETING workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
116
|
+
|
|
117
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
118
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
119
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
120
|
+
|
|
121
|
+
if (existingTemplate) {
|
|
122
|
+
try {
|
|
123
|
+
await this.deleteWorkflowTemplate(identifier);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.log('%s \tFAILED to delete workflow template %s.', chalk.red.bold('WORKFLOW TEMPLATES'), identifier);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
console.log('%s \tUnable to locate workflow template %s.', chalk.yellow.bold('WORKFLOW TEMPLATES'), identifier);
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private async deleteWorkflowTemplate(identifier: string) {
|
|
136
|
+
return await new Entities().delete({
|
|
137
|
+
entityName: 'event-workflow-template',
|
|
138
|
+
id: identifier,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public async listExistingWorkflowTemplates() {
|
|
143
|
+
const templates = await this.getExistingWorkflowTemplates();
|
|
144
|
+
console.log(templates);
|
|
145
|
+
return templates;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function getWorkflowTemplateIdentifier(workflowKey: string) {
|
|
150
|
+
return workflowKey;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function getActionByIdentifier(identifier: string) {
|
|
154
|
+
const result = await new Entities().get({
|
|
155
|
+
entityName: 'event-workflow-action-definition',
|
|
156
|
+
criteria: { identifier },
|
|
157
|
+
});
|
|
158
|
+
return result.length > 0? result[0]: {};
|
|
159
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { authUser } from '../auth/login';
|
|
5
|
+
import { WorkflowTemplateDeclaration } from '../interfaces';
|
|
6
|
+
import { getSeparatorByPlatform } from '../common';
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
import { WorkflowTemplateDeployer } from './workflow-template-deployer';
|
|
9
|
+
|
|
10
|
+
export async function deleteWorkflowTemplate() {
|
|
11
|
+
let wtDeclaration: WorkflowTemplateDeclaration;
|
|
12
|
+
try {
|
|
13
|
+
wtDeclaration = loadTemplateConfig();
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.log(`%s Workflow Deletion Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
await authUser();
|
|
21
|
+
await new WorkflowTemplateDeployer().deleteWorkflowTemplates(wtDeclaration);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function deployWorkflowTemplate() {
|
|
25
|
+
let wtDeclaration: WorkflowTemplateDeclaration;
|
|
26
|
+
try {
|
|
27
|
+
wtDeclaration = loadTemplateConfig();
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.log(`%s Workflow Deletion Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await authUser();
|
|
35
|
+
await new WorkflowTemplateDeployer().deployWorkflows(wtDeclaration);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
export async function listWorkflowTemplate() {
|
|
40
|
+
await authUser();
|
|
41
|
+
return await new WorkflowTemplateDeployer().listExistingWorkflowTemplates();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function loadTemplateConfig() {
|
|
45
|
+
const TARGET_DIR = process.cwd();
|
|
46
|
+
try {
|
|
47
|
+
const separator = getSeparatorByPlatform();
|
|
48
|
+
const doc = yaml.load(fs.readFileSync(TARGET_DIR + separator + 'workflow.yml', 'utf8'));
|
|
49
|
+
console.log(doc);
|
|
50
|
+
return doc;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { Entities } from '@contrail/sdk';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { App, AppDeclaration, WorkflowTemplateDeclaration } from './interfaces';
|
|
4
|
-
import { getActionDeclarationIdentifier, getActionsForApp } from './actions-deployer'
|
|
5
|
-
|
|
6
|
-
export class WorkflowDeployer {
|
|
7
|
-
async deployWorkflows(appDeclaration: AppDeclaration, app: App) {
|
|
8
|
-
|
|
9
|
-
// FETCH ALL WORKFLOWS FROM THE API.
|
|
10
|
-
const existingWorkflows = await this.getWorkflowsForApp(app);
|
|
11
|
-
|
|
12
|
-
// UPSERT / DELETE BASED ON WORKFLOW IDENTIFIER
|
|
13
|
-
console.log('%s \tDeploying workflows.', chalk.yellow.bold('WORKFLOW'));
|
|
14
|
-
|
|
15
|
-
for (const workflowKey of Object.keys(appDeclaration.workflows)) {
|
|
16
|
-
await this.deployWorkflow(workflowKey,
|
|
17
|
-
appDeclaration.workflows[workflowKey] as WorkflowTemplateDeclaration,
|
|
18
|
-
app,
|
|
19
|
-
existingWorkflows,
|
|
20
|
-
appDeclaration);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getWorkflowsForApp(app: App) {
|
|
25
|
-
return await new Entities().get({
|
|
26
|
-
entityName: 'event-workflow-template',
|
|
27
|
-
criteria: { ownerKey: `app:${app.id}` },
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async deployWorkflow(workflowKey: string, workflow: WorkflowTemplateDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration) {
|
|
32
|
-
console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
|
|
33
|
-
|
|
34
|
-
const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
|
|
35
|
-
const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
36
|
-
|
|
37
|
-
if (existingDefinition) {
|
|
38
|
-
return await this.updateWorkflowDefinition(existingDefinition, workflow, app, appDeclaration);
|
|
39
|
-
}
|
|
40
|
-
return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private async createNewWorkflowDefinition(workflowKey: string, workflowDeclaration: WorkflowTemplateDeclaration, app: App, appDeclaration: AppDeclaration) {
|
|
44
|
-
await this.populateActionIds(workflowDeclaration, appDeclaration, app);
|
|
45
|
-
const newObject: WorkflowTemplateDeclaration = {
|
|
46
|
-
identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
|
|
47
|
-
name: workflowDeclaration.name,
|
|
48
|
-
ownerKey: `app:${app.id}`,
|
|
49
|
-
triggerKey: workflowDeclaration.triggerKey,
|
|
50
|
-
workflowDefinition: workflowDeclaration.workflowDefinition,
|
|
51
|
-
isActive: workflowDeclaration.isActive,
|
|
52
|
-
supportingAppId: workflowDeclaration.supportingAppId,
|
|
53
|
-
messageGroupId: workflowDeclaration.messageGroupId,
|
|
54
|
-
parallelWorkerCount: workflowDeclaration.parallelWorkerCount,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const workflowTemplate = await new Entities().create({
|
|
58
|
-
entityName: 'event-workflow-template',
|
|
59
|
-
object: newObject,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
|
|
63
|
-
|
|
64
|
-
return workflowTemplate;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private async populateActionIds(workflowDeclaration: WorkflowTemplateDeclaration, appDeclaration: AppDeclaration, app: App) {
|
|
68
|
-
let availableAppActions = await getActionsForApp(app);
|
|
69
|
-
if (!workflowDeclaration.workflowDefinition?.paths) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
for (const path of workflowDeclaration.workflowDefinition.paths) {
|
|
73
|
-
if (!path?.actionDefinitionConfigs) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
for (const actionConfiguration of path.actionDefinitionConfigs) {
|
|
77
|
-
const actionKey = actionConfiguration.action;
|
|
78
|
-
const action = availableAppActions.find(
|
|
79
|
-
action => action.identifier === getActionDeclarationIdentifier(actionKey, app)
|
|
80
|
-
)
|
|
81
|
-
if (!action) {
|
|
82
|
-
throw new Error(`Could not find action ${actionKey} declared in ${workflowDeclaration.name}`);
|
|
83
|
-
}
|
|
84
|
-
actionConfiguration.id = action.id;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private async updateWorkflowDefinition(existingWorkflowDefinition: WorkflowTemplateDeclaration, workflowDeclaration: WorkflowTemplateDeclaration, app: App, appDeclaration: AppDeclaration) {
|
|
90
|
-
await this.populateActionIds(workflowDeclaration, appDeclaration, app);
|
|
91
|
-
const updates = Object.assign(new Object(), {
|
|
92
|
-
name: workflowDeclaration.name,
|
|
93
|
-
triggerKey: workflowDeclaration.triggerKey,
|
|
94
|
-
workflowDefinition: workflowDeclaration.workflowDefinition
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const updatedWorkflowDefinition = await new Entities().update({
|
|
98
|
-
entityName: 'event-workflow-template',
|
|
99
|
-
id: existingWorkflowDefinition.id,
|
|
100
|
-
object: updates,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
console.log(`%s Updated existing workflow definition: ${updatedWorkflowDefinition.identifier}`, chalk.yellow.bold('WORKFLOW'));
|
|
104
|
-
|
|
105
|
-
return updatedWorkflowDefinition;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
getWorkflowDeclarationIdentifier(actionKey, app: App) {
|
|
109
|
-
return app.identifier + ':' + actionKey;
|
|
110
|
-
}
|
|
111
|
-
}
|