@contrail/cli 1.0.30 → 1.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli.js +7 -1
- package/lib/types/parse-types.d.ts +1 -0
- package/lib/types/parse-types.js +43 -2
- package/package.json +2 -2
- package/src/auth/login.ts +1 -1
- package/src/cli.ts +7 -1
- package/src/types/parse-types.ts +55 -6
- package/lib/apps/deploy-app/docker-action-builder.d.ts +0 -10
- package/lib/apps/deploy-app/docker-action-builder.js +0 -97
- package/lib/apps/deploy-app/interfaces.d.ts +0 -76
- package/lib/apps/deploy-app/interfaces.js +0 -4
- package/lib/apps/deploy-app/workflow-deployer.d.ts +0 -10
- package/lib/apps/deploy-app/workflow-deployer.js +0 -87
package/lib/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { UploadOptionSets } from './types/option-set-uploader';
|
|
|
6
6
|
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
|
-
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
9
|
+
import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles } from './types/parse-types';
|
|
10
10
|
import { loadColors, deleteColors } from './colors/color-loader';
|
|
11
11
|
import { listConfig, removeConfig } from './config/configCommands';
|
|
12
12
|
import { deleteWorkflowTemplate, deployWorkflowTemplate, listWorkflowTemplate } from './workflows/workflowCommands';
|
|
@@ -77,6 +77,10 @@ export async function cli(args) {
|
|
|
77
77
|
ParseTypesFromLocalFiles(args);
|
|
78
78
|
break;
|
|
79
79
|
}
|
|
80
|
+
case 'parseTypesFromTemplateFromLocalFiles': {
|
|
81
|
+
ParseTypesFromTemplateFromLocalFiles(args);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
80
84
|
case 'parseTypesFromFiles': {
|
|
81
85
|
ParseTypesFromFiles(args);
|
|
82
86
|
break;
|
|
@@ -221,6 +225,8 @@ const helpSections = [
|
|
|
221
225
|
'parseOptionSetsLocalFiles <File Paths> Parse CSV files into OptionSets',
|
|
222
226
|
'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
|
|
223
227
|
'. OptionSets from local files.\n',
|
|
228
|
+
'parseTypesFromTemplateFromLocalFiles <File Paths> Parse CSV files into ',
|
|
229
|
+
'. Types and OptionSets from local files.\n',
|
|
224
230
|
'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
|
|
225
231
|
'. OptionSets from VibeIQ Files.\n',
|
|
226
232
|
'mergeOptionSets <File Path> Merge the OptionSets from an existing',
|
package/lib/types/parse-types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetSuggestedTypes } from '@contrail/types';
|
|
1
|
+
import { GetSuggestedTypes, GetTypesFromTemplate } from '@contrail/types';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { getSeparatorByPlatform } from '../common';
|
|
@@ -6,6 +6,7 @@ import * as csvToJson from 'csvtojson';
|
|
|
6
6
|
import { authUser } from '../auth/login';
|
|
7
7
|
import { getCSVFromFile } from './csv-parser';
|
|
8
8
|
const yaml = require('js-yaml');
|
|
9
|
+
// This uses local files to get the data to parse into types
|
|
9
10
|
export async function ParseTypesFromLocalFiles(args) {
|
|
10
11
|
try {
|
|
11
12
|
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
@@ -23,6 +24,7 @@ export async function ParseTypesFromLocalFiles(args) {
|
|
|
23
24
|
}
|
|
24
25
|
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
25
26
|
}
|
|
27
|
+
// This uses VibeIq file ids to get the data to parse into types
|
|
26
28
|
export async function ParseTypesFromFiles(args) {
|
|
27
29
|
try {
|
|
28
30
|
if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
|
|
@@ -40,13 +42,33 @@ export async function ParseTypesFromFiles(args) {
|
|
|
40
42
|
}
|
|
41
43
|
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
42
44
|
}
|
|
45
|
+
// This uses local files to get type template file and the data file to parse into types
|
|
46
|
+
export async function ParseTypesFromTemplateFromLocalFiles(args) {
|
|
47
|
+
try {
|
|
48
|
+
if ((args === null || args === void 0 ? void 0 : args.length) < 5) {
|
|
49
|
+
throw new Error('File names must be included.');
|
|
50
|
+
}
|
|
51
|
+
console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
52
|
+
const templateFileLocation = args[3];
|
|
53
|
+
const dataFileLocation = args[4];
|
|
54
|
+
console.log('Using Template File Location: ', templateFileLocation);
|
|
55
|
+
console.log('Using Data File Location: ', dataFileLocation);
|
|
56
|
+
await parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation);
|
|
57
|
+
console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
64
|
+
}
|
|
43
65
|
async function loadDataFromLocalCSV(fileName) {
|
|
44
66
|
const CURRENT_DIR = process.cwd();
|
|
45
67
|
try {
|
|
46
68
|
const separator = getSeparatorByPlatform();
|
|
47
69
|
const fullPath = CURRENT_DIR + separator + fileName;
|
|
48
70
|
console.log('Getting file from path: ', fullPath);
|
|
49
|
-
const csvData = await csvToJson.default().fromFile(fullPath);
|
|
71
|
+
const csvData = await csvToJson.default({ flatKeys: true }).fromFile(fullPath);
|
|
50
72
|
return csvData;
|
|
51
73
|
}
|
|
52
74
|
catch (e) {
|
|
@@ -72,6 +94,25 @@ async function parseTypesFromLocalFiles(fileLocations) {
|
|
|
72
94
|
saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
|
|
73
95
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
74
96
|
}
|
|
97
|
+
async function parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation) {
|
|
98
|
+
let templateCSVData = [];
|
|
99
|
+
let dataCSVData = [];
|
|
100
|
+
try {
|
|
101
|
+
console.log('Getting template from fileLocation: ', templateFileLocation);
|
|
102
|
+
templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
|
|
103
|
+
console.log(`CSV import was successful. ${templateCSVData === null || templateCSVData === void 0 ? void 0 : templateCSVData.length} rows found.`);
|
|
104
|
+
console.log('Getting data from fileLocation: ', dataFileLocation);
|
|
105
|
+
dataCSVData = await loadDataFromLocalCSV(dataFileLocation);
|
|
106
|
+
console.log(`CSV import was successful. ${dataCSVData === null || dataCSVData === void 0 ? void 0 : dataCSVData.length} rows found.`);
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
console.log('Error importing csv data.', e);
|
|
110
|
+
throw e;
|
|
111
|
+
}
|
|
112
|
+
const types = GetTypesFromTemplate(templateCSVData, dataCSVData);
|
|
113
|
+
saveData({ optionSets: types.OptionSets }, 'parsed_optionSets.yml');
|
|
114
|
+
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
115
|
+
}
|
|
75
116
|
async function parseTypesFromFiles(fileIds) {
|
|
76
117
|
await authUser();
|
|
77
118
|
// get csv data
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "VibeIQ's Contrail Platform CLI.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"license": "ISC",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@contrail/sdk": "^1.0.154",
|
|
27
|
-
"@contrail/types": "^2.0.
|
|
27
|
+
"@contrail/types": "^2.0.69",
|
|
28
28
|
"@contrail/util": "^1.0.17",
|
|
29
29
|
"amazon-cognito-identity-js": "^5.2.3",
|
|
30
30
|
"arg": "^4.0.1",
|
package/src/auth/login.ts
CHANGED
package/src/cli.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { UploadOptionSets } from './types/option-set-uploader';
|
|
|
7
7
|
import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
|
|
8
8
|
import { MergeOptionSets } from './types/option-set-merger';
|
|
9
9
|
import { MergeTypeProperties } from './types/types-properties-merger';
|
|
10
|
-
import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
|
|
10
|
+
import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles } 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';
|
|
@@ -84,6 +84,10 @@ export async function cli(args) {
|
|
|
84
84
|
ParseTypesFromLocalFiles(args);
|
|
85
85
|
break;
|
|
86
86
|
}
|
|
87
|
+
case 'parseTypesFromTemplateFromLocalFiles': {
|
|
88
|
+
ParseTypesFromTemplateFromLocalFiles(args);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
87
91
|
case 'parseTypesFromFiles': {
|
|
88
92
|
ParseTypesFromFiles(args);
|
|
89
93
|
break;
|
|
@@ -235,6 +239,8 @@ const helpSections = [
|
|
|
235
239
|
'parseOptionSetsLocalFiles <File Paths> Parse CSV files into OptionSets',
|
|
236
240
|
'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
|
|
237
241
|
'. OptionSets from local files.\n',
|
|
242
|
+
'parseTypesFromTemplateFromLocalFiles <File Paths> Parse CSV files into ',
|
|
243
|
+
'. Types and OptionSets from local files.\n',
|
|
238
244
|
'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
|
|
239
245
|
'. OptionSets from VibeIQ Files.\n',
|
|
240
246
|
'mergeOptionSets <File Path> Merge the OptionSets from an existing',
|
package/src/types/parse-types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetSuggestedTypes } from '@contrail/types';
|
|
1
|
+
import { GetSuggestedTypes, GetTypesFromTemplate } from '@contrail/types';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { getSeparatorByPlatform } from '../common';
|
|
@@ -8,6 +8,7 @@ import { getCSVFromFile } from './csv-parser';
|
|
|
8
8
|
|
|
9
9
|
const yaml = require('js-yaml');
|
|
10
10
|
|
|
11
|
+
// This uses local files to get the data to parse into types
|
|
11
12
|
export async function ParseTypesFromLocalFiles(args) {
|
|
12
13
|
try {
|
|
13
14
|
if (args?.length < 4) {
|
|
@@ -29,6 +30,7 @@ export async function ParseTypesFromLocalFiles(args) {
|
|
|
29
30
|
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
// This uses VibeIq file ids to get the data to parse into types
|
|
32
34
|
export async function ParseTypesFromFiles(args) {
|
|
33
35
|
try {
|
|
34
36
|
if (args?.length < 4) {
|
|
@@ -50,6 +52,30 @@ export async function ParseTypesFromFiles(args) {
|
|
|
50
52
|
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
// This uses local files to get type template file and the data file to parse into types
|
|
56
|
+
export async function ParseTypesFromTemplateFromLocalFiles(args) {
|
|
57
|
+
try {
|
|
58
|
+
if (args?.length < 5) {
|
|
59
|
+
throw new Error('File names must be included.');
|
|
60
|
+
}
|
|
61
|
+
console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
62
|
+
const templateFileLocation = args[3];
|
|
63
|
+
const dataFileLocation = args[4];
|
|
64
|
+
console.log('Using Template File Location: ', templateFileLocation);
|
|
65
|
+
console.log('Using Data File Location: ', dataFileLocation);
|
|
66
|
+
|
|
67
|
+
await parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation);
|
|
68
|
+
console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
|
|
77
|
+
}
|
|
78
|
+
|
|
53
79
|
async function loadDataFromLocalCSV(fileName) {
|
|
54
80
|
const CURRENT_DIR = process.cwd();
|
|
55
81
|
try {
|
|
@@ -57,7 +83,7 @@ async function loadDataFromLocalCSV(fileName) {
|
|
|
57
83
|
const fullPath = CURRENT_DIR + separator + fileName;
|
|
58
84
|
|
|
59
85
|
console.log('Getting file from path: ', fullPath);
|
|
60
|
-
const csvData = await csvToJson.default().fromFile(fullPath);
|
|
86
|
+
const csvData = await csvToJson.default({flatKeys: true}).fromFile(fullPath);
|
|
61
87
|
|
|
62
88
|
return csvData;
|
|
63
89
|
} catch (e) {
|
|
@@ -84,8 +110,31 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
|
|
|
84
110
|
|
|
85
111
|
console.log(`CSV imports were successful. ${csvJSONData?.length} total rows found.`);
|
|
86
112
|
const suggestions = GetSuggestedTypes(csvJSONData)
|
|
87
|
-
saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
|
|
88
|
-
saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
|
|
113
|
+
saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
|
|
114
|
+
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function parseTypesFromTemplateFromLocalFiles(templateFileLocation: string, dataFileLocation: string) {
|
|
118
|
+
|
|
119
|
+
let templateCSVData: any[] = [];
|
|
120
|
+
let dataCSVData: any[] = [];
|
|
121
|
+
try {
|
|
122
|
+
console.log('Getting template from fileLocation: ', templateFileLocation);
|
|
123
|
+
templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
|
|
124
|
+
console.log(`CSV import was successful. ${templateCSVData?.length} rows found.`);
|
|
125
|
+
|
|
126
|
+
console.log('Getting data from fileLocation: ', dataFileLocation);
|
|
127
|
+
dataCSVData = await loadDataFromLocalCSV(dataFileLocation);
|
|
128
|
+
console.log(`CSV import was successful. ${dataCSVData?.length} rows found.`);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
console.log('Error importing csv data.', e);
|
|
132
|
+
throw e;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const types = GetTypesFromTemplate(templateCSVData, dataCSVData)
|
|
136
|
+
saveData({ optionSets: types.OptionSets }, 'parsed_optionSets.yml');
|
|
137
|
+
saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
|
|
89
138
|
}
|
|
90
139
|
|
|
91
140
|
async function parseTypesFromFiles(fileIds: string[]) {
|
|
@@ -109,8 +158,8 @@ async function parseTypesFromFiles(fileIds: string[]) {
|
|
|
109
158
|
console.log(`CSV downloads were successful. ${csvJSONData?.length} total rows found.`);
|
|
110
159
|
const suggestions = GetSuggestedTypes(csvJSONData)
|
|
111
160
|
|
|
112
|
-
saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
|
|
113
|
-
saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
|
|
161
|
+
saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
|
|
162
|
+
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
114
163
|
}
|
|
115
164
|
|
|
116
165
|
function saveData(data, name) {
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { App, AppDeclaration, AppActionDeclaration } from '../../interfaces';
|
|
2
|
-
export declare class ActionsDeployer {
|
|
3
|
-
deployActions(appDeclaration: AppDeclaration, app: App): Promise<void>;
|
|
4
|
-
getActionsForApp(app: App): Promise<any>;
|
|
5
|
-
deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>): Promise<void>;
|
|
6
|
-
private createNewActionDefinition;
|
|
7
|
-
private updateActionDefinition;
|
|
8
|
-
getActionDeclarationIdentifier(actionKey: any, app: App): string;
|
|
9
|
-
getFunction(actionDeclaration: AppActionDeclaration): Promise<string>;
|
|
10
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { Entities } from '@contrail/sdk';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { ConfigPropertiesParser } from './app-template-parsers';
|
|
4
|
-
import { getSeparatorByPlatform } from '../../common';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
export class ActionsDeployer {
|
|
7
|
-
async deployActions(appDeclaration, app) {
|
|
8
|
-
// FETCH ALL ACTIONS FROM THE API.
|
|
9
|
-
const existingActions = await this.getActionsForApp(app);
|
|
10
|
-
// UPSERT / DELETE BASED ON ACTION IDENTIFIER
|
|
11
|
-
console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
|
|
12
|
-
for (const actionKey of Object.keys(appDeclaration.actions)) {
|
|
13
|
-
await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
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
|
-
async deployAction(actionKey, actionDeclaration, app, existingActions) {
|
|
23
|
-
console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
|
|
24
|
-
const identifier = this.getActionDeclarationIdentifier(actionKey, app);
|
|
25
|
-
const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
|
|
26
|
-
if (!existingDefinition) {
|
|
27
|
-
await this.createNewActionDefinition(actionKey, actionDeclaration, app);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
await this.updateActionDefinition(existingDefinition, actionDeclaration);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async createNewActionDefinition(actionKey, actionDeclaration, app) {
|
|
34
|
-
let configProperties;
|
|
35
|
-
if (actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) {
|
|
36
|
-
configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
|
|
37
|
-
}
|
|
38
|
-
const newObject = {
|
|
39
|
-
identifier: this.getActionDeclarationIdentifier(actionKey, app),
|
|
40
|
-
name: actionDeclaration.name,
|
|
41
|
-
ownerKey: `app:${app.id}`,
|
|
42
|
-
public: app.public,
|
|
43
|
-
configProperties,
|
|
44
|
-
};
|
|
45
|
-
const functionString = await this.getFunction(actionDeclaration);
|
|
46
|
-
if (functionString) {
|
|
47
|
-
newObject.executeFunctionString = functionString;
|
|
48
|
-
}
|
|
49
|
-
const actionDefinition = await new Entities().create({
|
|
50
|
-
entityName: 'event-workflow-action-definition',
|
|
51
|
-
object: newObject,
|
|
52
|
-
});
|
|
53
|
-
console.log(`%s Created new action definition: ${actionKey}`, chalk.yellow.bold('APP'));
|
|
54
|
-
return actionDefinition;
|
|
55
|
-
}
|
|
56
|
-
async updateActionDefinition(existingActionDefinition, actionDeclaration) {
|
|
57
|
-
let configProperties;
|
|
58
|
-
if (actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) {
|
|
59
|
-
configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
|
|
60
|
-
}
|
|
61
|
-
else if (!(actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) && existingActionDefinition.configProperties) {
|
|
62
|
-
configProperties = null;
|
|
63
|
-
}
|
|
64
|
-
const updates = {
|
|
65
|
-
name: actionDeclaration.name,
|
|
66
|
-
// public: actionDeclaration.public, // TODO - an actions visibility is allowed to change
|
|
67
|
-
configProperties,
|
|
68
|
-
};
|
|
69
|
-
const functionString = await this.getFunction(actionDeclaration);
|
|
70
|
-
if (functionString) {
|
|
71
|
-
updates.executeFunctionString = functionString;
|
|
72
|
-
}
|
|
73
|
-
const actionDefinition = await new Entities().update({
|
|
74
|
-
entityName: 'event-workflow-action-definition',
|
|
75
|
-
id: existingActionDefinition.id,
|
|
76
|
-
object: updates,
|
|
77
|
-
});
|
|
78
|
-
console.log(`%s Updated existing action definition: ${actionDefinition.identifier}`, chalk.yellow.bold('APP'));
|
|
79
|
-
return actionDefinition;
|
|
80
|
-
}
|
|
81
|
-
getActionDeclarationIdentifier(actionKey, app) {
|
|
82
|
-
return app.identifier + ':' + actionKey;
|
|
83
|
-
}
|
|
84
|
-
async getFunction(actionDeclaration) {
|
|
85
|
-
if (!actionDeclaration.handler) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
if (!actionDeclaration.handler.endsWith('.js')) {
|
|
89
|
-
throw new Error('Action handler must be a .js file.');
|
|
90
|
-
}
|
|
91
|
-
const CURRENT_DIR = process.cwd();
|
|
92
|
-
const separator = getSeparatorByPlatform();
|
|
93
|
-
const functionLocation = CURRENT_DIR + separator + actionDeclaration.handler;
|
|
94
|
-
const content = fs.readFileSync(functionLocation);
|
|
95
|
-
return content.toString();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
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
|
-
isDockerBased?: boolean;
|
|
22
|
-
}
|
|
23
|
-
export interface ConfigPropertyElements {
|
|
24
|
-
[key: string]: ConfigPropertyElement;
|
|
25
|
-
}
|
|
26
|
-
export interface ConfigPropertyElement {
|
|
27
|
-
propertyType: string;
|
|
28
|
-
options?: any[];
|
|
29
|
-
label: string;
|
|
30
|
-
}
|
|
31
|
-
export interface AppActionDeclaration {
|
|
32
|
-
handler: string;
|
|
33
|
-
name: string;
|
|
34
|
-
description?: string;
|
|
35
|
-
actionConfiguration?: ConfigPropertyElements;
|
|
36
|
-
}
|
|
37
|
-
export interface AppTriggerDeclaration {
|
|
38
|
-
key: string;
|
|
39
|
-
name: string;
|
|
40
|
-
external?: boolean;
|
|
41
|
-
description?: string;
|
|
42
|
-
}
|
|
43
|
-
export interface App {
|
|
44
|
-
id: string;
|
|
45
|
-
identifier: string;
|
|
46
|
-
name: string;
|
|
47
|
-
public: boolean;
|
|
48
|
-
description?: string;
|
|
49
|
-
publisher: string;
|
|
50
|
-
thumbnail: string;
|
|
51
|
-
eventWorkflowTriggerKeyMapping: string;
|
|
52
|
-
configProperties?: ConfigProperty[];
|
|
53
|
-
triggerKeyDefinitions?: TriggerKeyDefinition[];
|
|
54
|
-
}
|
|
55
|
-
export declare class ConfigProperty {
|
|
56
|
-
slug: string;
|
|
57
|
-
propertyType: string;
|
|
58
|
-
options?: any[];
|
|
59
|
-
label: string;
|
|
60
|
-
}
|
|
61
|
-
export interface EventWorkflowActionDefinition {
|
|
62
|
-
id?: string;
|
|
63
|
-
identifier?: string;
|
|
64
|
-
name?: string;
|
|
65
|
-
executeFunctionString?: string;
|
|
66
|
-
ownerKey?: string;
|
|
67
|
-
public?: boolean;
|
|
68
|
-
configProperties?: ConfigProperty[];
|
|
69
|
-
isDockerBased?: boolean;
|
|
70
|
-
}
|
|
71
|
-
export declare class TriggerKeyDefinition {
|
|
72
|
-
name: string;
|
|
73
|
-
description?: string;
|
|
74
|
-
triggerKey: string;
|
|
75
|
-
external?: boolean;
|
|
76
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { App, AppDeclaration, WorkflowTemplateDeclaration } 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: WorkflowTemplateDeclaration, 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
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
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
|
-
supportingAppId: workflowDeclaration.supportingAppId,
|
|
39
|
-
messageGroupId: workflowDeclaration.messageGroupId,
|
|
40
|
-
parallelWorkerCount: workflowDeclaration.parallelWorkerCount,
|
|
41
|
-
};
|
|
42
|
-
const workflowTemplate = await new Entities().create({
|
|
43
|
-
entityName: 'event-workflow-template',
|
|
44
|
-
object: newObject,
|
|
45
|
-
});
|
|
46
|
-
console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
|
|
47
|
-
return workflowTemplate;
|
|
48
|
-
}
|
|
49
|
-
async populateActionIds(workflowDeclaration, appDeclaration, app) {
|
|
50
|
-
var _a;
|
|
51
|
-
let availableAppActions = await getActionsForApp(app);
|
|
52
|
-
if (!((_a = workflowDeclaration.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
for (const path of workflowDeclaration.workflowDefinition.paths) {
|
|
56
|
-
if (!(path === null || path === void 0 ? void 0 : path.actionDefinitionConfigs)) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
for (const actionConfiguration of path.actionDefinitionConfigs) {
|
|
60
|
-
const actionKey = actionConfiguration.action;
|
|
61
|
-
const action = availableAppActions.find(action => action.identifier === getActionDeclarationIdentifier(actionKey, app));
|
|
62
|
-
if (!action) {
|
|
63
|
-
throw new Error(`Could not find action ${actionKey} declared in ${workflowDeclaration.name}`);
|
|
64
|
-
}
|
|
65
|
-
actionConfiguration.id = action.id;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async updateWorkflowDefinition(existingWorkflowDefinition, workflowDeclaration, app, appDeclaration) {
|
|
70
|
-
await this.populateActionIds(workflowDeclaration, appDeclaration, app);
|
|
71
|
-
const updates = Object.assign(new Object(), {
|
|
72
|
-
name: workflowDeclaration.name,
|
|
73
|
-
triggerKey: workflowDeclaration.triggerKey,
|
|
74
|
-
workflowDefinition: workflowDeclaration.workflowDefinition
|
|
75
|
-
});
|
|
76
|
-
const updatedWorkflowDefinition = await new Entities().update({
|
|
77
|
-
entityName: 'event-workflow-template',
|
|
78
|
-
id: existingWorkflowDefinition.id,
|
|
79
|
-
object: updates,
|
|
80
|
-
});
|
|
81
|
-
console.log(`%s Updated existing workflow definition: ${updatedWorkflowDefinition.identifier}`, chalk.yellow.bold('WORKFLOW'));
|
|
82
|
-
return updatedWorkflowDefinition;
|
|
83
|
-
}
|
|
84
|
-
getWorkflowDeclarationIdentifier(actionKey, app) {
|
|
85
|
-
return app.identifier + ':' + actionKey;
|
|
86
|
-
}
|
|
87
|
-
}
|