@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.
@@ -1,4 +1,4 @@
1
- import { App, AppDeclaration, AppActionDeclaration } from './interfaces';
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 './interfaces';
1
+ import { App, AppDeclaration } from '../../interfaces';
2
2
  export declare class AppDeployer {
3
- deploy(appDeclaration: AppDeclaration, deployWorkflowTemplateOnly?: boolean): Promise<void>;
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, deployWorkflowTemplateOnly = false) {
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
- if (deployWorkflowTemplateOnly) {
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 './interfaces';
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, templateOnly);
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, WorkflowDefinitionDeclaration } from './interfaces';
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: WorkflowDefinitionDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration): Promise<any>;
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, appDeclaration);
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, appDeclaration) {
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, appDeclaration);
25
+ return await this.updateWorkflowDefinition(existingDefinition, workflow, app);
26
26
  }
27
- return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
27
+ return await this.createNewWorkflowDefinition(workflowKey, workflow, app);
28
28
  }
29
- async createNewWorkflowDefinition(workflowKey, workflowDeclaration, app, appDeclaration) {
30
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
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(workflowDeclaration, appDeclaration, app) {
49
+ async populateActionIds(workflowDefinition, app) {
48
50
  var _a;
49
51
  let availableAppActions = await getActionsForApp(app);
50
- if (!((_a = workflowDeclaration.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
52
+ if (!((_a = workflowDefinition.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
51
53
  return;
52
54
  }
53
- for (const path of workflowDeclaration.workflowDefinition.paths) {
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 ${workflowDeclaration.name}`);
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, workflowDeclaration, app, appDeclaration) {
68
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
69
+ async updateWorkflowDefinition(existingWorkflowDefinition, workflowDefinition, app) {
70
+ await this.populateActionIds(workflowDefinition, app);
69
71
  const updates = Object.assign(new Object(), {
70
- name: workflowDeclaration.name,
71
- triggerKey: workflowDeclaration.triggerKey,
72
- workflowDefinition: workflowDeclaration.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
- // case 'delete': {
104
- // await deleteColors();
105
- // break;
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
- return new Entities().get({ entityName: 'color' }); //, useSearch: false }); Not in EntitiesClientGetOptions yet
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,4 @@
1
+ export class ConfigProperty {
2
+ }
3
+ export class TriggerKeyDefinition {
4
+ }
@@ -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,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.23",
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> {
@@ -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,7 @@ 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
18
  }
19
19
 
20
20
  export interface ConfigPropertyElements {
@@ -42,32 +42,38 @@ export interface AppTriggerDeclaration {
42
42
  }
43
43
 
44
44
 
45
- export interface WorkflowDefinitionDeclaration {
45
+ export interface WorkflowDefinition {
46
46
  id?: string;
47
47
  identifier: string;
48
48
  name: string;
49
49
  triggerKey: string;
50
- workflowDefinition: 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: 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 WorkflowDefinition {
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
- }