@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.
Files changed (31) hide show
  1. package/lib/apps/deploy-app/actions-deployer.d.ts +1 -1
  2. package/lib/apps/deploy-app/app-deployer.d.ts +2 -2
  3. package/lib/apps/deploy-app/app-deployer.js +4 -8
  4. package/lib/apps/deploy-app/app-template-parsers.d.ts +1 -1
  5. package/lib/apps/deploy-app/deploy.js +1 -2
  6. package/lib/apps/deploy-app/docker-action-builder.d.ts +10 -0
  7. package/lib/apps/deploy-app/docker-action-builder.js +97 -0
  8. package/lib/apps/deploy-app/interfaces.d.ts +2 -41
  9. package/lib/apps/deploy-app/workflow-definition-deployer.d.ts +2 -2
  10. package/lib/apps/deploy-app/workflow-definition-deployer.js +19 -15
  11. package/lib/cli.js +34 -9
  12. package/lib/colors/color-loader.js +3 -1
  13. package/lib/interfaces.d.ts +124 -0
  14. package/lib/interfaces.js +4 -0
  15. package/lib/workflows/workflow-template-deployer.d.ts +14 -0
  16. package/lib/workflows/workflow-template-deployer.js +127 -0
  17. package/lib/workflows/workflowCommands.d.ts +3 -0
  18. package/lib/workflows/workflowCommands.js +46 -0
  19. package/package.json +1 -1
  20. package/src/apps/deploy-app/actions-deployer.ts +1 -1
  21. package/src/apps/deploy-app/app-deployer.ts +5 -8
  22. package/src/apps/deploy-app/app-template-parsers.ts +1 -1
  23. package/src/apps/deploy-app/deploy.ts +2 -3
  24. package/src/apps/deploy-app/workflow-definition-deployer.ts +21 -18
  25. package/src/cli.ts +33 -9
  26. package/src/colors/color-loader.ts +3 -1
  27. package/src/{apps/deploy-app/interfaces.ts → interfaces.ts} +14 -6
  28. package/src/workflows/workflow-template-deployer.ts +157 -0
  29. package/src/workflows/workflowCommands.ts +54 -0
  30. package/templates/typescript/app.yml +1 -0
  31. 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,3 @@
1
+ export declare function deleteWorkflowTemplate(): Promise<void>;
2
+ export declare function deployWorkflowTemplate(): Promise<void>;
3
+ export declare function listWorkflowTemplate(): Promise<any>;
@@ -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
  {
2
2
  "name": "@contrail/cli",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  import { Entities } from '@contrail/sdk';
2
2
  import chalk from 'chalk';
3
- import { App, AppDeclaration, AppActionDeclaration, EventWorkflowActionDefinition } from './interfaces';
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 './interfaces';
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, deployWorkflowTemplateOnly = false) {
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
- if (deployWorkflowTemplateOnly) {
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 './interfaces';
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 './interfaces';
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, templateOnly);
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, WorkflowDefinitionDeclaration } from './interfaces';
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 WorkflowDefinitionDeclaration,
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: WorkflowDefinitionDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration) {
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, appDeclaration);
38
+ return await this.updateWorkflowDefinition(existingDefinition, workflow, app);
40
39
  }
41
- return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
40
+ return await this.createNewWorkflowDefinition(workflowKey, workflow, app);
42
41
  }
43
42
 
44
- private async createNewWorkflowDefinition(workflowKey: string, workflowDeclaration: WorkflowDefinitionDeclaration, app: App, appDeclaration: AppDeclaration) {
45
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
46
- const newObject: WorkflowDefinitionDeclaration = {
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(workflowDeclaration: WorkflowDefinitionDeclaration, appDeclaration: AppDeclaration, app: App) {
67
+ private async populateActionIds(workflowDefinition: WorkflowDefinition, app: App) {
67
68
  let availableAppActions = await getActionsForApp(app);
68
- if (!workflowDeclaration.workflowDefinition?.paths) {
69
+ if (!workflowDefinition.workflowDefinition?.paths) {
69
70
  return;
70
71
  }
71
- for (const path of workflowDeclaration.workflowDefinition.paths) {
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 ${workflowDeclaration.name}`);
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: WorkflowDefinitionDeclaration, workflowDeclaration: WorkflowDefinitionDeclaration, app: App, appDeclaration: AppDeclaration) {
89
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
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: workflowDeclaration.name,
92
- triggerKey: workflowDeclaration.triggerKey,
93
- workflowDefinition: workflowDeclaration.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
- // case 'delete': {
113
- // await deleteColors();
114
- // break;
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
- return new Entities().get({ entityName: 'color'}); //, useSearch: false }); Not in EntitiesClientGetOptions yet
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]: WorkflowDefinitionDeclaration|WorkflowTemplateDeclaration }
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 WorkflowDefinitionDeclaration {
46
+ export interface WorkflowDefinition {
46
47
  id?: string;
47
48
  identifier: string;
48
49
  name: string;
49
50
  triggerKey: string;
50
- workflowDefinition: 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: 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 WorkflowDefinition {
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
+ }