@contrail/cli 2.0.6 → 2.0.8
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/README.md +14 -12
- package/dist/api/apps.js +1 -0
- package/dist/api/users.d.ts +2 -0
- package/dist/api/users.js +16 -0
- package/dist/commands/groups/export.d.ts +1 -1
- package/dist/commands/groups/export.js +14 -10
- package/dist/commands/groups/upload.js +49 -72
- package/dist/commands/instance/export.js +4 -2
- package/dist/commands/instance/import.js +6 -2
- package/dist/commands/types/getAll.d.ts +1 -1
- package/dist/commands/types/getAll.js +35 -5
- package/dist/commands/types/loadAll.d.ts +1 -1
- package/dist/commands/types/loadAll.js +4 -2
- package/dist/commands/types/uploadTypePropertyPolicies.js +37 -6
- package/dist/commands/users/export.d.ts +1 -1
- package/dist/commands/users/export.js +4 -6
- package/dist/helpers/file-helpers.js +1 -1
- package/dist/helpers/workflow-template-definitions/workflow-template-definition-deployer.js +2 -0
- package/dist/helpers/workflow-templates/helper.js +7 -2
- package/dist/interface-converters.d.ts +3 -0
- package/dist/interface-converters.js +11 -0
- package/dist/interface-converters.spec.d.ts +1 -0
- package/dist/interface-converters.spec.js +89 -0
- package/dist/interfaces.d.ts +4 -0
- package/dist/templates/typescript/app.yml +1 -0
- package/oclif.manifest.json +10 -7
- package/package.json +21 -7
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ $ npm install -g @contrail/cli
|
|
|
15
15
|
$ contrail COMMAND
|
|
16
16
|
running command...
|
|
17
17
|
$ contrail (--version)
|
|
18
|
-
@contrail/cli/2.0.
|
|
18
|
+
@contrail/cli/2.0.8 darwin-arm64 node-v18.13.0
|
|
19
19
|
$ contrail --help [COMMAND]
|
|
20
20
|
USAGE
|
|
21
21
|
$ contrail COMMAND
|
|
@@ -331,11 +331,11 @@ Export all groups in the org.
|
|
|
331
331
|
|
|
332
332
|
```
|
|
333
333
|
USAGE
|
|
334
|
-
$ contrail groups export [-
|
|
334
|
+
$ contrail groups export [-f <value>] [--overwrite]
|
|
335
335
|
|
|
336
336
|
FLAGS
|
|
337
|
-
-
|
|
338
|
-
--overwrite
|
|
337
|
+
-f, --outFile=<value> [default: groups.yml] The location for the file to be saved
|
|
338
|
+
--overwrite Replaces existing files if they exist
|
|
339
339
|
|
|
340
340
|
DESCRIPTION
|
|
341
341
|
Export all groups in the org.
|
|
@@ -388,11 +388,12 @@ Exports an data of an instance including types and users
|
|
|
388
388
|
|
|
389
389
|
```
|
|
390
390
|
USAGE
|
|
391
|
-
$ contrail instance export [
|
|
391
|
+
$ contrail instance export [-d <value>] [-f]
|
|
392
392
|
|
|
393
393
|
FLAGS
|
|
394
|
-
--outDir=<value> [default: .] The directory to which to export the instance data. Defaults to the current
|
|
395
|
-
|
|
394
|
+
-d, --outDir=<value> [default: .] The directory to which to export the instance data. Defaults to the current
|
|
395
|
+
directory
|
|
396
|
+
-f, --overwrite Replaces any existing export files in outDir
|
|
396
397
|
|
|
397
398
|
DESCRIPTION
|
|
398
399
|
Exports an data of an instance including types and users
|
|
@@ -407,10 +408,11 @@ Import the data to an instance, including types and users
|
|
|
407
408
|
|
|
408
409
|
```
|
|
409
410
|
USAGE
|
|
410
|
-
$ contrail instance import [
|
|
411
|
+
$ contrail instance import [-d <value>]
|
|
411
412
|
|
|
412
413
|
FLAGS
|
|
413
|
-
--dir=<value> [default: .] The directory from which to export the instance data. Defaults to the current
|
|
414
|
+
-d, --dir=<value> [default: .] The directory from which to export the instance data. Defaults to the current
|
|
415
|
+
directory
|
|
414
416
|
|
|
415
417
|
DESCRIPTION
|
|
416
418
|
Import the data to an instance, including types and users
|
|
@@ -1088,11 +1090,11 @@ Export all users in the org.
|
|
|
1088
1090
|
|
|
1089
1091
|
```
|
|
1090
1092
|
USAGE
|
|
1091
|
-
$ contrail users export [-
|
|
1093
|
+
$ contrail users export [-f <value>] [--overwrite]
|
|
1092
1094
|
|
|
1093
1095
|
FLAGS
|
|
1094
|
-
-
|
|
1095
|
-
--overwrite
|
|
1096
|
+
-f, --outFile=<value> [default: users.yml] The location for the file to be saved
|
|
1097
|
+
--overwrite Replaces existing files if they exist
|
|
1096
1098
|
|
|
1097
1099
|
DESCRIPTION
|
|
1098
1100
|
Export all users in the org.
|
package/dist/api/apps.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getGroups = exports.getUserOrgs = void 0;
|
|
4
|
+
const sdk_1 = require("@contrail/sdk");
|
|
5
|
+
async function getUserOrgs(options) {
|
|
6
|
+
return new sdk_1.Entities().get({
|
|
7
|
+
entityName: 'user-org', ...options
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
exports.getUserOrgs = getUserOrgs;
|
|
11
|
+
async function getGroups(options) {
|
|
12
|
+
return new sdk_1.Entities().get({
|
|
13
|
+
entityName: 'group', ...options
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
exports.getGroups = getGroups;
|
|
@@ -4,7 +4,7 @@ export default class ExportGroups extends Command {
|
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
|
-
|
|
7
|
+
outFile: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
8
|
overwrite: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
};
|
|
10
10
|
run(): Promise<void>;
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.exportGroups = exports.DEFAULT_FILE_LOCATION = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
|
-
const sdk_1 = require("@contrail/sdk");
|
|
7
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
7
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
9
8
|
const login_1 = require("../../auth/login");
|
|
10
9
|
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
11
10
|
const core_1 = require("@oclif/core");
|
|
12
11
|
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
12
|
+
const users_1 = require("../../api/users");
|
|
13
13
|
exports.DEFAULT_FILE_LOCATION = 'groups.yml';
|
|
14
14
|
class ExportGroups extends core_1.Command {
|
|
15
15
|
async run() {
|
|
@@ -18,7 +18,7 @@ class ExportGroups extends core_1.Command {
|
|
|
18
18
|
try {
|
|
19
19
|
await (0, login_1.authUser)();
|
|
20
20
|
this.log('%s Getting Groups.', chalk_1.default.blue.bold('START'));
|
|
21
|
-
await exportGroups((_a = flags.
|
|
21
|
+
await exportGroups((_a = flags.outFile) !== null && _a !== void 0 ? _a : exports.DEFAULT_FILE_LOCATION, flags.overwrite);
|
|
22
22
|
this.log('%s Done', chalk_1.default.yellow.bold('GROUPS'));
|
|
23
23
|
}
|
|
24
24
|
catch (e) {
|
|
@@ -35,16 +35,12 @@ ExportGroups.examples = [
|
|
|
35
35
|
`,
|
|
36
36
|
];
|
|
37
37
|
ExportGroups.flags = {
|
|
38
|
-
|
|
38
|
+
outFile: core_1.Flags.string({ char: 'f', description: 'The location for the file to be saved', required: false, default: exports.DEFAULT_FILE_LOCATION }),
|
|
39
39
|
overwrite: core_1.Flags.boolean({ description: 'Replaces existing files if they exist', required: false, default: false })
|
|
40
40
|
};
|
|
41
41
|
async function exportGroups(fileLocation, overwrite) {
|
|
42
|
-
const allGroups = await
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
const allUsersInOrg = await new sdk_1.Entities().get({
|
|
46
|
-
entityName: 'user-org',
|
|
47
|
-
});
|
|
42
|
+
const allGroups = await (0, users_1.getGroups)({ relations: ['groupPrincipals'] });
|
|
43
|
+
const allUsersInOrg = await (0, users_1.getUserOrgs)();
|
|
48
44
|
const groups = [];
|
|
49
45
|
for (const group of allGroups) {
|
|
50
46
|
const groupPrincipals = getGroupPrincipals(group, allGroups, allUsersInOrg);
|
|
@@ -53,19 +49,26 @@ async function exportGroups(fileLocation, overwrite) {
|
|
|
53
49
|
groupPrincipals,
|
|
54
50
|
});
|
|
55
51
|
}
|
|
52
|
+
console.log("saving groups:", JSON.stringify(groups));
|
|
56
53
|
await saveData(groups, fileLocation, overwrite);
|
|
57
54
|
}
|
|
58
55
|
exports.exportGroups = exportGroups;
|
|
59
56
|
async function saveData(data, fileLocation, overwrite) {
|
|
60
57
|
const yamlStr = js_yaml_1.default.dump(data);
|
|
58
|
+
console.log("file location:", fileLocation);
|
|
59
|
+
console.log("final yml string:", yamlStr);
|
|
61
60
|
const CURRENT_DIR = process.cwd();
|
|
62
|
-
const pathToWrite = path.
|
|
61
|
+
const pathToWrite = path.join(CURRENT_DIR, fileLocation);
|
|
63
62
|
if (fs_1.default.existsSync(pathToWrite)) {
|
|
64
63
|
await (0, file_helpers_1.safeFileOverwrite)(pathToWrite, overwrite);
|
|
65
64
|
}
|
|
66
65
|
fs_1.default.writeFileSync(pathToWrite, yamlStr, 'utf8');
|
|
67
66
|
}
|
|
68
67
|
function getGroupPrincipals(group, allGroups, orgUsers) {
|
|
68
|
+
if (!(group === null || group === void 0 ? void 0 : group.groupPrincipals)) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
console.log("all groups:", allGroups.map(x => x.id));
|
|
69
72
|
const principals = [];
|
|
70
73
|
for (const principal of group.groupPrincipals) {
|
|
71
74
|
const [type, id] = principal.principalReference.split(':');
|
|
@@ -83,6 +86,7 @@ function getGroupPrincipals(group, allGroups, orgUsers) {
|
|
|
83
86
|
}
|
|
84
87
|
else if (type === 'group') {
|
|
85
88
|
const nestedGroup = allGroups.find(x => x.id === id);
|
|
89
|
+
console.log("looking for group", id);
|
|
86
90
|
principals.push({
|
|
87
91
|
type: 'group',
|
|
88
92
|
name: nestedGroup.name
|
|
@@ -56,12 +56,12 @@ async function uploadGroups(fileLocation) {
|
|
|
56
56
|
});
|
|
57
57
|
const toDelete = existingGroups.filter(x => !groupsToImport.map(y => y.name).includes(x.name));
|
|
58
58
|
const toCreate = groupsToImport.filter(x => !existingGroups.map(y => y.name).includes(x.name));
|
|
59
|
-
const toUpdate =
|
|
59
|
+
const toUpdate = groupsToImport.filter(x => existingGroups.map(y => y.name).includes(x.name));
|
|
60
60
|
const createdGroups = [];
|
|
61
61
|
// it's important to create all the groups first, to resolve any downstream principal dependencies
|
|
62
62
|
for (const group of toCreate) {
|
|
63
63
|
if (!group.groupPrincipals || !group.name) {
|
|
64
|
-
console.log('skipping invalid group');
|
|
64
|
+
console.log('skipping create of invalid group');
|
|
65
65
|
}
|
|
66
66
|
createdGroups.push(await new sdk_1.Entities().create({
|
|
67
67
|
entityName: 'group', object: { name: group.name }
|
|
@@ -77,90 +77,67 @@ async function uploadGroups(fileLocation) {
|
|
|
77
77
|
}
|
|
78
78
|
for (const group of toUpdate) {
|
|
79
79
|
if (!group.groupPrincipals || !group.name) {
|
|
80
|
-
console.log('skipping invalid group');
|
|
80
|
+
console.log('skipping update invalid group');
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
const existingGroup = existingGroups.find(x => x.name === group.name);
|
|
83
|
+
await updateGroup(group.groupPrincipals, orgUsers, existingGroup, allGroupsAfterCreate);
|
|
83
84
|
}
|
|
84
85
|
for (const group of toDelete) {
|
|
85
86
|
if (!group.groupPrincipals || !group.name) {
|
|
86
|
-
console.log('skipping invalid group');
|
|
87
|
+
console.log('skipping delete of invalid group');
|
|
87
88
|
}
|
|
88
89
|
await new sdk_1.Entities().delete({ entityName: 'group', id: group.id });
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
exports.uploadGroups = uploadGroups;
|
|
92
93
|
async function updateGroup(principals, orgUsers, existingGroup, allGroupsAfterCreate) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
await new sdk_1.Entities().update({
|
|
105
|
-
entityName: 'group-principal', object: {
|
|
106
|
-
principalReference: `user:${user.id}`,
|
|
107
|
-
groupId: existingGroup.id
|
|
108
|
-
}
|
|
109
|
-
});
|
|
94
|
+
var _a;
|
|
95
|
+
const principalsToUpdate = principals
|
|
96
|
+
.map(x => groupPrincipalNameToId(x, allGroupsAfterCreate, orgUsers))
|
|
97
|
+
.filter(x => !!x)
|
|
98
|
+
.map(x => { return { principalReference: `${x.type}:${x.identifier}`, groupId: existingGroup.id }; });
|
|
99
|
+
await new sdk_1.Entities().batchCreate({
|
|
100
|
+
entityName: 'group-principal', objects: {
|
|
101
|
+
principalReferences: principalsToUpdate.map(x => x.principalReference),
|
|
102
|
+
groupIds: [existingGroup.id]
|
|
110
103
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
groupId: existingGroup.id
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
104
|
+
});
|
|
105
|
+
// remove principals
|
|
106
|
+
const principalsToKeep = principalsToUpdate.map(principal => `${principal.type}:${principal.identifier}`);
|
|
107
|
+
const principalsToDelete = ((_a = existingGroup === null || existingGroup === void 0 ? void 0 : existingGroup.groupPrincipals) !== null && _a !== void 0 ? _a : [])
|
|
108
|
+
.map(x => groupPrincipalNameToId(x, allGroupsAfterCreate, orgUsers))
|
|
109
|
+
.filter(x => !!x)
|
|
110
|
+
.filter(x => !principalsToKeep.includes(`${x.type}:${x.identifier}`));
|
|
111
|
+
await principalsToDelete.forEach(async (principal) => {
|
|
112
|
+
await new sdk_1.Entities().delete({
|
|
113
|
+
entityName: 'group-principal', id: principal.cloudId
|
|
114
|
+
});
|
|
115
|
+
});
|
|
128
116
|
}
|
|
129
117
|
async function createGroupPrincipals(group, principals, orgUsers, allGroupsAfterCreate) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
catch (e) {
|
|
145
|
-
console.log('could not create group principal');
|
|
146
|
-
}
|
|
118
|
+
const principalsToCreate = principals
|
|
119
|
+
.map(x => groupPrincipalNameToId(x, allGroupsAfterCreate, orgUsers))
|
|
120
|
+
.filter(x => !!x)
|
|
121
|
+
.map(x => { return { principalReference: `${x.type}:${x.identifier}`, groupId: group.id }; });
|
|
122
|
+
await new sdk_1.Entities().batchCreate({
|
|
123
|
+
entityName: 'group-principal', objects: principalsToCreate
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function groupPrincipalNameToId(principal, groups, orgUsers) {
|
|
127
|
+
if (principal.type === 'user') {
|
|
128
|
+
const user = orgUsers.map(x => x.user).find(x => x.email === (principal === null || principal === void 0 ? void 0 : principal.email));
|
|
129
|
+
if (!user) {
|
|
130
|
+
console.log(`user ${principal.email} is not in this org's user list`);
|
|
131
|
+
return undefined;
|
|
147
132
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
entityName: 'group-principal', object: {
|
|
156
|
-
principalReference: `group:${nestedGroup.id}`,
|
|
157
|
-
groupId: group.id
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
catch (e) {
|
|
162
|
-
console.log('could not create nested group');
|
|
163
|
-
}
|
|
133
|
+
return { type: 'user', identifier: user.id, cloudId: principal.id };
|
|
134
|
+
}
|
|
135
|
+
else if (principal.type === 'group') {
|
|
136
|
+
const group = groups.find(x => x.name === principal.name);
|
|
137
|
+
if (!group) {
|
|
138
|
+
console.log(`group ${principal.name} is not in this org's group list`);
|
|
139
|
+
return undefined;
|
|
164
140
|
}
|
|
141
|
+
return { type: 'group', identifier: group.id, cloudId: principal.id };
|
|
165
142
|
}
|
|
166
143
|
}
|
|
@@ -5,11 +5,13 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const getAll_1 = require("../types/getAll");
|
|
7
7
|
const export_1 = require("../users/export");
|
|
8
|
+
const export_2 = require("../groups/export");
|
|
8
9
|
class ExportInstance extends core_1.Command {
|
|
9
10
|
async run() {
|
|
10
11
|
const { flags } = await this.parse(ExportInstance);
|
|
11
12
|
await (0, getAll_1.getAll)(flags.outDir, flags.overwrite);
|
|
12
13
|
await (0, export_1.exportUsers)(path.join(flags.outDir, 'users.yml'), flags.overwrite);
|
|
14
|
+
await (0, export_2.exportGroups)(path.join(flags.outDir, 'groups.yml'), flags.overwrite);
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
exports.default = ExportInstance;
|
|
@@ -19,6 +21,6 @@ ExportInstance.examples = [
|
|
|
19
21
|
`,
|
|
20
22
|
];
|
|
21
23
|
ExportInstance.flags = {
|
|
22
|
-
outDir: core_1.Flags.string({ description: 'The directory to which to export the instance data. Defaults to the current directory', required: false, default: '.' }),
|
|
23
|
-
overwrite: core_1.Flags.boolean({ description: 'Replaces any existing export files in outDir', required: false, default: false })
|
|
24
|
+
outDir: core_1.Flags.string({ char: 'd', description: 'The directory to which to export the instance data. Defaults to the current directory', required: false, default: '.' }),
|
|
25
|
+
overwrite: core_1.Flags.boolean({ char: 'f', description: 'Replaces any existing export files in outDir', required: false, default: false })
|
|
24
26
|
};
|
|
@@ -5,11 +5,15 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const loadAll_1 = require("../types/loadAll");
|
|
7
7
|
const upload_1 = require("../users/upload");
|
|
8
|
+
const upload_2 = require("../groups/upload");
|
|
9
|
+
const uploadTypePropertyPolicies_1 = require("../types/uploadTypePropertyPolicies");
|
|
8
10
|
class ImportInstance extends core_1.Command {
|
|
9
11
|
async run() {
|
|
10
12
|
const { flags } = await this.parse(ImportInstance);
|
|
11
|
-
await (0, loadAll_1.loadAll)(flags.dir);
|
|
13
|
+
await (0, loadAll_1.loadAll)(flags.dir, true);
|
|
12
14
|
await (0, upload_1.uploadUsers)(path.join(flags.dir, 'users.yml'));
|
|
15
|
+
await (0, upload_2.uploadGroups)(path.join(flags.dir, 'groups.yml'));
|
|
16
|
+
await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(flags.dir);
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
exports.default = ImportInstance;
|
|
@@ -19,5 +23,5 @@ ImportInstance.examples = [
|
|
|
19
23
|
`,
|
|
20
24
|
];
|
|
21
25
|
ImportInstance.flags = {
|
|
22
|
-
dir: core_1.Flags.string({ description: 'The directory from which to export the instance data. Defaults to the current directory', required: false, default: '.' }),
|
|
26
|
+
dir: core_1.Flags.string({ char: 'd', description: 'The directory from which to export the instance data. Defaults to the current directory', required: false, default: '.' }),
|
|
23
27
|
};
|
|
@@ -30,4 +30,4 @@ export default class GetAllTypes extends Command {
|
|
|
30
30
|
}
|
|
31
31
|
export declare function getAll(outDir: string, overwrite: boolean): Promise<void>;
|
|
32
32
|
export declare function reduceTypes(dataHolder: DataHolder): any[];
|
|
33
|
-
export declare function reduceData(data: DataHolder): ReducedDataHolder
|
|
33
|
+
export declare function reduceData(data: DataHolder): Promise<ReducedDataHolder>;
|
|
@@ -10,6 +10,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
10
10
|
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
11
11
|
const types_1 = require("../../api/types");
|
|
12
12
|
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
13
|
+
const users_1 = require("../../api/users");
|
|
13
14
|
const yaml = require('js-yaml');
|
|
14
15
|
class GetAllTypes extends core_1.Command {
|
|
15
16
|
async run() {
|
|
@@ -45,7 +46,7 @@ async function getAll(outDir, overwrite) {
|
|
|
45
46
|
typePropertyPolicies: await (0, types_1.getTypePropertyPolicies)(),
|
|
46
47
|
typePropertyPolicyLinks: await (0, types_1.getTypePropertyPolicyLinks)(),
|
|
47
48
|
};
|
|
48
|
-
const reducedData = reduceData(data);
|
|
49
|
+
const reducedData = await reduceData(data);
|
|
49
50
|
await saveData(reducedData, outDir, overwrite);
|
|
50
51
|
console.log('%s Retrieved', chalk_1.default.yellow.bold('TYPES'));
|
|
51
52
|
}
|
|
@@ -56,14 +57,43 @@ async function getAll(outDir, overwrite) {
|
|
|
56
57
|
console.log('%s Types Retrieval Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
57
58
|
}
|
|
58
59
|
exports.getAll = getAll;
|
|
59
|
-
function reduceTypePropertyPolicies(data) {
|
|
60
|
+
async function reduceTypePropertyPolicies(data) {
|
|
60
61
|
var _a;
|
|
62
|
+
const orgUsers = await (0, users_1.getUserOrgs)();
|
|
63
|
+
const groups = await (0, users_1.getGroups)();
|
|
64
|
+
function reducePrincipal(statement) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if (!(statement === null || statement === void 0 ? void 0 : statement.principal)) {
|
|
67
|
+
return statement;
|
|
68
|
+
}
|
|
69
|
+
const [type, id] = statement.principal.split(':');
|
|
70
|
+
if (!type || !id) {
|
|
71
|
+
return statement;
|
|
72
|
+
}
|
|
73
|
+
if (type === 'group') {
|
|
74
|
+
const groupName = (_a = groups.find(x => x.id === id)) === null || _a === void 0 ? void 0 : _a.name;
|
|
75
|
+
if (!groupName) {
|
|
76
|
+
console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
|
|
77
|
+
return statement;
|
|
78
|
+
}
|
|
79
|
+
statement.principal = `group:${groupName}`;
|
|
80
|
+
}
|
|
81
|
+
else if (type === 'user') {
|
|
82
|
+
const userEmail = (_b = orgUsers.find(x => x.user.id === id)) === null || _b === void 0 ? void 0 : _b.email;
|
|
83
|
+
if (!userEmail) {
|
|
84
|
+
console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
|
|
85
|
+
return statement;
|
|
86
|
+
}
|
|
87
|
+
statement.principal = `user:${userEmail}`;
|
|
88
|
+
}
|
|
89
|
+
return statement;
|
|
90
|
+
}
|
|
61
91
|
return (_a = data === null || data === void 0 ? void 0 : data.typePropertyPolicies) === null || _a === void 0 ? void 0 : _a.map(x => {
|
|
62
92
|
return {
|
|
63
93
|
label: x.label,
|
|
64
94
|
policy: {
|
|
65
95
|
version: x.policy.version,
|
|
66
|
-
statements: x.policy.statements,
|
|
96
|
+
statements: x.policy.statements.map(x => reducePrincipal(x)),
|
|
67
97
|
}
|
|
68
98
|
};
|
|
69
99
|
});
|
|
@@ -195,7 +225,7 @@ function reduceTypes(dataHolder) {
|
|
|
195
225
|
return reducedTypes;
|
|
196
226
|
}
|
|
197
227
|
exports.reduceTypes = reduceTypes;
|
|
198
|
-
function reduceData(data) {
|
|
228
|
+
async function reduceData(data) {
|
|
199
229
|
return {
|
|
200
230
|
reducedTypes: reduceTypes(data),
|
|
201
231
|
reducedOptionSets: reduceOptionSets(data),
|
|
@@ -203,7 +233,7 @@ function reduceData(data) {
|
|
|
203
233
|
reducedRuleSets: reduceRuleSets(data),
|
|
204
234
|
reducedRuleSetLinks: reduceRuleSetLinks(data),
|
|
205
235
|
reducedUsageInfo: reduceUsageInfo(data),
|
|
206
|
-
reducedTypePropertyPolicies: reduceTypePropertyPolicies(data),
|
|
236
|
+
reducedTypePropertyPolicies: await reduceTypePropertyPolicies(data),
|
|
207
237
|
reducedTypePropertyPolicyLinks: reduceTypePropertyPolicyLinks(data),
|
|
208
238
|
};
|
|
209
239
|
}
|
|
@@ -26,7 +26,7 @@ LoadAllTypes.examples = [
|
|
|
26
26
|
LoadAllTypes.flags = {
|
|
27
27
|
dir: core_1.Flags.string({ char: 'd', description: 'The directory from which to load the types data. Defaults to the current directory.', required: false, default: '.' }),
|
|
28
28
|
};
|
|
29
|
-
async function loadAll(dir) {
|
|
29
|
+
async function loadAll(dir, skipPolicies = false) {
|
|
30
30
|
try {
|
|
31
31
|
await (0, login_1.authUser)();
|
|
32
32
|
await (0, uploadOptionSets_1.uploadOptionSets)(dir);
|
|
@@ -34,7 +34,9 @@ async function loadAll(dir) {
|
|
|
34
34
|
await (0, type_uploader_1.uploadTypes)(dir);
|
|
35
35
|
await (0, uploadUsageInfo_1.uploadUsageInfo)(dir);
|
|
36
36
|
await (0, uploadRuleSets_1.uploadRuleSets)(dir);
|
|
37
|
-
|
|
37
|
+
if (!skipPolicies) {
|
|
38
|
+
await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(dir);
|
|
39
|
+
}
|
|
38
40
|
}
|
|
39
41
|
catch (e) {
|
|
40
42
|
console.log(`%s Types Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
@@ -9,6 +9,7 @@ const login_1 = require("../../auth/login");
|
|
|
9
9
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
10
10
|
const core_1 = require("@oclif/core");
|
|
11
11
|
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
12
|
+
const users_1 = require("../../api/users");
|
|
12
13
|
const yaml = require('js-yaml');
|
|
13
14
|
class UploadTypePropertyPolicies extends core_1.Command {
|
|
14
15
|
async run() {
|
|
@@ -58,6 +59,42 @@ function loadTPPolicies(fromDir) {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
62
|
+
const orgUsers = await (0, users_1.getUserOrgs)();
|
|
63
|
+
const groups = await (0, users_1.getGroups)();
|
|
64
|
+
function fillPrincipal(statement) {
|
|
65
|
+
const principal = statement === null || statement === void 0 ? void 0 : statement.principal;
|
|
66
|
+
if (!principal) {
|
|
67
|
+
console.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
68
|
+
return statement;
|
|
69
|
+
}
|
|
70
|
+
const [type, identifier] = principal.split(':');
|
|
71
|
+
if (!type || !identifier) {
|
|
72
|
+
console.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
|
|
73
|
+
return statement;
|
|
74
|
+
}
|
|
75
|
+
if (type === 'group') {
|
|
76
|
+
const group = groups.find(x => x.name === identifier);
|
|
77
|
+
if (!group) {
|
|
78
|
+
console.log(`Could not find group ${identifier}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
statement.principal = `group:${group.id}`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (type === 'user') {
|
|
85
|
+
const orgUser = orgUsers.find(x => x.user.email === identifier);
|
|
86
|
+
if (!orgUser) {
|
|
87
|
+
console.log(`Could not find user ${identifier}`);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
statement.principal = `user:${orgUser.user.id}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return statement;
|
|
94
|
+
}
|
|
95
|
+
reducedTypePropertyPolicies.forEach(policy => {
|
|
96
|
+
policy.policy.statements = policy.policy.statements.map(x => fillPrincipal(x));
|
|
97
|
+
});
|
|
61
98
|
const currentTPPolicies = await new sdk_1.Entities().get({
|
|
62
99
|
entityName: 'type-property-policy',
|
|
63
100
|
});
|
|
@@ -69,8 +106,6 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
69
106
|
for (const loadedTPP of reducedTypePropertyPolicies) {
|
|
70
107
|
loadedTPPByName[loadedTPP.label] = loadedTPP;
|
|
71
108
|
}
|
|
72
|
-
// console.debug('current tp policy:', currentTPPolicies);
|
|
73
|
-
// console.debug('reduced tp policy:', reducedTypePropertyPolicies);
|
|
74
109
|
for (const [label, loadedTPP] of Object.entries(loadedTPPByName)) {
|
|
75
110
|
try {
|
|
76
111
|
const found = currentTPPByLabel[label];
|
|
@@ -137,8 +172,6 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
137
172
|
const hash = `${loadedLink.typePropertySlug}|${loadedLink.typePropertyPolicyLabel}`;
|
|
138
173
|
reducedLinksByHashes[hash] = loadedLink;
|
|
139
174
|
}
|
|
140
|
-
console.debug('current type property policy links:', currentLinksHashes);
|
|
141
|
-
console.debug('reduced type property policy links:', reducedLinksByHashes);
|
|
142
175
|
for (const loadedTPPLink of reducedTypePropertyPolicyLinks) {
|
|
143
176
|
try {
|
|
144
177
|
const found = currentLinksHashes[`${loadedTPPLink.typePropertySlug}|${loadedTPPLink.typePropertyPolicyLabel}`];
|
|
@@ -146,7 +179,6 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
146
179
|
if (!transformReducedLink(loadedTPPLink, typeProperties, currentTPPs)) {
|
|
147
180
|
continue;
|
|
148
181
|
}
|
|
149
|
-
console.log('Creating: ', loadedTPPLink);
|
|
150
182
|
await new sdk_1.Entities().create({
|
|
151
183
|
entityName: 'type-property-policy-link',
|
|
152
184
|
object: {
|
|
@@ -159,7 +191,6 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
159
191
|
if (!transformReducedLink(loadedTPPLink, typeProperties, currentTPPs)) {
|
|
160
192
|
continue;
|
|
161
193
|
}
|
|
162
|
-
console.log('skipping existing link: ', loadedTPPLink);
|
|
163
194
|
}
|
|
164
195
|
}
|
|
165
196
|
catch (err) {
|
|
@@ -4,7 +4,7 @@ export default class ExportUsers extends Command {
|
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
|
-
|
|
7
|
+
outFile: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
8
|
overwrite: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
};
|
|
10
10
|
run(): Promise<void>;
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.exportUsers = exports.DEFAULT_FILE_LOCATION = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
|
-
const sdk_1 = require("@contrail/sdk");
|
|
7
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
7
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
9
8
|
const login_1 = require("../../auth/login");
|
|
10
9
|
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
11
10
|
const core_1 = require("@oclif/core");
|
|
12
11
|
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
12
|
+
const users_1 = require("../../api/users");
|
|
13
13
|
exports.DEFAULT_FILE_LOCATION = 'users.yml';
|
|
14
14
|
class ExportUsers extends core_1.Command {
|
|
15
15
|
async run() {
|
|
@@ -18,7 +18,7 @@ class ExportUsers extends core_1.Command {
|
|
|
18
18
|
try {
|
|
19
19
|
await (0, login_1.authUser)();
|
|
20
20
|
this.log('%s Getting Users.', chalk_1.default.blue.bold('START'));
|
|
21
|
-
await exportUsers((_a = flags.
|
|
21
|
+
await exportUsers((_a = flags.outFile) !== null && _a !== void 0 ? _a : exports.DEFAULT_FILE_LOCATION, flags.overwrite);
|
|
22
22
|
this.log('%s Done', chalk_1.default.yellow.bold('USERS'));
|
|
23
23
|
}
|
|
24
24
|
catch (e) {
|
|
@@ -35,13 +35,11 @@ ExportUsers.examples = [
|
|
|
35
35
|
`,
|
|
36
36
|
];
|
|
37
37
|
ExportUsers.flags = {
|
|
38
|
-
|
|
38
|
+
outFile: core_1.Flags.string({ char: 'f', description: 'The location for the file to be saved', required: false, default: exports.DEFAULT_FILE_LOCATION }),
|
|
39
39
|
overwrite: core_1.Flags.boolean({ description: 'Replaces existing files if they exist', required: false, default: false })
|
|
40
40
|
};
|
|
41
41
|
async function exportUsers(fileLocation, overwrite) {
|
|
42
|
-
const allUsersInOrg = await
|
|
43
|
-
entityName: 'user-org',
|
|
44
|
-
});
|
|
42
|
+
const allUsersInOrg = await (0, users_1.getUserOrgs)();
|
|
45
43
|
const users = [];
|
|
46
44
|
for (const userInOrg of allUsersInOrg) {
|
|
47
45
|
delete userInOrg.user.id;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.safeFileOverwrite = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
6
|
-
const PASS_FORCE_TO_OVERWRITE = 'Pass --
|
|
6
|
+
const PASS_FORCE_TO_OVERWRITE = 'Pass --overwrite to overwrite without prompting';
|
|
7
7
|
//throws an error if the user declines to overwrite the file
|
|
8
8
|
async function safeFileOverwrite(fileLocation, overwrite) {
|
|
9
9
|
if (overwrite) {
|
|
@@ -8,6 +8,7 @@ const apps_1 = require("../../api/apps");
|
|
|
8
8
|
const event_workflow_templates_1 = require("../../api/event-workflow-templates");
|
|
9
9
|
const event_workflow_template_definition_1 = require("../../api/event-workflow-template-definition");
|
|
10
10
|
const actions_deployer_1 = require("../app/actions-deployer");
|
|
11
|
+
const interface_converters_1 = require("../../interface-converters");
|
|
11
12
|
class WorkflowTemplateDefinitionDeployer {
|
|
12
13
|
async cliInstallWorkflowTemplateDefinitions() {
|
|
13
14
|
const installedApps = await (0, apps_1.getInstalledApps)();
|
|
@@ -94,6 +95,7 @@ class WorkflowTemplateDefinitionDeployer {
|
|
|
94
95
|
console.log(`%s \tDeploying workflow definitions: ${workflowKey}`, chalk_1.default.yellow.bold('WORKFLOW DEFINITION'));
|
|
95
96
|
const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
|
|
96
97
|
const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
98
|
+
(0, interface_converters_1.convertWorkflow)(workflow);
|
|
97
99
|
if (existingDefinition) {
|
|
98
100
|
return await this.updateWorkflowTemplateDefinition(existingDefinition, workflow, app);
|
|
99
101
|
}
|
|
@@ -9,6 +9,7 @@ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
|
9
9
|
const event_workflow_action_definition_1 = require("../../api/event-workflow-action-definition");
|
|
10
10
|
const event_workflow_templates_1 = require("../../api/event-workflow-templates");
|
|
11
11
|
const login_1 = require("../../auth/login");
|
|
12
|
+
const interface_converters_1 = require("../../interface-converters");
|
|
12
13
|
const yaml = require('js-yaml');
|
|
13
14
|
class LocalWorkflowTemplateDeployer {
|
|
14
15
|
async deployWorkflows(wtDeclaration) {
|
|
@@ -24,6 +25,7 @@ class LocalWorkflowTemplateDeployer {
|
|
|
24
25
|
console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk_1.default.yellow.bold('WORKFLOW TEMPLATES'));
|
|
25
26
|
const identifier = getWorkflowTemplateIdentifier(workflowKey);
|
|
26
27
|
const existingTemplate = existingWorkflows.find(ad => ad.identifier === identifier);
|
|
28
|
+
(0, interface_converters_1.convertWorkflow)(workflow);
|
|
27
29
|
if (existingTemplate) {
|
|
28
30
|
return await this.updateWorkflowTemplate(workflowKey, existingTemplate, workflow);
|
|
29
31
|
}
|
|
@@ -47,6 +49,7 @@ class LocalWorkflowTemplateDeployer {
|
|
|
47
49
|
}
|
|
48
50
|
async populateActionIds(workflowTemplate, workflowKey) {
|
|
49
51
|
var _a;
|
|
52
|
+
console.log('workflow tempalate:', JSON.stringify(workflowTemplate, null, 2));
|
|
50
53
|
if (!((_a = workflowTemplate === null || workflowTemplate === void 0 ? void 0 : workflowTemplate.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
|
|
51
54
|
return;
|
|
52
55
|
}
|
|
@@ -70,11 +73,14 @@ class LocalWorkflowTemplateDeployer {
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
async updateWorkflowTemplate(workflowKey, existingWorkflowTemplate, workflowTemplate) {
|
|
76
|
+
var _a, _b;
|
|
73
77
|
await this.populateActionIds(workflowTemplate, workflowKey);
|
|
74
78
|
const updates = Object.assign(new Object(), {
|
|
75
79
|
name: workflowTemplate.name,
|
|
76
80
|
triggerKey: workflowTemplate.triggerKey,
|
|
77
|
-
workflowDefinition: workflowTemplate.workflowDefinition
|
|
81
|
+
workflowDefinition: workflowTemplate.workflowDefinition,
|
|
82
|
+
messageGroupId: (_a = workflowTemplate.messageGroupId) !== null && _a !== void 0 ? _a : existingWorkflowTemplate.messageGroupId,
|
|
83
|
+
parallelWorkerCount: (_b = workflowTemplate.parallelWorkerCount) !== null && _b !== void 0 ? _b : existingWorkflowTemplate.parallelWorkerCount,
|
|
78
84
|
});
|
|
79
85
|
const updatedWorkflowTemplate = await (0, event_workflow_templates_1.updateWorkflowTemplate)({ id: existingWorkflowTemplate.id, updates });
|
|
80
86
|
console.log(`%s Updated existing workflow template: ${updatedWorkflowTemplate.identifier}`, chalk_1.default.yellow.bold('WORKFLOW TEMPLATES'));
|
|
@@ -157,7 +163,6 @@ function loadTemplateConfig(saveFile) {
|
|
|
157
163
|
const TARGET_DIR = process.cwd();
|
|
158
164
|
try {
|
|
159
165
|
const doc = yaml.load(fs_1.default.readFileSync(path.resolve(path.join(TARGET_DIR, saveFile)), 'utf8'));
|
|
160
|
-
console.log(doc);
|
|
161
166
|
return doc;
|
|
162
167
|
}
|
|
163
168
|
catch (e) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertWorkflow = exports.DEFAULT_WORKFLOW_PARALLELISM = void 0;
|
|
4
|
+
exports.DEFAULT_WORKFLOW_PARALLELISM = 1;
|
|
5
|
+
// parses the user-facing interface of the workflow and converts it to the cloud-facing format in-place.
|
|
6
|
+
function convertWorkflow(workflow) {
|
|
7
|
+
var _a;
|
|
8
|
+
workflow.parallelWorkerCount = (_a = workflow.parallelism) !== null && _a !== void 0 ? _a : exports.DEFAULT_WORKFLOW_PARALLELISM;
|
|
9
|
+
workflow.messageGroupId = workflow.groupId;
|
|
10
|
+
}
|
|
11
|
+
exports.convertWorkflow = convertWorkflow;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const interface_converters_1 = require("./interface-converters");
|
|
4
|
+
describe('Workflow Template converter tests', () => {
|
|
5
|
+
it('should use default parallelism', () => {
|
|
6
|
+
const workflow = {
|
|
7
|
+
identifier: 'identifier',
|
|
8
|
+
name: 'name1',
|
|
9
|
+
triggerKey: 'foo|bar',
|
|
10
|
+
workflowDefinition: {
|
|
11
|
+
paths: [
|
|
12
|
+
{
|
|
13
|
+
conditional: 'true',
|
|
14
|
+
actionDefinitionConfigs: [
|
|
15
|
+
{
|
|
16
|
+
action: 'logItem',
|
|
17
|
+
name: 'Log Item'
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
ownerKey: 'app:123',
|
|
24
|
+
isActive: true,
|
|
25
|
+
public: true,
|
|
26
|
+
// parallelism: 3,
|
|
27
|
+
};
|
|
28
|
+
(0, interface_converters_1.convertWorkflow)(workflow);
|
|
29
|
+
expect(workflow.parallelWorkerCount).toEqual(interface_converters_1.DEFAULT_WORKFLOW_PARALLELISM);
|
|
30
|
+
expect(workflow['concurrency']).toBeUndefined();
|
|
31
|
+
expect(workflow.messageGroupId).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
it('should pass user concurrency as parallel count', () => {
|
|
34
|
+
const workflow = {
|
|
35
|
+
identifier: 'identifier',
|
|
36
|
+
name: 'name1',
|
|
37
|
+
triggerKey: 'foo|bar',
|
|
38
|
+
workflowDefinition: {
|
|
39
|
+
paths: [
|
|
40
|
+
{
|
|
41
|
+
conditional: 'true',
|
|
42
|
+
actionDefinitionConfigs: [
|
|
43
|
+
{
|
|
44
|
+
action: 'logItem',
|
|
45
|
+
name: 'Log Item'
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
ownerKey: 'app:123',
|
|
52
|
+
isActive: true,
|
|
53
|
+
public: true,
|
|
54
|
+
parallelism: 3,
|
|
55
|
+
};
|
|
56
|
+
(0, interface_converters_1.convertWorkflow)(workflow);
|
|
57
|
+
expect(workflow.parallelWorkerCount).toEqual(3);
|
|
58
|
+
expect(workflow['concurrency']).toBeUndefined();
|
|
59
|
+
expect(workflow.messageGroupId).toBeUndefined();
|
|
60
|
+
});
|
|
61
|
+
it('should ignore concurrency if we pass group ID or ', () => {
|
|
62
|
+
const workflow = {
|
|
63
|
+
identifier: 'identifier',
|
|
64
|
+
name: 'name1',
|
|
65
|
+
triggerKey: 'foo|bar',
|
|
66
|
+
workflowDefinition: {
|
|
67
|
+
paths: [
|
|
68
|
+
{
|
|
69
|
+
conditional: 'true',
|
|
70
|
+
actionDefinitionConfigs: [
|
|
71
|
+
{
|
|
72
|
+
action: 'logItem',
|
|
73
|
+
name: 'Log Item'
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
ownerKey: 'app:123',
|
|
80
|
+
isActive: true,
|
|
81
|
+
public: true,
|
|
82
|
+
parallelism: 3,
|
|
83
|
+
};
|
|
84
|
+
(0, interface_converters_1.convertWorkflow)(workflow);
|
|
85
|
+
expect(workflow.parallelWorkerCount).toEqual(3);
|
|
86
|
+
expect(workflow['concurrency']).toBeUndefined();
|
|
87
|
+
expect(workflow.messageGroupId).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
});
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ export interface WorkflowDefinition {
|
|
|
57
57
|
isActive: boolean;
|
|
58
58
|
public: boolean;
|
|
59
59
|
supportingAppId?: string;
|
|
60
|
+
parallelism?: number;
|
|
61
|
+
groupId?: string;
|
|
60
62
|
messageGroupId?: string;
|
|
61
63
|
parallelWorkerCount?: number;
|
|
62
64
|
}
|
|
@@ -74,6 +76,8 @@ export interface WorkflowTemplate {
|
|
|
74
76
|
isActive: boolean;
|
|
75
77
|
ownerKey?: string;
|
|
76
78
|
supportingAppId?: string;
|
|
79
|
+
parallelism?: number;
|
|
80
|
+
groupId?: string;
|
|
77
81
|
messageGroupId?: string;
|
|
78
82
|
parallelWorkerCount?: number;
|
|
79
83
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.0.
|
|
2
|
+
"version": "2.0.8",
|
|
3
3
|
"commands": {
|
|
4
4
|
"app:create": {
|
|
5
5
|
"id": "app:create",
|
|
@@ -307,10 +307,10 @@
|
|
|
307
307
|
"$ contrail groups export\n"
|
|
308
308
|
],
|
|
309
309
|
"flags": {
|
|
310
|
-
"
|
|
311
|
-
"name": "
|
|
310
|
+
"outFile": {
|
|
311
|
+
"name": "outFile",
|
|
312
312
|
"type": "option",
|
|
313
|
-
"char": "
|
|
313
|
+
"char": "f",
|
|
314
314
|
"description": "The location for the file to be saved",
|
|
315
315
|
"required": false,
|
|
316
316
|
"multiple": false,
|
|
@@ -361,6 +361,7 @@
|
|
|
361
361
|
"outDir": {
|
|
362
362
|
"name": "outDir",
|
|
363
363
|
"type": "option",
|
|
364
|
+
"char": "d",
|
|
364
365
|
"description": "The directory to which to export the instance data. Defaults to the current directory",
|
|
365
366
|
"required": false,
|
|
366
367
|
"multiple": false,
|
|
@@ -369,6 +370,7 @@
|
|
|
369
370
|
"overwrite": {
|
|
370
371
|
"name": "overwrite",
|
|
371
372
|
"type": "boolean",
|
|
373
|
+
"char": "f",
|
|
372
374
|
"description": "Replaces any existing export files in outDir",
|
|
373
375
|
"required": false,
|
|
374
376
|
"allowNo": false
|
|
@@ -391,6 +393,7 @@
|
|
|
391
393
|
"dir": {
|
|
392
394
|
"name": "dir",
|
|
393
395
|
"type": "option",
|
|
396
|
+
"char": "d",
|
|
394
397
|
"description": "The directory from which to export the instance data. Defaults to the current directory",
|
|
395
398
|
"required": false,
|
|
396
399
|
"multiple": false,
|
|
@@ -930,10 +933,10 @@
|
|
|
930
933
|
"$ contrail users export\n"
|
|
931
934
|
],
|
|
932
935
|
"flags": {
|
|
933
|
-
"
|
|
934
|
-
"name": "
|
|
936
|
+
"outFile": {
|
|
937
|
+
"name": "outFile",
|
|
935
938
|
"type": "option",
|
|
936
|
-
"char": "
|
|
939
|
+
"char": "f",
|
|
937
940
|
"description": "The location for the file to be saved",
|
|
938
941
|
"required": false,
|
|
939
942
|
"multiple": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "VibeIQ's Contrail Platform CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"contrail-cli": "./bin/run",
|
|
@@ -50,16 +50,17 @@
|
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@oclif/test": "^2.3.8",
|
|
52
52
|
"@types/chai": "^4",
|
|
53
|
-
"@types/
|
|
53
|
+
"@types/jest": "^29.5.0",
|
|
54
54
|
"@types/node": "^16.18.14",
|
|
55
55
|
"chai": "^4",
|
|
56
56
|
"eslint": "^8.35.0",
|
|
57
57
|
"eslint-config-oclif": "^4",
|
|
58
58
|
"eslint-config-oclif-typescript": "^1.0.3",
|
|
59
59
|
"eslint-plugin-unused-imports": "^2.0.0",
|
|
60
|
-
"
|
|
60
|
+
"jest": "^29.5.0",
|
|
61
61
|
"oclif": "^3",
|
|
62
62
|
"shx": "^0.3.3",
|
|
63
|
+
"ts-jest": "^29.0.5",
|
|
63
64
|
"ts-node": "^10.9.1",
|
|
64
65
|
"tslib": "^2.5.0",
|
|
65
66
|
"typescript": "^4.9.5"
|
|
@@ -106,16 +107,29 @@
|
|
|
106
107
|
},
|
|
107
108
|
"scripts": {
|
|
108
109
|
"build": "shx rm -rf dist && tsc -b && npm run copy-templates",
|
|
109
|
-
"lint": "eslint . --ext .ts --config .eslintrc",
|
|
110
|
+
"lint": "eslint . --ext .ts --config .eslintrc.js",
|
|
110
111
|
"copy-templates": "cp -r templates/ dist/templates",
|
|
111
112
|
"postpack": "shx rm -f oclif.manifest.json",
|
|
112
|
-
"posttest": "yarn lint",
|
|
113
113
|
"prepack": "yarn build && oclif manifest && oclif readme",
|
|
114
|
-
"test": "
|
|
114
|
+
"test": "jest",
|
|
115
115
|
"version": "oclif readme && git add README.md"
|
|
116
116
|
},
|
|
117
117
|
"engines": {
|
|
118
118
|
"node": ">=12.0.0"
|
|
119
119
|
},
|
|
120
|
-
"types": "dist/index.d.ts"
|
|
120
|
+
"types": "dist/index.d.ts",
|
|
121
|
+
"jest": {
|
|
122
|
+
"moduleFileExtensions": [
|
|
123
|
+
"js",
|
|
124
|
+
"json",
|
|
125
|
+
"ts"
|
|
126
|
+
],
|
|
127
|
+
"rootDir": "src",
|
|
128
|
+
"testRegex": ".spec.ts$",
|
|
129
|
+
"transform": {
|
|
130
|
+
"^.+\\.(t|j)s$": "ts-jest"
|
|
131
|
+
},
|
|
132
|
+
"coverageDirectory": "../coverage",
|
|
133
|
+
"testEnvironment": "node"
|
|
134
|
+
}
|
|
121
135
|
}
|