@contrail/cli 1.0.22 → 1.0.24
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 +4 -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/docker-action-builder.d.ts +10 -0
- package/lib/apps/deploy-app/docker-action-builder.js +97 -0
- package/lib/apps/deploy-app/interfaces.d.ts +2 -41
- 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 +124 -0
- package/lib/interfaces.js +4 -0
- package/lib/workflows/workflow-template-deployer.d.ts +14 -0
- package/lib/workflows/workflow-template-deployer.js +127 -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 +5 -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} +14 -6
- package/src/workflows/workflow-template-deployer.ts +157 -0
- package/src/workflows/workflowCommands.ts +54 -0
- package/templates/typescript/app.yml +1 -0
- package/src/apps/deploy-app/workflow-deployer.ts +0 -111
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
actionConfiguration.id = actionEntity.id;
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
console.log(e);
|
|
63
|
+
}
|
|
64
|
+
if (!actionConfiguration.id) {
|
|
65
|
+
throw new Error(`Could not find action ${actionKey} declared in ${workflowKey}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async updateWorkflowTemplate(workflowKey, existingWorkflowTemplate, workflowTemplate) {
|
|
71
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
72
|
+
const updates = Object.assign(new Object(), {
|
|
73
|
+
name: workflowTemplate.name,
|
|
74
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
75
|
+
workflowDefinition: workflowTemplate.workflowDefinition
|
|
76
|
+
});
|
|
77
|
+
const updatedWorkflowTemplate = await new Entities().update({
|
|
78
|
+
entityName: 'event-workflow-template',
|
|
79
|
+
id: existingWorkflowTemplate.id,
|
|
80
|
+
object: updates,
|
|
81
|
+
});
|
|
82
|
+
console.log(`%s Updated existing workflow template: ${updatedWorkflowTemplate.identifier}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
83
|
+
return updatedWorkflowTemplate;
|
|
84
|
+
}
|
|
85
|
+
async deleteWorkflowTemplates(wtDeclaration) {
|
|
86
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
87
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
88
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
89
|
+
console.log('%s \tDELETING workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
90
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
91
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
92
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
93
|
+
if (existingTemplate) {
|
|
94
|
+
try {
|
|
95
|
+
await this.deleteWorkflowTemplate(identifier);
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.log('%s \tFAILED to delete workflow template %s.', chalk.red.bold('WORKFLOW TEMPLATES'), identifier);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log('%s \tUnable to locate workflow template %s.', chalk.yellow.bold('WORKFLOW TEMPLATES'), identifier);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async deleteWorkflowTemplate(identifier) {
|
|
107
|
+
return await new Entities().delete({
|
|
108
|
+
entityName: 'event-workflow-template',
|
|
109
|
+
id: identifier,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async listExistingWorkflowTemplates() {
|
|
113
|
+
const templates = await this.getExistingWorkflowTemplates();
|
|
114
|
+
console.log(templates);
|
|
115
|
+
return templates;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export function getWorkflowTemplateIdentifier(workflowKey) {
|
|
119
|
+
return workflowKey;
|
|
120
|
+
}
|
|
121
|
+
export async function getActionByIdentifier(identifier) {
|
|
122
|
+
const result = await new Entities().get({
|
|
123
|
+
entityName: 'event-workflow-action-definition',
|
|
124
|
+
criteria: { identifier },
|
|
125
|
+
});
|
|
126
|
+
return result.length > 0 ? result[0] : {};
|
|
127
|
+
}
|
|
@@ -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> {
|
|
@@ -70,6 +65,7 @@ export class AppDeployer {
|
|
|
70
65
|
keywords: appDeclaration.keywords,
|
|
71
66
|
configProperties,
|
|
72
67
|
triggerKeyDefinitions,
|
|
68
|
+
isDockerBased: appDeclaration.isDockerBased,
|
|
73
69
|
};
|
|
74
70
|
const app = await new Entities().create({ entityName: 'app', object: newApp });
|
|
75
71
|
console.log(`%s Created new app: ${app.name}`, chalk.yellow.bold('APP'));
|
|
@@ -98,6 +94,7 @@ export class AppDeployer {
|
|
|
98
94
|
keywords: appDeclaration.keywords,
|
|
99
95
|
configProperties,
|
|
100
96
|
triggerKeyDefinitions,
|
|
97
|
+
isDockerBased: appDeclaration.isDockerBased,
|
|
101
98
|
};
|
|
102
99
|
const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
|
|
103
100
|
console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('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,8 @@ 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
|
+
isDockerBased?: boolean;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface ConfigPropertyElements {
|
|
@@ -42,32 +43,38 @@ export interface AppTriggerDeclaration {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
export interface
|
|
46
|
+
export interface WorkflowDefinition {
|
|
46
47
|
id?: string;
|
|
47
48
|
identifier: string;
|
|
48
49
|
name: string;
|
|
49
50
|
triggerKey: string;
|
|
50
|
-
workflowDefinition:
|
|
51
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
51
52
|
ownerKey: string;
|
|
52
53
|
isActive: boolean;
|
|
53
54
|
public: boolean;
|
|
54
55
|
supportingAppId?: string;
|
|
56
|
+
messageGroupId?: string;
|
|
57
|
+
parallelWorkerCount?: number;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
export interface WorkflowTemplateDeclaration {
|
|
61
|
+
workflows?: { [key: string]: WorkflowTemplate }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface WorkflowTemplate {
|
|
58
65
|
id?: string;
|
|
59
66
|
identifier: string;
|
|
60
67
|
name: string;
|
|
61
68
|
triggerKey: string;
|
|
62
|
-
workflowDefinition:
|
|
63
|
-
ownerKey: string;
|
|
69
|
+
workflowDefinition: WorkflowDefinitionPaths;
|
|
64
70
|
isActive: boolean;
|
|
71
|
+
ownerKey?: string;
|
|
65
72
|
supportingAppId?: string;
|
|
66
73
|
messageGroupId?: string;
|
|
67
74
|
parallelWorkerCount?: number;
|
|
68
75
|
}
|
|
69
76
|
|
|
70
|
-
export interface
|
|
77
|
+
export interface WorkflowDefinitionPaths {
|
|
71
78
|
paths: WorkflowConditional[]
|
|
72
79
|
}
|
|
73
80
|
|
|
@@ -110,6 +117,7 @@ export interface EventWorkflowActionDefinition {
|
|
|
110
117
|
ownerKey?: string;
|
|
111
118
|
public?: boolean;
|
|
112
119
|
configProperties?: ConfigProperty[];
|
|
120
|
+
isDockerBased?: boolean;
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
export class TriggerKeyDefinition {
|
|
@@ -0,0 +1,157 @@
|
|
|
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
|
+
actionConfiguration.id = actionEntity.id;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.log(e)
|
|
81
|
+
}
|
|
82
|
+
if(!actionConfiguration.id) {
|
|
83
|
+
throw new Error(`Could not find action ${actionKey} declared in ${workflowKey}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private async updateWorkflowTemplate(workflowKey: string, existingWorkflowTemplate: WorkflowTemplate, workflowTemplate: WorkflowTemplate) {
|
|
90
|
+
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
91
|
+
const updates = Object.assign(new Object(), {
|
|
92
|
+
name: workflowTemplate.name,
|
|
93
|
+
triggerKey: workflowTemplate.triggerKey,
|
|
94
|
+
workflowDefinition: workflowTemplate.workflowDefinition
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const updatedWorkflowTemplate = await new Entities().update({
|
|
98
|
+
entityName: 'event-workflow-template',
|
|
99
|
+
id: existingWorkflowTemplate.id,
|
|
100
|
+
object: updates,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
console.log(`%s Updated existing workflow template: ${updatedWorkflowTemplate.identifier}`, chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
104
|
+
|
|
105
|
+
return updatedWorkflowTemplate;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public async deleteWorkflowTemplates(wtDeclaration: WorkflowTemplateDeclaration) {
|
|
109
|
+
// FETCH ALL WORKFLOWS FROM THE API.
|
|
110
|
+
const existingWorkflows = await this.getExistingWorkflowTemplates();
|
|
111
|
+
|
|
112
|
+
// UPSERT / DELETE BASED ON WORKFLOW TEMPLATES IDENTIFIER
|
|
113
|
+
console.log('%s \tDELETING workflow templates.', chalk.yellow.bold('WORKFLOW TEMPLATES'));
|
|
114
|
+
|
|
115
|
+
for (const workflowKey of Object.keys(wtDeclaration.workflows)) {
|
|
116
|
+
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
117
|
+
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
118
|
+
|
|
119
|
+
if (existingTemplate) {
|
|
120
|
+
try {
|
|
121
|
+
await this.deleteWorkflowTemplate(identifier);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
console.log('%s \tFAILED to delete workflow template %s.', chalk.red.bold('WORKFLOW TEMPLATES'), identifier);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
console.log('%s \tUnable to locate workflow template %s.', chalk.yellow.bold('WORKFLOW TEMPLATES'), identifier);
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private async deleteWorkflowTemplate(identifier: string) {
|
|
134
|
+
return await new Entities().delete({
|
|
135
|
+
entityName: 'event-workflow-template',
|
|
136
|
+
id: identifier,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public async listExistingWorkflowTemplates() {
|
|
141
|
+
const templates = await this.getExistingWorkflowTemplates();
|
|
142
|
+
console.log(templates);
|
|
143
|
+
return templates;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function getWorkflowTemplateIdentifier(workflowKey: string) {
|
|
148
|
+
return workflowKey;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function getActionByIdentifier(identifier: string) {
|
|
152
|
+
const result = await new Entities().get({
|
|
153
|
+
entityName: 'event-workflow-action-definition',
|
|
154
|
+
criteria: { identifier },
|
|
155
|
+
});
|
|
156
|
+
return result.length > 0? result[0]: {};
|
|
157
|
+
}
|