@contrail/cli 1.0.18 → 1.0.19

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,10 +1,10 @@
1
1
  import { App, AppDeclaration, AppActionDeclaration } from './interfaces';
2
+ export declare function getActionsForApp(app: App): Promise<any>;
3
+ export declare function getActionDeclarationIdentifier(actionKey: any, app: App): string;
2
4
  export declare class ActionsDeployer {
3
5
  deployActions(appDeclaration: AppDeclaration, app: App): Promise<void>;
4
- getActionsForApp(app: App): Promise<any>;
5
6
  deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>): Promise<void>;
6
7
  private createNewActionDefinition;
7
8
  private updateActionDefinition;
8
- getActionDeclarationIdentifier(actionKey: any, app: App): string;
9
9
  getFunction(actionDeclaration: AppActionDeclaration): Promise<string>;
10
10
  }
@@ -3,25 +3,28 @@ import chalk from 'chalk';
3
3
  import { ConfigPropertiesParser } from './app-template-parsers';
4
4
  import { getSeparatorByPlatform } from '../../common';
5
5
  import fs from 'fs';
6
+ export async function getActionsForApp(app) {
7
+ return await new Entities().get({
8
+ entityName: 'event-workflow-action-definition',
9
+ criteria: { ownerKey: `app:${app.id}` },
10
+ });
11
+ }
12
+ export function getActionDeclarationIdentifier(actionKey, app) {
13
+ return app.identifier + ':' + actionKey;
14
+ }
6
15
  export class ActionsDeployer {
7
16
  async deployActions(appDeclaration, app) {
8
17
  // FETCH ALL ACTIONS FROM THE API.
9
- const existingActions = await this.getActionsForApp(app);
18
+ const existingActions = await getActionsForApp(app);
10
19
  // UPSERT / DELETE BASED ON ACTION IDENTIFIER
11
20
  console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
12
21
  for (const actionKey of Object.keys(appDeclaration.actions)) {
13
22
  await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
14
23
  }
15
24
  }
16
- async getActionsForApp(app) {
17
- return await new Entities().get({
18
- entityName: 'event-workflow-action-definition',
19
- criteria: { ownerKey: `app:${app.id}` },
20
- });
21
- }
22
25
  async deployAction(actionKey, actionDeclaration, app, existingActions) {
23
26
  console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
24
- const identifier = this.getActionDeclarationIdentifier(actionKey, app);
27
+ const identifier = getActionDeclarationIdentifier(actionKey, app);
25
28
  const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
26
29
  if (!existingDefinition) {
27
30
  await this.createNewActionDefinition(actionKey, actionDeclaration, app);
@@ -36,7 +39,7 @@ export class ActionsDeployer {
36
39
  configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
37
40
  }
38
41
  const newObject = {
39
- identifier: this.getActionDeclarationIdentifier(actionKey, app),
42
+ identifier: getActionDeclarationIdentifier(actionKey, app),
40
43
  name: actionDeclaration.name,
41
44
  ownerKey: `app:${app.id}`,
42
45
  public: app.public,
@@ -78,9 +81,6 @@ export class ActionsDeployer {
78
81
  console.log(`%s Updated existing action definition: ${actionDefinition.identifier}`, chalk.yellow.bold('APP'));
79
82
  return actionDefinition;
80
83
  }
81
- getActionDeclarationIdentifier(actionKey, app) {
82
- return app.identifier + ':' + actionKey;
83
- }
84
84
  async getFunction(actionDeclaration) {
85
85
  if (!actionDeclaration.handler) {
86
86
  return;
@@ -3,6 +3,7 @@ import chalk from 'chalk';
3
3
  import { Auth } from '../../auth/auth';
4
4
  import { ActionsDeployer } from './actions-deployer';
5
5
  import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
6
+ import { WorkflowDeployer } from './workflow-deployer';
6
7
  export class AppDeployer {
7
8
  async deploy(appDeclaration) {
8
9
  let app = await this.getExistingApp(appDeclaration);
@@ -15,6 +16,7 @@ export class AppDeployer {
15
16
  app = await this.updateExistingApp(appDeclaration, app);
16
17
  }
17
18
  await new ActionsDeployer().deployActions(appDeclaration, app);
19
+ await new WorkflowDeployer().deployWorkflows(appDeclaration, app);
18
20
  }
19
21
  async getExistingApp(appDeclaration) {
20
22
  const orgId = Auth.config.orgId;
@@ -18,6 +18,9 @@ export interface AppDeclaration {
18
18
  triggers: {
19
19
  [key: string]: AppTriggerDeclaration;
20
20
  };
21
+ workflows?: {
22
+ [key: string]: WorkflowDeclaration;
23
+ };
21
24
  }
22
25
  export interface ConfigPropertyElements {
23
26
  [key: string]: ConfigPropertyElement;
@@ -39,6 +42,30 @@ export interface AppTriggerDeclaration {
39
42
  external?: boolean;
40
43
  description?: string;
41
44
  }
45
+ export interface WorkflowDeclaration {
46
+ id?: string;
47
+ identifier: string;
48
+ name: string;
49
+ triggerKey: string;
50
+ workflowDefinition: WorkflowDefinition;
51
+ ownerKey: string;
52
+ isActive: boolean;
53
+ }
54
+ export interface WorkflowDefinition {
55
+ paths: WorkflowConditional[];
56
+ }
57
+ export interface WorkflowConditional {
58
+ conditional: string;
59
+ actionDefinitionConfigs: ActionDefinitionConfig[];
60
+ }
61
+ export interface ActionDefinitionConfig {
62
+ name: string;
63
+ action: string;
64
+ config?: {
65
+ [key: string]: any;
66
+ };
67
+ id?: string;
68
+ }
42
69
  export interface App {
43
70
  id: string;
44
71
  identifier: string;
@@ -0,0 +1,10 @@
1
+ import { App, AppDeclaration, WorkflowDeclaration } from './interfaces';
2
+ export declare class WorkflowDeployer {
3
+ deployWorkflows(appDeclaration: AppDeclaration, app: App): Promise<void>;
4
+ getWorkflowsForApp(app: App): Promise<any>;
5
+ deployWorkflow(workflowKey: string, workflow: WorkflowDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration): Promise<any>;
6
+ private createNewWorkflowDefinition;
7
+ private populateActionIds;
8
+ private updateWorkflowDefinition;
9
+ getWorkflowDeclarationIdentifier(actionKey: any, app: App): string;
10
+ }
@@ -0,0 +1,84 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import { getActionDeclarationIdentifier, getActionsForApp } from './actions-deployer';
4
+ export class WorkflowDeployer {
5
+ async deployWorkflows(appDeclaration, app) {
6
+ // FETCH ALL WORKFLOWS FROM THE API.
7
+ const existingWorkflows = await this.getWorkflowsForApp(app);
8
+ // UPSERT / DELETE BASED ON WORKFLOW IDENTIFIER
9
+ console.log('%s \tDeploying workflows.', chalk.yellow.bold('WORKFLOW'));
10
+ for (const workflowKey of Object.keys(appDeclaration.workflows)) {
11
+ await this.deployWorkflow(workflowKey, appDeclaration.workflows[workflowKey], app, existingWorkflows, appDeclaration);
12
+ }
13
+ }
14
+ async getWorkflowsForApp(app) {
15
+ return await new Entities().get({
16
+ entityName: 'event-workflow-template',
17
+ criteria: { ownerKey: `app:${app.id}` },
18
+ });
19
+ }
20
+ async deployWorkflow(workflowKey, workflow, app, existingWorkflows, appDeclaration) {
21
+ console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
22
+ const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
23
+ const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
24
+ if (existingDefinition) {
25
+ return await this.updateWorkflowDefinition(existingDefinition, workflow, app, appDeclaration);
26
+ }
27
+ return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
28
+ }
29
+ async createNewWorkflowDefinition(workflowKey, workflowDeclaration, app, appDeclaration) {
30
+ await this.populateActionIds(workflowDeclaration, appDeclaration, app);
31
+ const newObject = {
32
+ identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
33
+ name: workflowDeclaration.name,
34
+ ownerKey: `app:${app.id}`,
35
+ triggerKey: workflowDeclaration.triggerKey,
36
+ workflowDefinition: workflowDeclaration.workflowDefinition,
37
+ isActive: workflowDeclaration.isActive
38
+ };
39
+ const workflowTemplate = 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'));
44
+ return workflowTemplate;
45
+ }
46
+ async populateActionIds(workflowDeclaration, appDeclaration, app) {
47
+ var _a;
48
+ let availableAppActions = await getActionsForApp(app);
49
+ if (!((_a = workflowDeclaration.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
50
+ return;
51
+ }
52
+ for (const path of workflowDeclaration.workflowDefinition.paths) {
53
+ if (!(path === null || path === void 0 ? void 0 : path.actionDefinitionConfigs)) {
54
+ continue;
55
+ }
56
+ for (const actionConfiguration of path.actionDefinitionConfigs) {
57
+ const actionKey = actionConfiguration.action;
58
+ const action = availableAppActions.find(action => action.identifier === getActionDeclarationIdentifier(actionKey, app));
59
+ if (!action) {
60
+ throw new Error(`Could not find action ${actionKey} declared in ${workflowDeclaration.name}`);
61
+ }
62
+ actionConfiguration.id = action.id;
63
+ }
64
+ }
65
+ }
66
+ async updateWorkflowDefinition(existingWorkflowDefinition, workflowDeclaration, app, appDeclaration) {
67
+ await this.populateActionIds(workflowDeclaration, appDeclaration, app);
68
+ const updates = Object.assign(new Object(), {
69
+ name: workflowDeclaration.name,
70
+ triggerKey: workflowDeclaration.triggerKey,
71
+ workflowDefinition: workflowDeclaration.workflowDefinition
72
+ });
73
+ const updatedWorkflowDefinition = await new Entities().update({
74
+ entityName: 'event-workflow-template',
75
+ id: existingWorkflowDefinition.id,
76
+ object: updates,
77
+ });
78
+ console.log(`%s Updated existing workflow definition: ${updatedWorkflowDefinition.identifier}`, chalk.yellow.bold('WORKFLOW'));
79
+ return updatedWorkflowDefinition;
80
+ }
81
+ getWorkflowDeclarationIdentifier(actionKey, app) {
82
+ return app.identifier + ':' + actionKey;
83
+ }
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -6,11 +6,24 @@ import { getSeparatorByPlatform } from '../../common';
6
6
 
7
7
  import fs from 'fs';
8
8
 
9
+
10
+ export async function getActionsForApp(app: App) {
11
+ return await new Entities().get({
12
+ entityName: 'event-workflow-action-definition',
13
+ criteria: { ownerKey: `app:${app.id}` },
14
+ });
15
+ }
16
+
17
+
18
+ export function getActionDeclarationIdentifier(actionKey, app: App) {
19
+ return app.identifier + ':' + actionKey;
20
+ }
21
+
9
22
  export class ActionsDeployer {
10
23
  async deployActions(appDeclaration: AppDeclaration, app: App) {
11
24
 
12
25
  // FETCH ALL ACTIONS FROM THE API.
13
- const existingActions = await this.getActionsForApp(app);
26
+ const existingActions = await getActionsForApp(app);
14
27
 
15
28
  // UPSERT / DELETE BASED ON ACTION IDENTIFIER
16
29
  console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
@@ -19,18 +32,10 @@ export class ActionsDeployer {
19
32
  await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
20
33
  }
21
34
  }
22
-
23
- async getActionsForApp(app: App) {
24
- return await new Entities().get({
25
- entityName: 'event-workflow-action-definition',
26
- criteria: { ownerKey: `app:${app.id}` },
27
- });
28
- }
29
-
30
35
  async deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>) {
31
36
  console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
32
37
 
33
- const identifier = this.getActionDeclarationIdentifier(actionKey, app);
38
+ const identifier = getActionDeclarationIdentifier(actionKey, app);
34
39
  const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
35
40
 
36
41
  if (!existingDefinition) {
@@ -46,7 +51,7 @@ export class ActionsDeployer {
46
51
  configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
47
52
  }
48
53
  const newObject: EventWorkflowActionDefinition = {
49
- identifier: this.getActionDeclarationIdentifier(actionKey, app),
54
+ identifier: getActionDeclarationIdentifier(actionKey, app),
50
55
  name: actionDeclaration.name,
51
56
  ownerKey: `app:${app.id}`,
52
57
  public: app.public, // TODO - an actions visibility is not tied to the visibility of the app
@@ -100,9 +105,6 @@ export class ActionsDeployer {
100
105
  return actionDefinition;
101
106
  }
102
107
 
103
- getActionDeclarationIdentifier(actionKey, app: App) {
104
- return app.identifier + ':' + actionKey;
105
- }
106
108
 
107
109
  async getFunction(actionDeclaration: AppActionDeclaration): Promise<string> {
108
110
  if (!actionDeclaration.handler) {
@@ -4,6 +4,7 @@ import { Auth } from '../../auth/auth';
4
4
  import { ActionsDeployer } from './actions-deployer';
5
5
  import { App, AppDeclaration } from './interfaces';
6
6
  import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
7
+ import { WorkflowDeployer } from './workflow-deployer';
7
8
 
8
9
  export class AppDeployer {
9
10
  public async deploy(appDeclaration: AppDeclaration) {
@@ -16,6 +17,7 @@ export class AppDeployer {
16
17
  app = await this.updateExistingApp(appDeclaration, app);
17
18
  }
18
19
  await new ActionsDeployer().deployActions(appDeclaration, app);
20
+ await new WorkflowDeployer().deployWorkflows(appDeclaration, app);
19
21
  }
20
22
 
21
23
  public async getExistingApp(appDeclaration: AppDeclaration): Promise<App> {
@@ -14,6 +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]: WorkflowDeclaration }
17
18
  }
18
19
 
19
20
  export interface ConfigPropertyElements {
@@ -40,6 +41,31 @@ export interface AppTriggerDeclaration {
40
41
  description?: string;
41
42
  }
42
43
 
44
+ export interface WorkflowDeclaration {
45
+ id?: string;
46
+ identifier: string;
47
+ name: string;
48
+ triggerKey: string;
49
+ workflowDefinition: WorkflowDefinition;
50
+ ownerKey: string;
51
+ isActive: boolean;
52
+ }
53
+
54
+ export interface WorkflowDefinition {
55
+ paths: WorkflowConditional[]
56
+ }
57
+
58
+ export interface WorkflowConditional {
59
+ conditional: string;
60
+ actionDefinitionConfigs: ActionDefinitionConfig[]
61
+ }
62
+ export interface ActionDefinitionConfig {
63
+ name: string;
64
+ action: string;
65
+ config?: {[key: string]: any};
66
+ id?: string;
67
+ }
68
+
43
69
  export interface App {
44
70
  id: string;
45
71
  identifier: string;
@@ -0,0 +1,104 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import { App, AppDeclaration, AppActionDeclaration, WorkflowDeclaration, WorkflowDefinition } 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, appDeclaration.workflows[workflowKey], app, existingWorkflows, appDeclaration);
17
+ }
18
+ }
19
+
20
+ async getWorkflowsForApp(app: App) {
21
+ return await new Entities().get({
22
+ entityName: 'event-workflow-template',
23
+ criteria: { ownerKey: `app:${app.id}` },
24
+ });
25
+ }
26
+
27
+ async deployWorkflow(workflowKey: string, workflow: WorkflowDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration) {
28
+ console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
29
+
30
+ const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
31
+ const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
32
+
33
+ if (existingDefinition) {
34
+ return await this.updateWorkflowDefinition(existingDefinition, workflow, app, appDeclaration);
35
+ }
36
+ return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
37
+ }
38
+
39
+ private async createNewWorkflowDefinition(workflowKey: string, workflowDeclaration: WorkflowDeclaration, app: App, appDeclaration: AppDeclaration) {
40
+ await this.populateActionIds(workflowDeclaration, appDeclaration, app);
41
+ const newObject: WorkflowDeclaration = {
42
+ identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
43
+ name: workflowDeclaration.name,
44
+ ownerKey: `app:${app.id}`,
45
+ triggerKey: workflowDeclaration.triggerKey,
46
+ workflowDefinition: workflowDeclaration.workflowDefinition,
47
+ isActive: workflowDeclaration.isActive
48
+ };
49
+
50
+ const workflowTemplate = await new Entities().create({
51
+ entityName: 'event-workflow-template',
52
+ object: newObject,
53
+ });
54
+
55
+ console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
56
+
57
+ return workflowTemplate;
58
+ }
59
+
60
+ private async populateActionIds(workflowDeclaration: WorkflowDeclaration, appDeclaration: AppDeclaration, app: App){
61
+ let availableAppActions = await getActionsForApp(app);
62
+ if(!workflowDeclaration.workflowDefinition?.paths) {
63
+ return;
64
+ }
65
+ for(const path of workflowDeclaration.workflowDefinition.paths){
66
+ if(!path?.actionDefinitionConfigs) {
67
+ continue;
68
+ }
69
+ for(const actionConfiguration of path.actionDefinitionConfigs) {
70
+ const actionKey = actionConfiguration.action;
71
+ const action = availableAppActions.find(
72
+ action => action.identifier === getActionDeclarationIdentifier(actionKey, app)
73
+ )
74
+ if (!action) {
75
+ throw new Error(`Could not find action ${actionKey} declared in ${workflowDeclaration.name}`);
76
+ }
77
+ actionConfiguration.id = action.id;
78
+ }
79
+ }
80
+ }
81
+
82
+ private async updateWorkflowDefinition(existingWorkflowDefinition: WorkflowDeclaration, workflowDeclaration: WorkflowDeclaration, app: App, appDeclaration: AppDeclaration) {
83
+ await this.populateActionIds(workflowDeclaration, appDeclaration, app);
84
+ const updates = Object.assign(new Object(), {
85
+ name: workflowDeclaration.name,
86
+ triggerKey: workflowDeclaration.triggerKey,
87
+ workflowDefinition: workflowDeclaration.workflowDefinition
88
+ });
89
+
90
+ const updatedWorkflowDefinition = await new Entities().update({
91
+ entityName: 'event-workflow-template',
92
+ id: existingWorkflowDefinition.id,
93
+ object: updates,
94
+ });
95
+
96
+ console.log(`%s Updated existing workflow definition: ${updatedWorkflowDefinition.identifier}`, chalk.yellow.bold('WORKFLOW'));
97
+
98
+ return updatedWorkflowDefinition;
99
+ }
100
+
101
+ getWorkflowDeclarationIdentifier(actionKey, app: App) {
102
+ return app.identifier + ':' + actionKey;
103
+ }
104
+ }