@contrail/cli 2.1.1 → 2.1.3
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 +23 -3
- package/dist/api/types.d.ts +3 -0
- package/dist/api/types.js +22 -1
- package/dist/commands/instance/import.js +2 -0
- package/dist/commands/types/getAll.d.ts +6 -0
- package/dist/commands/types/getAll.js +112 -3
- package/dist/commands/types/loadAll.js +3 -1
- package/dist/commands/types/mergeTypeProperties.js +3 -0
- package/dist/commands/types/uploadOptionSetHierarchies.js +104 -0
- package/dist/commands/types/uploadTypePolicies.d.ts +10 -0
- package/dist/commands/types/uploadTypePolicies.js +226 -0
- package/dist/commands/types/uploadTypePropertyPolicies.js +17 -9
- package/dist/helpers/types/type-extractor.d.ts +1 -1
- package/dist/helpers/types/type-extractor.js +4 -1
- package/dist/helpers/types/type-uploader.js +10 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/templates/typescript/package.json +3 -3
- package/dist/templates/typescript/src/main.ts +12 -5
- package/oclif.manifest.json +26 -1
- package/package.json +2 -2
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.1.
|
|
18
|
+
@contrail/cli/2.1.3 darwin-arm64 node-v18.13.0
|
|
19
19
|
$ contrail --help [COMMAND]
|
|
20
20
|
USAGE
|
|
21
21
|
$ contrail COMMAND
|
|
@@ -75,6 +75,7 @@ To get instructions on how to set up autocomplete for your shell, run `contrail
|
|
|
75
75
|
* [`contrail types uploadOptionSets`](#contrail-types-uploadoptionsets)
|
|
76
76
|
* [`contrail types uploadOptionSetsHierarchyLocalFile FILE NAME`](#contrail-types-uploadoptionsetshierarchylocalfile-file-name)
|
|
77
77
|
* [`contrail types uploadRuleSets`](#contrail-types-uploadrulesets)
|
|
78
|
+
* [`contrail types uploadTypePolicies`](#contrail-types-uploadtypepolicies)
|
|
78
79
|
* [`contrail types uploadTypePropertyPolicies`](#contrail-types-uploadtypepropertypolicies)
|
|
79
80
|
* [`contrail types uploadUsageInfo`](#contrail-types-uploadusageinfo)
|
|
80
81
|
* [`contrail users export`](#contrail-users-export)
|
|
@@ -764,11 +765,11 @@ Get all Types and associated data for your Org
|
|
|
764
765
|
|
|
765
766
|
```
|
|
766
767
|
USAGE
|
|
767
|
-
$ contrail types getAll [-d <value>] [
|
|
768
|
+
$ contrail types getAll [-d <value>] [-f]
|
|
768
769
|
|
|
769
770
|
FLAGS
|
|
770
771
|
-d, --outDir=<value> [default: .] The directory to which to export the type data. Defaults to the current directory
|
|
771
|
-
--overwrite
|
|
772
|
+
-f, --overwrite Replaces any existing export files in outDir
|
|
772
773
|
|
|
773
774
|
DESCRIPTION
|
|
774
775
|
Get all Types and associated data for your Org
|
|
@@ -1047,6 +1048,25 @@ EXAMPLES
|
|
|
1047
1048
|
$ contrail types uploadRuleSets
|
|
1048
1049
|
```
|
|
1049
1050
|
|
|
1051
|
+
## `contrail types uploadTypePolicies`
|
|
1052
|
+
|
|
1053
|
+
Upload type policies
|
|
1054
|
+
|
|
1055
|
+
```
|
|
1056
|
+
USAGE
|
|
1057
|
+
$ contrail types uploadTypePolicies [-d <value>]
|
|
1058
|
+
|
|
1059
|
+
FLAGS
|
|
1060
|
+
-d, --dir=<value> [default: .] The directory from which to export the type policy data. Defaults to the current
|
|
1061
|
+
directory. The type policy data will be loaded from $dir/type-policies/*.yml
|
|
1062
|
+
|
|
1063
|
+
DESCRIPTION
|
|
1064
|
+
Upload type policies
|
|
1065
|
+
|
|
1066
|
+
EXAMPLES
|
|
1067
|
+
$ contrail types UploadTypePolicies
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1050
1070
|
## `contrail types uploadTypePropertyPolicies`
|
|
1051
1071
|
|
|
1052
1072
|
Upload type property policies
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export declare function getOptionSets(): Promise<any>;
|
|
2
2
|
export declare function getOptionSetHierarchies(): Promise<any>;
|
|
3
|
+
export declare function getOptionSetHierarchyLinks(): Promise<any>;
|
|
3
4
|
export declare function getRuleSets(): Promise<any>;
|
|
4
5
|
export declare function getRuleSetLinks(): Promise<any>;
|
|
5
6
|
export declare function getUsageInfo(): Promise<any>;
|
|
6
7
|
export declare function getTypePropertyPolicies(): Promise<any>;
|
|
7
8
|
export declare function getTypePropertyPolicyLinks(): Promise<any>;
|
|
9
|
+
export declare function getTypePolicies(): Promise<any>;
|
|
10
|
+
export declare function getTypePolicyLinks(): Promise<any>;
|
package/dist/api/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchies = exports.getOptionSets = void 0;
|
|
3
|
+
exports.getTypePolicyLinks = exports.getTypePolicies = exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchyLinks = exports.getOptionSetHierarchies = exports.getOptionSets = void 0;
|
|
4
4
|
const sdk_1 = require("@contrail/sdk");
|
|
5
5
|
async function getOptionSets() {
|
|
6
6
|
return await new sdk_1.Entities().get({
|
|
@@ -15,6 +15,13 @@ async function getOptionSetHierarchies() {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
exports.getOptionSetHierarchies = getOptionSetHierarchies;
|
|
18
|
+
async function getOptionSetHierarchyLinks() {
|
|
19
|
+
const entitiesClient = new sdk_1.Entities();
|
|
20
|
+
return await entitiesClient.get({
|
|
21
|
+
entityName: 'type-option-set-hierarchy-link',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
exports.getOptionSetHierarchyLinks = getOptionSetHierarchyLinks;
|
|
18
25
|
async function getRuleSets() {
|
|
19
26
|
const entitiesClient = new sdk_1.Entities();
|
|
20
27
|
return await entitiesClient.get({
|
|
@@ -50,3 +57,17 @@ async function getTypePropertyPolicyLinks() {
|
|
|
50
57
|
});
|
|
51
58
|
}
|
|
52
59
|
exports.getTypePropertyPolicyLinks = getTypePropertyPolicyLinks;
|
|
60
|
+
async function getTypePolicies() {
|
|
61
|
+
const entitiesClient = new sdk_1.Entities();
|
|
62
|
+
return await entitiesClient.get({
|
|
63
|
+
entityName: 'type-policy',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
exports.getTypePolicies = getTypePolicies;
|
|
67
|
+
async function getTypePolicyLinks() {
|
|
68
|
+
const entitiesClient = new sdk_1.Entities();
|
|
69
|
+
return await entitiesClient.get({
|
|
70
|
+
entityName: 'type-policy-link',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
exports.getTypePolicyLinks = getTypePolicyLinks;
|
|
@@ -7,6 +7,7 @@ const loadAll_1 = require("../types/loadAll");
|
|
|
7
7
|
const upload_1 = require("../users/upload");
|
|
8
8
|
const upload_2 = require("../groups/upload");
|
|
9
9
|
const uploadTypePropertyPolicies_1 = require("../types/uploadTypePropertyPolicies");
|
|
10
|
+
const uploadTypePolicies_1 = require("../types/uploadTypePolicies");
|
|
10
11
|
class ImportInstance extends core_1.Command {
|
|
11
12
|
async run() {
|
|
12
13
|
const { flags } = await this.parse(ImportInstance);
|
|
@@ -14,6 +15,7 @@ class ImportInstance extends core_1.Command {
|
|
|
14
15
|
await (0, upload_1.uploadUsers)(path.join(flags.dir, 'users.yml'));
|
|
15
16
|
await (0, upload_2.uploadGroups)(path.join(flags.dir, 'groups.yml'));
|
|
16
17
|
await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(flags.dir);
|
|
18
|
+
await (0, uploadTypePolicies_1.uploadTypePolicies)(flags.dir);
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
exports.default = ImportInstance;
|
|
@@ -3,21 +3,27 @@ export interface DataHolder {
|
|
|
3
3
|
types: any[];
|
|
4
4
|
optionSets: any[];
|
|
5
5
|
optionSetHierarchies: any[];
|
|
6
|
+
optionSetHierarchyLinks: any[];
|
|
6
7
|
ruleSets: any[];
|
|
7
8
|
ruleSetLinks: any[];
|
|
8
9
|
usageInfo: any[];
|
|
9
10
|
typePropertyPolicies: any[];
|
|
10
11
|
typePropertyPolicyLinks: any[];
|
|
12
|
+
typePolicies: any[];
|
|
13
|
+
typePolicyLinks: any[];
|
|
11
14
|
}
|
|
12
15
|
export interface ReducedDataHolder {
|
|
13
16
|
reducedTypes: any[];
|
|
14
17
|
reducedOptionSets: any[];
|
|
15
18
|
reducedOptionSetHierarchies: any[];
|
|
19
|
+
reducedOptionSetHierarchyLinks: any[];
|
|
16
20
|
reducedRuleSets: any[];
|
|
17
21
|
reducedRuleSetLinks: any[];
|
|
18
22
|
reducedUsageInfo: any[];
|
|
19
23
|
reducedTypePropertyPolicies: any[];
|
|
20
24
|
reducedTypePropertyPolicyLinks: any[];
|
|
25
|
+
reducedTypePolicies: any[];
|
|
26
|
+
reducedTypePolicyLinks: any[];
|
|
21
27
|
}
|
|
22
28
|
export default class GetAllTypes extends Command {
|
|
23
29
|
static description: string;
|
|
@@ -26,7 +26,7 @@ GetAllTypes.examples = [
|
|
|
26
26
|
];
|
|
27
27
|
GetAllTypes.flags = {
|
|
28
28
|
outDir: core_1.Flags.string({ char: 'd', description: 'The directory to which to export the type data. Defaults to the current directory', required: false, default: '.' }),
|
|
29
|
-
overwrite: core_1.Flags.boolean({ description: 'Replaces any existing export files in outDir', required: false, default: false })
|
|
29
|
+
overwrite: core_1.Flags.boolean({ char: 'f', description: 'Replaces any existing export files in outDir', required: false, default: false })
|
|
30
30
|
};
|
|
31
31
|
async function getAll(outDir, overwrite) {
|
|
32
32
|
try {
|
|
@@ -40,11 +40,14 @@ async function getAll(outDir, overwrite) {
|
|
|
40
40
|
types: await (0, type_extractor_1.getTypes)(),
|
|
41
41
|
optionSets: await (0, types_1.getOptionSets)(),
|
|
42
42
|
optionSetHierarchies: await (0, types_1.getOptionSetHierarchies)(),
|
|
43
|
+
optionSetHierarchyLinks: await (0, types_1.getOptionSetHierarchyLinks)(),
|
|
43
44
|
ruleSets: await (0, types_1.getRuleSets)(),
|
|
44
45
|
ruleSetLinks: await (0, types_1.getRuleSetLinks)(),
|
|
45
46
|
usageInfo: await (0, types_1.getUsageInfo)(),
|
|
46
47
|
typePropertyPolicies: await (0, types_1.getTypePropertyPolicies)(),
|
|
47
48
|
typePropertyPolicyLinks: await (0, types_1.getTypePropertyPolicyLinks)(),
|
|
49
|
+
typePolicies: await (0, types_1.getTypePolicies)(),
|
|
50
|
+
typePolicyLinks: await (0, types_1.getTypePolicyLinks)(),
|
|
48
51
|
};
|
|
49
52
|
const reducedData = await reduceData(data);
|
|
50
53
|
await saveData(reducedData, outDir, overwrite);
|
|
@@ -101,11 +104,80 @@ async function reduceTypePropertyPolicies(data) {
|
|
|
101
104
|
function reduceTypePropertyPolicyLinks(data) {
|
|
102
105
|
var _a, _b;
|
|
103
106
|
const typeProperties = (_a = data === null || data === void 0 ? void 0 : data.types) === null || _a === void 0 ? void 0 : _a.map(x => x.typeProperties).reduce((x, y) => x.concat(y));
|
|
107
|
+
// make a map of all type properties to their type ids
|
|
108
|
+
const typePropertyIdToTypeSlugMap = data.types.reduce((map, obj) => {
|
|
109
|
+
for (const tp of obj.typeProperties) {
|
|
110
|
+
map[tp.id] = obj.slug;
|
|
111
|
+
}
|
|
112
|
+
return map;
|
|
113
|
+
}, {});
|
|
104
114
|
return (_b = data === null || data === void 0 ? void 0 : data.typePropertyPolicyLinks) === null || _b === void 0 ? void 0 : _b.map(x => {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
const typeSlug = typePropertyIdToTypeSlugMap[x.typePropertyId];
|
|
117
|
+
const typePropertySlug = (_a = typeProperties.find(y => y.id === x.typePropertyId)) === null || _a === void 0 ? void 0 : _a.slug;
|
|
118
|
+
const typePropertyPolicyLabel = (_b = data.typePropertyPolicies.find(y => y.id === x.typePropertyPolicyId)) === null || _b === void 0 ? void 0 : _b.label;
|
|
119
|
+
if (!typeSlug ||
|
|
120
|
+
!typePropertySlug ||
|
|
121
|
+
!typePropertyPolicyLabel) {
|
|
122
|
+
console.warn('Could not reduce bad type property policy link... skipping', x);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
typeSlug,
|
|
127
|
+
typePropertySlug,
|
|
128
|
+
typePropertyPolicyLabel,
|
|
129
|
+
};
|
|
130
|
+
}).filter(x => !!x);
|
|
131
|
+
}
|
|
132
|
+
async function reduceTypePolicies(data) {
|
|
133
|
+
var _a;
|
|
134
|
+
const orgUsers = await (0, users_1.getUserOrgs)();
|
|
135
|
+
const groups = await (0, users_1.getGroups)();
|
|
136
|
+
function reducePrincipal(statement) {
|
|
137
|
+
var _a, _b;
|
|
138
|
+
if (!(statement === null || statement === void 0 ? void 0 : statement.principal)) {
|
|
139
|
+
return statement;
|
|
140
|
+
}
|
|
141
|
+
const [type, id] = statement.principal.split(':');
|
|
142
|
+
if (!type || !id) {
|
|
143
|
+
return statement;
|
|
144
|
+
}
|
|
145
|
+
if (type === 'group') {
|
|
146
|
+
const groupName = (_a = groups.find(x => x.id === id)) === null || _a === void 0 ? void 0 : _a.name;
|
|
147
|
+
if (!groupName) {
|
|
148
|
+
console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
|
|
149
|
+
return statement;
|
|
150
|
+
}
|
|
151
|
+
statement.principal = `group:${groupName}`;
|
|
152
|
+
}
|
|
153
|
+
else if (type === 'user') {
|
|
154
|
+
const userEmail = (_b = orgUsers.find(x => x.user.id === id)) === null || _b === void 0 ? void 0 : _b.email;
|
|
155
|
+
if (!userEmail) {
|
|
156
|
+
console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
|
|
157
|
+
return statement;
|
|
158
|
+
}
|
|
159
|
+
statement.principal = `user:${userEmail}`;
|
|
160
|
+
}
|
|
161
|
+
return statement;
|
|
162
|
+
}
|
|
163
|
+
return (_a = data === null || data === void 0 ? void 0 : data.typePolicies) === null || _a === void 0 ? void 0 : _a.map(x => {
|
|
164
|
+
return {
|
|
165
|
+
label: x.label,
|
|
166
|
+
policy: {
|
|
167
|
+
version: x.policy.version,
|
|
168
|
+
statements: x.policy.statements.map(x => reducePrincipal(x)),
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function reduceTypePolicyLinks(data) {
|
|
174
|
+
var _a;
|
|
175
|
+
const types = data === null || data === void 0 ? void 0 : data.types;
|
|
176
|
+
return (_a = data === null || data === void 0 ? void 0 : data.typePolicyLinks) === null || _a === void 0 ? void 0 : _a.map(x => {
|
|
105
177
|
var _a, _b;
|
|
106
178
|
return {
|
|
107
|
-
|
|
108
|
-
|
|
179
|
+
typeSlug: (_a = types.find(y => y.id === x.typeId)) === null || _a === void 0 ? void 0 : _a.slug,
|
|
180
|
+
typePolicyLabel: (_b = data.typePolicies.find(y => y.id === x.typePolicyId)) === null || _b === void 0 ? void 0 : _b.label,
|
|
109
181
|
};
|
|
110
182
|
});
|
|
111
183
|
}
|
|
@@ -176,6 +248,36 @@ function reduceOptionSetHierarchies(data) {
|
|
|
176
248
|
};
|
|
177
249
|
});
|
|
178
250
|
}
|
|
251
|
+
function reduceOptionSetHierarchyLinks(data) {
|
|
252
|
+
var _a;
|
|
253
|
+
return (_a = data.optionSetHierarchyLinks) === null || _a === void 0 ? void 0 : _a.map(x => {
|
|
254
|
+
var _a;
|
|
255
|
+
const osh = data.optionSetHierarchies.find(y => y.id === x.optionSetHierarchyId);
|
|
256
|
+
if (!osh) {
|
|
257
|
+
console.log('OSH Link: could not find option set hierarchy', x.optionSetHierarchyId, 'skipping...');
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const type = data.types.find(y => y.id === x.typeId);
|
|
261
|
+
if (!type) {
|
|
262
|
+
console.log('OSH Link: could not find type', x.typeId, 'skipping...');
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
const typePropertySlugs = [];
|
|
266
|
+
for (const tpId of x.hierarchyTypePropertyIds) {
|
|
267
|
+
const typePropertySlug = (_a = type.typeProperties.find(y => y.id === tpId)) === null || _a === void 0 ? void 0 : _a.slug;
|
|
268
|
+
if (!typePropertySlug) {
|
|
269
|
+
console.log('OSH Link: could not find type property', tpId, 'skipping...');
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
typePropertySlugs.push(typePropertySlug);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
optionSetHierarchyName: osh.name,
|
|
276
|
+
typeSlug: type.slug,
|
|
277
|
+
typePropertySlugs,
|
|
278
|
+
};
|
|
279
|
+
}).filter(x => !!x);
|
|
280
|
+
}
|
|
179
281
|
function reduceTypes(dataHolder) {
|
|
180
282
|
console.log('Found types: ', dataHolder.types.length);
|
|
181
283
|
let reducedTypes = [];
|
|
@@ -197,6 +299,7 @@ function reduceTypes(dataHolder) {
|
|
|
197
299
|
core: typeProperty.core,
|
|
198
300
|
typePropertyOptionSetName: optionSetNameById[typeProperty.typePropertyOptionSetId],
|
|
199
301
|
formula: typeProperty.formula,
|
|
302
|
+
referencedTypePath: typeProperty.referencedTypePath,
|
|
200
303
|
referencedTypeRootSlug: typeProperty.referencedTypeRootSlug,
|
|
201
304
|
defaultValue: typeProperty.defaultValue,
|
|
202
305
|
propertyLevel: typeProperty.propertyLevel,
|
|
@@ -230,11 +333,14 @@ async function reduceData(data) {
|
|
|
230
333
|
reducedTypes: reduceTypes(data),
|
|
231
334
|
reducedOptionSets: reduceOptionSets(data),
|
|
232
335
|
reducedOptionSetHierarchies: reduceOptionSetHierarchies(data),
|
|
336
|
+
reducedOptionSetHierarchyLinks: reduceOptionSetHierarchyLinks(data),
|
|
233
337
|
reducedRuleSets: reduceRuleSets(data),
|
|
234
338
|
reducedRuleSetLinks: reduceRuleSetLinks(data),
|
|
235
339
|
reducedUsageInfo: reduceUsageInfo(data),
|
|
236
340
|
reducedTypePropertyPolicies: await reduceTypePropertyPolicies(data),
|
|
237
341
|
reducedTypePropertyPolicyLinks: reduceTypePropertyPolicyLinks(data),
|
|
342
|
+
reducedTypePolicies: await reduceTypePolicies(data),
|
|
343
|
+
reducedTypePolicyLinks: reduceTypePolicyLinks(data),
|
|
238
344
|
};
|
|
239
345
|
}
|
|
240
346
|
exports.reduceData = reduceData;
|
|
@@ -276,11 +382,14 @@ async function saveData(reducedData, dir, overwrite) {
|
|
|
276
382
|
reducedTypes: { filename: 'types', split: false, fileLabel: 'slug', saveFunction: saveTypesFunction },
|
|
277
383
|
reducedOptionSets: { filename: 'option-sets', split: true, fileLabel: 'name' },
|
|
278
384
|
reducedOptionSetHierarchies: { filename: 'option-set-hierarchies', split: true, fileLabel: 'name' },
|
|
385
|
+
reducedOptionSetHierarchyLinks: { filename: 'type-option-set-hierarchy-links', split: false, fileLabel: '' },
|
|
279
386
|
reducedRuleSets: { filename: 'rule-sets', split: true, fileLabel: 'name' },
|
|
280
387
|
reducedRuleSetLinks: { filename: 'rule-set-links', split: false, fileLabel: '' },
|
|
281
388
|
reducedUsageInfo: { filename: 'usage-info', split: false, fileLabel: '' },
|
|
282
389
|
reducedTypePropertyPolicies: { filename: 'type-property-policies', split: true, fileLabel: 'label' },
|
|
283
390
|
reducedTypePropertyPolicyLinks: { filename: 'type-property-policy-links', split: false, fileLabel: '' },
|
|
391
|
+
reducedTypePolicies: { filename: 'type-policies', split: true, fileLabel: 'label' },
|
|
392
|
+
reducedTypePolicyLinks: { filename: 'type-policy-links', split: false, fileLabel: '' },
|
|
284
393
|
};
|
|
285
394
|
for (const [key, folder] of Object.entries(propertyToFolderMap)) {
|
|
286
395
|
const CURRENT_DIR = process.cwd();
|
|
@@ -11,6 +11,7 @@ const uploadUsageInfo_1 = require("./uploadUsageInfo");
|
|
|
11
11
|
const uploadRuleSets_1 = require("./uploadRuleSets");
|
|
12
12
|
const uploadTypePropertyPolicies_1 = require("./uploadTypePropertyPolicies");
|
|
13
13
|
const type_uploader_1 = require("../../helpers/types/type-uploader");
|
|
14
|
+
const uploadTypePolicies_1 = require("./uploadTypePolicies");
|
|
14
15
|
class LoadAllTypes extends core_1.Command {
|
|
15
16
|
async run() {
|
|
16
17
|
const { flags } = await this.parse(LoadAllTypes);
|
|
@@ -30,12 +31,13 @@ async function loadAll(dir, skipPolicies = false) {
|
|
|
30
31
|
try {
|
|
31
32
|
await (0, login_1.authUser)();
|
|
32
33
|
await (0, uploadOptionSets_1.uploadOptionSets)(dir);
|
|
33
|
-
await (0, uploadOptionSetHierarchies_1.uploadOptionSetHierarchies)(dir);
|
|
34
34
|
await (0, type_uploader_1.uploadTypes)(dir);
|
|
35
|
+
await (0, uploadOptionSetHierarchies_1.uploadOptionSetHierarchies)(dir);
|
|
35
36
|
await (0, uploadUsageInfo_1.uploadUsageInfo)(dir);
|
|
36
37
|
await (0, uploadRuleSets_1.uploadRuleSets)(dir);
|
|
37
38
|
if (!skipPolicies) {
|
|
38
39
|
await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(dir);
|
|
40
|
+
await (0, uploadTypePolicies_1.uploadTypePolicies)(dir);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
catch (e) {
|
|
@@ -58,11 +58,14 @@ async function mergeTypeProperties(fileLocation, typePaths) {
|
|
|
58
58
|
types: await (0, type_extractor_1.getTypes)(),
|
|
59
59
|
optionSets: await (0, types_1.getOptionSets)(),
|
|
60
60
|
optionSetHierarchies: [],
|
|
61
|
+
optionSetHierarchyLinks: [],
|
|
61
62
|
ruleSets: [],
|
|
62
63
|
ruleSetLinks: [],
|
|
63
64
|
usageInfo: [],
|
|
64
65
|
typePropertyPolicies: [],
|
|
65
66
|
typePropertyPolicyLinks: [],
|
|
67
|
+
typePolicies: [],
|
|
68
|
+
typePolicyLinks: [],
|
|
66
69
|
};
|
|
67
70
|
const reducedData = await (0, getAll_1.reduceData)(data);
|
|
68
71
|
for (const typePath of typePaths) {
|
|
@@ -8,6 +8,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
8
8
|
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
|
+
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
11
12
|
const yaml = require('js-yaml');
|
|
12
13
|
class UploadOptionSetHierarchies extends core_1.Command {
|
|
13
14
|
async run() {
|
|
@@ -30,6 +31,8 @@ async function uploadOptionSetHierarchies(dir) {
|
|
|
30
31
|
console.log('%s Uploading', chalk_1.default.yellow.bold('OPTION SET HIERARCHIES'));
|
|
31
32
|
const optionSetHierarchies = await loadOptionSetHierarchies(dir);
|
|
32
33
|
await uploadOSH(optionSetHierarchies);
|
|
34
|
+
const optionSetHierarchyLinks = await loadOptionSetHierarchyLinks(dir);
|
|
35
|
+
await uploadOSHLinks(optionSetHierarchyLinks);
|
|
33
36
|
console.log('%s Uploaded', chalk_1.default.yellow.bold('OPTION SET HIERARCHIES'));
|
|
34
37
|
}
|
|
35
38
|
catch (e) {
|
|
@@ -53,6 +56,14 @@ function loadOptionSetHierarchies(fromDir) {
|
|
|
53
56
|
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
54
57
|
}
|
|
55
58
|
}
|
|
59
|
+
function loadOptionSetHierarchyLinks(fromDir) {
|
|
60
|
+
try {
|
|
61
|
+
return yaml.load(fs_1.default.readFileSync(path.join(fromDir, 'type-option-set-hierarchy-links.yml'), 'utf8'));
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
56
67
|
async function uploadOSH(loadedOSHs) {
|
|
57
68
|
const optionSets = await new sdk_1.Entities().get({
|
|
58
69
|
entityName: 'type-property-option-set',
|
|
@@ -132,3 +143,96 @@ function transformOSHNameToID(hierarchy, optionSets) {
|
|
|
132
143
|
}
|
|
133
144
|
return true;
|
|
134
145
|
}
|
|
146
|
+
async function uploadOSHLinks(reducedOSHLinks) {
|
|
147
|
+
const typesWithProperties = await (0, type_extractor_1.getTypes)();
|
|
148
|
+
const typeProperties = [];
|
|
149
|
+
typesWithProperties.forEach(type => {
|
|
150
|
+
if (type.typeProperties) {
|
|
151
|
+
for (const tp of type.typeProperties) {
|
|
152
|
+
tp.typeId = type.id;
|
|
153
|
+
tp.typeSlug = type.slug;
|
|
154
|
+
typeProperties.push(tp);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
const currentOSHs = await new sdk_1.Entities().get({
|
|
159
|
+
entityName: 'option-set-hierarchy',
|
|
160
|
+
});
|
|
161
|
+
const currentOSHLinks = await new sdk_1.Entities().get({
|
|
162
|
+
entityName: 'type-option-set-hierarchy-link',
|
|
163
|
+
});
|
|
164
|
+
const currentOSHLinkHashes = {};
|
|
165
|
+
for (const currentLink of currentOSHLinks) {
|
|
166
|
+
const foundType = typesWithProperties.find(x => x.id === currentLink.typeId);
|
|
167
|
+
const foundOSH = currentOSHs.find(osh => osh.id === currentLink.optionSetHierarchyId);
|
|
168
|
+
const foundTPSlugs = typeProperties.filter(x => { var _a; return (_a = currentLink === null || currentLink === void 0 ? void 0 : currentLink.hierarchyTypePropertyIds) === null || _a === void 0 ? void 0 : _a.includes(x.id); }).map(x => x.slug);
|
|
169
|
+
if (!foundType || !foundOSH || (foundTPSlugs.length !== currentLink.hierarchyTypePropertyIds.length)) {
|
|
170
|
+
console.log('skipping unhashable, invalid type option set hierarchy link:', currentLink);
|
|
171
|
+
}
|
|
172
|
+
const hash = `${foundType.slug}|${foundOSH.name}|${foundTPSlugs.sort().join('|')}`;
|
|
173
|
+
currentOSHLinkHashes[hash] = currentLink;
|
|
174
|
+
}
|
|
175
|
+
const reducedLinksByHashes = {};
|
|
176
|
+
for (const loadedLink of reducedOSHLinks) {
|
|
177
|
+
const hash = `${loadedLink.typeSlug}|${loadedLink.optionSetHierarchyName}|${loadedLink.typePropertySlugs.sort().join('|')}}`;
|
|
178
|
+
reducedLinksByHashes[hash] = loadedLink;
|
|
179
|
+
}
|
|
180
|
+
for (const loadedLink of reducedOSHLinks) {
|
|
181
|
+
try {
|
|
182
|
+
const found = currentOSHLinkHashes[`${loadedLink.typeSlug}|${loadedLink.optionSetHierarchyName}|${loadedLink.typePropertySlugs.sort().join('|')}`];
|
|
183
|
+
if (!found) {
|
|
184
|
+
if (!transformReducedLink(loadedLink, typesWithProperties, currentOSHs)) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
await new sdk_1.Entities().create({
|
|
188
|
+
entityName: 'type-option-set-hierarchy-link',
|
|
189
|
+
object: {
|
|
190
|
+
hierarchyTypePropertyIds: loadedLink.hierarchyTypePropertyIds,
|
|
191
|
+
optionSetHierarchyId: loadedLink.optionSetHierarchyId,
|
|
192
|
+
typeId: loadedLink.typeId,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
throw new Error(`Error uploading type option set hierarchy links: ${err}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const [currentLinkHash, currentLink] of Object.entries(currentOSHLinkHashes)) {
|
|
202
|
+
try {
|
|
203
|
+
const found = reducedLinksByHashes[currentLinkHash];
|
|
204
|
+
if (!found) {
|
|
205
|
+
console.log('Deleting: ', currentLinkHash);
|
|
206
|
+
await new sdk_1.Entities().delete({
|
|
207
|
+
entityName: 'type-option-set-hierarchy-link',
|
|
208
|
+
id: currentLink['id'],
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
throw new Error(`Error Deleting rule set link: ${err}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function transformReducedLink(OSHLink, typesWithProperties, OSHs) {
|
|
218
|
+
var _a, _b;
|
|
219
|
+
const foundType = typesWithProperties.find(x => x.slug === OSHLink.typeSlug);
|
|
220
|
+
if (!foundType) {
|
|
221
|
+
console.error('OSH Links: Could not find type with slug', OSHLink.typeSlug);
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
OSHLink.typeId = foundType.id;
|
|
225
|
+
const foundTPs = (_b = (_a = foundType === null || foundType === void 0 ? void 0 : foundType.typeProperties) === null || _a === void 0 ? void 0 : _a.filter(x => OSHLink.typePropertySlugs.includes(x.slug))) !== null && _b !== void 0 ? _b : [];
|
|
226
|
+
if (foundTPs.length !== OSHLink.typePropertySlugs.length) {
|
|
227
|
+
console.error('OSH Links: Could not find all type properties with slugs', OSHLink.typePropertySlugs);
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
OSHLink.hierarchyTypePropertyIds = foundTPs.map(x => x.id);
|
|
231
|
+
const foundOSH = OSHs.find(x => x.name === OSHLink.optionSetHierarchyName);
|
|
232
|
+
if (!foundOSH) {
|
|
233
|
+
console.error('OSH Links: Could not find option set hierarchy with name', OSHLink.optionSetHierarchyName);
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
OSHLink.optionSetHierarchyId = foundOSH.id;
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class UploadTypePolicies extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
dir: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function uploadTypePolicies(dir: string): Promise<void>;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadTypePolicies = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const sdk_1 = require("@contrail/sdk");
|
|
6
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
7
|
+
const path = tslib_1.__importStar(require("path"));
|
|
8
|
+
const login_1 = require("../../auth/login");
|
|
9
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
10
|
+
const core_1 = require("@oclif/core");
|
|
11
|
+
const type_extractor_1 = require("../../helpers/types/type-extractor");
|
|
12
|
+
const users_1 = require("../../api/users");
|
|
13
|
+
const yaml = require('js-yaml');
|
|
14
|
+
class UploadTypePolicies extends core_1.Command {
|
|
15
|
+
async run() {
|
|
16
|
+
const { flags } = await this.parse(UploadTypePolicies);
|
|
17
|
+
return await uploadTypePolicies(flags.dir);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = UploadTypePolicies;
|
|
21
|
+
UploadTypePolicies.description = 'Upload type policies';
|
|
22
|
+
UploadTypePolicies.examples = [
|
|
23
|
+
`$ contrail types UploadTypePolicies
|
|
24
|
+
`,
|
|
25
|
+
];
|
|
26
|
+
UploadTypePolicies.flags = {
|
|
27
|
+
dir: core_1.Flags.string({ char: 'd', description: 'The directory from which to export the type policy data. Defaults to the current directory. The type policy data will be loaded from $dir/type-policies/*.yml', required: false, default: '.' }),
|
|
28
|
+
};
|
|
29
|
+
async function uploadTypePolicies(dir) {
|
|
30
|
+
try {
|
|
31
|
+
await (0, login_1.authUser)();
|
|
32
|
+
console.log('%s Uploading', chalk_1.default.yellow.bold('TYPE POLICY'));
|
|
33
|
+
const [reducedTypePolicies, reducedTypePolicyLinks] = await loadTypePolicies(dir);
|
|
34
|
+
await uploadTypePolicyObjects(reducedTypePolicies);
|
|
35
|
+
await uploadTypePolicyLinks(reducedTypePolicyLinks);
|
|
36
|
+
console.log('%s Uploaded', chalk_1.default.yellow.bold('TYPE POLICY'));
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.log(`%s Type Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log('%s Type Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
43
|
+
}
|
|
44
|
+
exports.uploadTypePolicies = uploadTypePolicies;
|
|
45
|
+
function loadTypePolicies(fromDir) {
|
|
46
|
+
const tps = [];
|
|
47
|
+
let tpLinks = [];
|
|
48
|
+
const dir = path.join(fromDir, 'type-policies');
|
|
49
|
+
try {
|
|
50
|
+
const files = fs_1.default.readdirSync(dir);
|
|
51
|
+
for (const file of files) {
|
|
52
|
+
tps.push(yaml.load(fs_1.default.readFileSync(path.join(dir, file), 'utf8')));
|
|
53
|
+
}
|
|
54
|
+
tpLinks = yaml.load(fs_1.default.readFileSync(path.join(fromDir, 'type-policy-links.yml'), 'utf8'));
|
|
55
|
+
return [tps, tpLinks];
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function uploadTypePolicyObjects(reducedTypePolicies) {
|
|
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
|
+
reducedTypePolicies.forEach(policy => {
|
|
96
|
+
policy.policy.statements = policy.policy.statements.map(x => fillPrincipal(x));
|
|
97
|
+
});
|
|
98
|
+
const currentTypePolicies = await new sdk_1.Entities().get({
|
|
99
|
+
entityName: 'type-policy',
|
|
100
|
+
});
|
|
101
|
+
const currentTypePolicyByLabel = {};
|
|
102
|
+
for (const currentTypePolicy of currentTypePolicies) {
|
|
103
|
+
currentTypePolicyByLabel[currentTypePolicy.label] = currentTypePolicy;
|
|
104
|
+
}
|
|
105
|
+
const loadedTypePolicyByName = {};
|
|
106
|
+
for (const loadedTPP of reducedTypePolicies) {
|
|
107
|
+
loadedTypePolicyByName[loadedTPP.label] = loadedTPP;
|
|
108
|
+
}
|
|
109
|
+
for (const [label, loadedTPP] of Object.entries(loadedTypePolicyByName)) {
|
|
110
|
+
try {
|
|
111
|
+
const found = currentTypePolicyByLabel[label];
|
|
112
|
+
if (!found) {
|
|
113
|
+
console.log('Creating: ', label);
|
|
114
|
+
await new sdk_1.Entities().create({
|
|
115
|
+
entityName: 'type-policy',
|
|
116
|
+
object: loadedTPP
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.log('Updating: ', label);
|
|
121
|
+
await new sdk_1.Entities().update({
|
|
122
|
+
entityName: 'type-policy',
|
|
123
|
+
id: found.id,
|
|
124
|
+
object: loadedTPP,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
throw new Error(`Error Uploading Type Policy: ${err}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const [label, currentTPP] of Object.entries(currentTypePolicyByLabel)) {
|
|
133
|
+
try {
|
|
134
|
+
const found = loadedTypePolicyByName[label];
|
|
135
|
+
if (!found) {
|
|
136
|
+
console.log('Deleting: ', label);
|
|
137
|
+
await new sdk_1.Entities().delete({
|
|
138
|
+
entityName: 'type-policy',
|
|
139
|
+
id: currentTPP['id'],
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
throw new Error(`Error Type Policy: ${err}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
|
|
149
|
+
const types = await (0, type_extractor_1.getTypes)();
|
|
150
|
+
const currentTypePolicies = await new sdk_1.Entities().get({
|
|
151
|
+
entityName: 'type-policy',
|
|
152
|
+
});
|
|
153
|
+
const currentTypePolicyLinks = await new sdk_1.Entities().get({
|
|
154
|
+
entityName: 'type-policy-link',
|
|
155
|
+
});
|
|
156
|
+
const currentLinksHashes = {};
|
|
157
|
+
for (const currentLink of currentTypePolicyLinks) {
|
|
158
|
+
const foundType = types.find(type => type.id === currentLink.typeId);
|
|
159
|
+
const foundTypePolicy = currentTypePolicies.find(tp => tp.id === currentLink.typePolicyId);
|
|
160
|
+
if (!foundType || !foundTypePolicy) {
|
|
161
|
+
console.log('skipping unhashable, invalid policy link:', currentLink);
|
|
162
|
+
}
|
|
163
|
+
const hash = `${foundType.slug}|${foundTypePolicy.label}`;
|
|
164
|
+
currentLinksHashes[hash] = currentLink;
|
|
165
|
+
}
|
|
166
|
+
const reducedLinksByHashes = {};
|
|
167
|
+
for (const loadedLink of reducedTypePolicyLinks) {
|
|
168
|
+
const hash = `${loadedLink.typeSlug}|${loadedLink.typePolicyLabel}`;
|
|
169
|
+
reducedLinksByHashes[hash] = loadedLink;
|
|
170
|
+
}
|
|
171
|
+
for (const loadedTPLink of reducedTypePolicyLinks) {
|
|
172
|
+
try {
|
|
173
|
+
const found = currentLinksHashes[`${loadedTPLink.typeSlug}|${loadedTPLink.typePolicyLabel}`];
|
|
174
|
+
if (!found) {
|
|
175
|
+
if (!transformReducedLink(loadedTPLink, types, currentTypePolicies)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
await new sdk_1.Entities().create({
|
|
179
|
+
entityName: 'type-policy-link',
|
|
180
|
+
object: {
|
|
181
|
+
typePolicyId: loadedTPLink.typePolicyId,
|
|
182
|
+
typeId: loadedTPLink.typeId,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
if (!transformReducedLink(loadedTPLink, types, currentTypePolicies)) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
throw new Error(`Error Uploading type policy links: ${err}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const [currentLinkHash, currentLink] of Object.entries(currentLinksHashes)) {
|
|
197
|
+
try {
|
|
198
|
+
const found = reducedLinksByHashes[currentLinkHash];
|
|
199
|
+
if (!found) {
|
|
200
|
+
console.log('Deleting: ', currentLinkHash);
|
|
201
|
+
await new sdk_1.Entities().delete({
|
|
202
|
+
entityName: 'type-policy-link',
|
|
203
|
+
id: currentLink['id'],
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
throw new Error(`Error Deleting rule set link: ${err}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function transformReducedLink(typePolicyLink, types, typePolicies) {
|
|
213
|
+
const foundType = types.find(type => type.slug === typePolicyLink.typeSlug);
|
|
214
|
+
if (!foundType) {
|
|
215
|
+
console.error('Could not find type with slug', typePolicyLink.typeSlug);
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
typePolicyLink.typeId = foundType.id;
|
|
219
|
+
const foundTypePolicy = typePolicies.find(tpp => tpp.label === typePolicyLink.typePolicyLabel);
|
|
220
|
+
if (!foundTypePolicy) {
|
|
221
|
+
console.error('Could not find type policy with label', typePolicyLink.typePolicyLabel);
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
typePolicyLink.typePolicyId = foundTypePolicy.id;
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
@@ -37,6 +37,8 @@ async function uploadTypePropertyPolicies(dir) {
|
|
|
37
37
|
}
|
|
38
38
|
catch (e) {
|
|
39
39
|
console.log(`%s Type Property Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
|
|
40
|
+
//TODO make this only print if a debug flag is set
|
|
41
|
+
console.trace(e);
|
|
40
42
|
return;
|
|
41
43
|
}
|
|
42
44
|
console.log('%s Type Property Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
|
|
@@ -147,10 +149,16 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
|
|
|
147
149
|
}
|
|
148
150
|
async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
149
151
|
const typesWithProperties = await (0, type_extractor_1.getTypes)();
|
|
150
|
-
const typeProperties =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
const typeProperties = [];
|
|
153
|
+
typesWithProperties.forEach(type => {
|
|
154
|
+
if (type.typeProperties) {
|
|
155
|
+
for (const tp of type.typeProperties) {
|
|
156
|
+
tp.typeId = type.id;
|
|
157
|
+
tp.typeSlug = type.slug;
|
|
158
|
+
typeProperties.push(tp);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
154
162
|
const currentTPPs = await new sdk_1.Entities().get({
|
|
155
163
|
entityName: 'type-property-policy',
|
|
156
164
|
});
|
|
@@ -164,17 +172,17 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
164
172
|
if (!foundTypeProperty || !foundTPP) {
|
|
165
173
|
console.log('skipping unhashable, invalid policy link:', currentLink);
|
|
166
174
|
}
|
|
167
|
-
const hash = `${foundTypeProperty.slug}|${foundTPP.label}`;
|
|
175
|
+
const hash = `${foundTypeProperty.typeSlug}${foundTypeProperty.slug}|${foundTPP.label}`;
|
|
168
176
|
currentLinksHashes[hash] = currentLink;
|
|
169
177
|
}
|
|
170
178
|
const reducedLinksByHashes = {};
|
|
171
179
|
for (const loadedLink of reducedTypePropertyPolicyLinks) {
|
|
172
|
-
const hash = `${loadedLink.typePropertySlug}|${loadedLink.typePropertyPolicyLabel}`;
|
|
180
|
+
const hash = `${loadedLink.typeSlug}|${loadedLink.typePropertySlug}|${loadedLink.typePropertyPolicyLabel}`;
|
|
173
181
|
reducedLinksByHashes[hash] = loadedLink;
|
|
174
182
|
}
|
|
175
183
|
for (const loadedTPPLink of reducedTypePropertyPolicyLinks) {
|
|
176
184
|
try {
|
|
177
|
-
const found = currentLinksHashes[`${loadedTPPLink.typePropertySlug}|${loadedTPPLink.typePropertyPolicyLabel}`];
|
|
185
|
+
const found = currentLinksHashes[`${loadedTPPLink.typeSlug}|${loadedTPPLink.typePropertySlug}|${loadedTPPLink.typePropertyPolicyLabel}`];
|
|
178
186
|
if (!found) {
|
|
179
187
|
if (!transformReducedLink(loadedTPPLink, typeProperties, currentTPPs)) {
|
|
180
188
|
continue;
|
|
@@ -209,12 +217,12 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
|
|
|
209
217
|
}
|
|
210
218
|
}
|
|
211
219
|
catch (err) {
|
|
212
|
-
throw new Error(`Error Deleting
|
|
220
|
+
throw new Error(`Error Deleting type property policy link: ${err}`);
|
|
213
221
|
}
|
|
214
222
|
}
|
|
215
223
|
}
|
|
216
224
|
function transformReducedLink(TPPLink, typeProperties, typePropertyPolicies) {
|
|
217
|
-
const foundTP = typeProperties.find(tp => tp.slug === TPPLink.typePropertySlug);
|
|
225
|
+
const foundTP = typeProperties.find(tp => tp.slug === TPPLink.typePropertySlug && tp.typeSlug === TPPLink.typeSlug);
|
|
218
226
|
if (!foundTP) {
|
|
219
227
|
console.error('Could not find type property with label', TPPLink.typePropertySlug);
|
|
220
228
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function getTypes(): Promise<any
|
|
1
|
+
export declare function getTypes(withTypeProperties?: boolean): Promise<any>;
|
|
@@ -6,13 +6,16 @@ const sdk_1 = require("@contrail/sdk");
|
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const p_limit_1 = tslib_1.__importDefault(require("p-limit"));
|
|
8
8
|
const limit = (0, p_limit_1.default)(30);
|
|
9
|
-
async function getTypes() {
|
|
9
|
+
async function getTypes(withTypeProperties = true) {
|
|
10
10
|
console.log('%s Retrieving', chalk_1.default.yellow.bold('TYPES'));
|
|
11
11
|
const entitiesClient = new sdk_1.Entities();
|
|
12
12
|
const types = await entitiesClient.get({
|
|
13
13
|
entityName: 'type',
|
|
14
14
|
});
|
|
15
15
|
console.log(`${chalk_1.default.yellow.bold('TYPES')} Found ${types.length} types`);
|
|
16
|
+
if (!withTypeProperties) {
|
|
17
|
+
return types;
|
|
18
|
+
}
|
|
16
19
|
const typesWithProperties = [];
|
|
17
20
|
const promises = [];
|
|
18
21
|
for (const type of types) {
|
|
@@ -78,7 +78,8 @@ async function uploadReducedTypes(dir) {
|
|
|
78
78
|
isArchived: type.isArchived,
|
|
79
79
|
},
|
|
80
80
|
});
|
|
81
|
-
await
|
|
81
|
+
const newTypeProperties = (await new sdk_1.Types().getType({ id: createdType.id })).typeProperties;
|
|
82
|
+
await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties);
|
|
82
83
|
}
|
|
83
84
|
else {
|
|
84
85
|
console.log('Updating Type: ', type.slug);
|
|
@@ -148,11 +149,13 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
148
149
|
core: newPropertyType.core,
|
|
149
150
|
typePropertyOptionSetId: optionSetIdByName[newPropertyType.typePropertyOptionSetName],
|
|
150
151
|
formula: newPropertyType.formula,
|
|
152
|
+
referencedTypePath: newPropertyType.referencedTypePath,
|
|
151
153
|
referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug,
|
|
152
154
|
defaultValue: newPropertyType.defaultValue,
|
|
153
155
|
propertyLevel: newPropertyType.propertyLevel,
|
|
154
156
|
formulaFunction: newPropertyType.formulaFunction,
|
|
155
157
|
validationFunction: newPropertyType.validationFunction,
|
|
158
|
+
numberFormat: newPropertyType.numberFormat,
|
|
156
159
|
}),
|
|
157
160
|
headers: {
|
|
158
161
|
Accept: 'application/json',
|
|
@@ -175,11 +178,13 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
175
178
|
core: newPropertyType.core,
|
|
176
179
|
typePropertyOptionSetId: optionSetIdByName[newPropertyType.typePropertyOptionSetName],
|
|
177
180
|
formula: newPropertyType.formula,
|
|
181
|
+
referencedTypePath: newPropertyType.referencedTypePath,
|
|
178
182
|
referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug,
|
|
179
183
|
defaultValue: newPropertyType.defaultValue,
|
|
180
184
|
propertyLevel: newPropertyType.propertyLevel,
|
|
181
185
|
formulaFunction: newPropertyType.formulaFunction,
|
|
182
186
|
validationFunction: newPropertyType.validationFunction,
|
|
187
|
+
numberFormat: newPropertyType.numberFormat,
|
|
183
188
|
},
|
|
184
189
|
});
|
|
185
190
|
}
|
|
@@ -218,11 +223,13 @@ function typePropertiesEqual(typeProperty1, typeProperty2, optionSetIdByName) {
|
|
|
218
223
|
core: typeProperty1.core,
|
|
219
224
|
typePropertyOptionSetId: optionSetIdByName[typeProperty1.typePropertyOptionSetName],
|
|
220
225
|
formula: typeProperty1.formula,
|
|
226
|
+
referencedTypePath: typeProperty1.referencedTypePath,
|
|
221
227
|
referencedTypeRootSlug: typeProperty1.referencedTypeRootSlug,
|
|
222
228
|
defaultValue: typeProperty1.defaultValue,
|
|
223
229
|
propertyLevel: typeProperty1.propertyLevel,
|
|
224
230
|
formulaFunction: typeProperty1.formulaFunction,
|
|
225
231
|
validationFunction: typeProperty1.validationFunction,
|
|
232
|
+
numberFormat: typeProperty1.numberFormat,
|
|
226
233
|
};
|
|
227
234
|
const reducedProperty2 = {
|
|
228
235
|
isArchived: typeProperty2.isArchived,
|
|
@@ -234,11 +241,13 @@ function typePropertiesEqual(typeProperty1, typeProperty2, optionSetIdByName) {
|
|
|
234
241
|
core: typeProperty2.core,
|
|
235
242
|
typePropertyOptionSetId: optionSetIdByName[typeProperty2.typePropertyOptionSetName],
|
|
236
243
|
formula: typeProperty2.formula,
|
|
244
|
+
referencedTypePath: typeProperty2.referencedTypePath,
|
|
237
245
|
referencedTypeRootSlug: typeProperty2.referencedTypeRootSlug,
|
|
238
246
|
defaultValue: typeProperty2.defaultValue,
|
|
239
247
|
propertyLevel: typeProperty2.propertyLevel,
|
|
240
248
|
formulaFunction: typeProperty2.formulaFunction,
|
|
241
249
|
validationFunction: typeProperty2.validationFunction,
|
|
250
|
+
numberFormat: typeProperty2.numberFormat,
|
|
242
251
|
};
|
|
243
252
|
return _.isEqual(reducedProperty1, reducedProperty2);
|
|
244
253
|
}
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc",
|
|
15
|
-
"start": "nodemon --watch \"src/**/*.ts\" --exec ts-node src/
|
|
16
|
-
"debug": "nodemon -r ts-node/register --inspect=127.0.0.1:60002 --watch 'actions/**/*.ts' --exec node src/
|
|
15
|
+
"start": "nodemon --watch \"src/**/*.ts\" --exec ts-node src/main.ts",
|
|
16
|
+
"debug": "nodemon -r ts-node/register --inspect=127.0.0.1:60002 --watch 'actions/**/*.ts' --exec node src/main.ts",
|
|
17
17
|
"lint": "eslint . --fix",
|
|
18
18
|
"test": "jest",
|
|
19
19
|
"test-watch": "jest --watch"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"author": "",
|
|
23
23
|
"license": "ISC",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@contrail/app-framework": "^1.0.
|
|
25
|
+
"@contrail/app-framework": "^1.0.9",
|
|
26
26
|
"@contrail/sdk": "^1.1.54",
|
|
27
27
|
"chalk": "^4.0.0",
|
|
28
28
|
"js-yaml": "^4.1.0"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContrailAppModule, loadAppConfig, registerAppInfo, runMockServer, AppActionRequest, AppActionResponse, ActionDispatcher } from '@contrail/app-framework';
|
|
1
|
+
import { ContrailAppModule, loadAppConfig, registerAppInfo, runMockServer, AppActionRequest, AppActionResponse, ActionDispatcher, GLOBAL_ACTION_REGISTRY } from '@contrail/app-framework';
|
|
2
2
|
|
|
3
3
|
// we can't use static import here. Require only
|
|
4
4
|
import fs from 'fs';
|
|
@@ -18,11 +18,18 @@ export class AppModule extends ContrailAppModule {
|
|
|
18
18
|
|
|
19
19
|
// register app's actions
|
|
20
20
|
for (const file of fs.readdirSync(path.join(__dirname, 'actions'))) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// only parse js and ts file, avoid property files
|
|
22
|
+
if (
|
|
23
|
+
file.endsWith('.js') ||
|
|
24
|
+
(file.endsWith('.ts') && !file.endsWith('.d.ts'))
|
|
25
|
+
) {
|
|
26
|
+
require(path.join(__dirname, 'actions', file));
|
|
23
27
|
}
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log(`Registered ${Object.keys(GLOBAL_ACTION_REGISTRY).length} action(s):`);
|
|
31
|
+
for(const key of Object.keys(GLOBAL_ACTION_REGISTRY)) {
|
|
32
|
+
console.log(`\t- ${appConfig.appIdentifier}:${key}`);
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.1.
|
|
2
|
+
"version": "2.1.3",
|
|
3
3
|
"commands": {
|
|
4
4
|
"app:create": {
|
|
5
5
|
"id": "app:create",
|
|
@@ -556,6 +556,7 @@
|
|
|
556
556
|
"overwrite": {
|
|
557
557
|
"name": "overwrite",
|
|
558
558
|
"type": "boolean",
|
|
559
|
+
"char": "f",
|
|
559
560
|
"description": "Replaces any existing export files in outDir",
|
|
560
561
|
"required": false,
|
|
561
562
|
"allowNo": false
|
|
@@ -890,6 +891,30 @@
|
|
|
890
891
|
},
|
|
891
892
|
"args": {}
|
|
892
893
|
},
|
|
894
|
+
"types:uploadTypePolicies": {
|
|
895
|
+
"id": "types:uploadTypePolicies",
|
|
896
|
+
"description": "Upload type policies",
|
|
897
|
+
"strict": true,
|
|
898
|
+
"pluginName": "@contrail/cli",
|
|
899
|
+
"pluginAlias": "@contrail/cli",
|
|
900
|
+
"pluginType": "core",
|
|
901
|
+
"aliases": [],
|
|
902
|
+
"examples": [
|
|
903
|
+
"$ contrail types UploadTypePolicies\n"
|
|
904
|
+
],
|
|
905
|
+
"flags": {
|
|
906
|
+
"dir": {
|
|
907
|
+
"name": "dir",
|
|
908
|
+
"type": "option",
|
|
909
|
+
"char": "d",
|
|
910
|
+
"description": "The directory from which to export the type policy data. Defaults to the current directory. The type policy data will be loaded from $dir/type-policies/*.yml",
|
|
911
|
+
"required": false,
|
|
912
|
+
"multiple": false,
|
|
913
|
+
"default": "."
|
|
914
|
+
}
|
|
915
|
+
},
|
|
916
|
+
"args": {}
|
|
917
|
+
},
|
|
893
918
|
"types:uploadTypePropertyPolicies": {
|
|
894
919
|
"id": "types:uploadTypePropertyPolicies",
|
|
895
920
|
"description": "Upload type property policies",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "VibeIQ's Contrail Platform CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"contrail-cli": "./bin/run",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"/oclif.manifest.json"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@contrail/sdk": "^1.2.
|
|
25
|
+
"@contrail/sdk": "^1.2.3",
|
|
26
26
|
"@contrail/types": "^3.0.20",
|
|
27
27
|
"@contrail/util": "^1.0.17",
|
|
28
28
|
"@oclif/core": "^2",
|