@terra-graph/conventions-aws 1.0.0-rc.1

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +25 -0
  3. package/dist/cjs/conventions/dataflow/profiles/base.js +89 -0
  4. package/dist/cjs/conventions/dataflow/profiles/dot.js +44 -0
  5. package/dist/cjs/conventions/dataflow/profiles/dot.test.js +147 -0
  6. package/dist/cjs/conventions/dataflow/rules.js +4 -0
  7. package/dist/cjs/conventions/dataflow/rules.test.js +11 -0
  8. package/dist/cjs/conventions/dataflow/rulesets.js +751 -0
  9. package/dist/cjs/conventions/dataflow/rulesets.test.js +27 -0
  10. package/dist/cjs/conventions/index.js +7 -0
  11. package/dist/cjs/conventions/index.test.js +8 -0
  12. package/dist/cjs/index.js +70 -0
  13. package/dist/cjs/index.test.js +58 -0
  14. package/dist/cjs/namespaces.js +14 -0
  15. package/dist/cjs/namespaces.test.js +17 -0
  16. package/dist/cjs/package.json +1 -0
  17. package/dist/cjs/plugins/AwsApiGateway.js +218 -0
  18. package/dist/cjs/plugins/AwsApiGateway.test.js +427 -0
  19. package/dist/cjs/plugins/AwsIam.js +432 -0
  20. package/dist/cjs/plugins/AwsIam.test.js +468 -0
  21. package/dist/cjs/plugins/AwsS3.js +107 -0
  22. package/dist/cjs/plugins/AwsS3.test.js +102 -0
  23. package/dist/cjs/plugins/AwsSns.js +52 -0
  24. package/dist/cjs/plugins/AwsSns.test.js +55 -0
  25. package/dist/cjs/plugins/AwsTransferFamily.js +105 -0
  26. package/dist/cjs/plugins/AwsTransferFamily.test.js +279 -0
  27. package/dist/cjs/rules/dot.js +36 -0
  28. package/dist/cjs/rules/dot.test.js +42 -0
  29. package/dist/cjs/rules/general.js +69 -0
  30. package/dist/cjs/rules/general.test.js +47 -0
  31. package/dist/cjs/rulesets/dot.js +25 -0
  32. package/dist/cjs/rulesets/dot.test.js +48 -0
  33. package/dist/esm/conventions/dataflow/profiles/base.d.ts +4 -0
  34. package/dist/esm/conventions/dataflow/profiles/base.js +86 -0
  35. package/dist/esm/conventions/dataflow/profiles/dot.d.ts +4 -0
  36. package/dist/esm/conventions/dataflow/profiles/dot.js +38 -0
  37. package/dist/esm/conventions/dataflow/profiles/dot.test.d.ts +1 -0
  38. package/dist/esm/conventions/dataflow/profiles/dot.test.js +109 -0
  39. package/dist/esm/conventions/dataflow/rules.d.ts +3 -0
  40. package/dist/esm/conventions/dataflow/rules.js +2 -0
  41. package/dist/esm/conventions/dataflow/rules.test.d.ts +1 -0
  42. package/dist/esm/conventions/dataflow/rules.test.js +6 -0
  43. package/dist/esm/conventions/dataflow/rulesets.d.ts +3 -0
  44. package/dist/esm/conventions/dataflow/rulesets.js +749 -0
  45. package/dist/esm/conventions/dataflow/rulesets.test.d.ts +1 -0
  46. package/dist/esm/conventions/dataflow/rulesets.test.js +22 -0
  47. package/dist/esm/conventions/index.d.ts +3 -0
  48. package/dist/esm/conventions/index.js +4 -0
  49. package/dist/esm/conventions/index.test.d.ts +1 -0
  50. package/dist/esm/conventions/index.test.js +6 -0
  51. package/dist/esm/index.d.ts +3 -0
  52. package/dist/esm/index.js +32 -0
  53. package/dist/esm/index.test.d.ts +1 -0
  54. package/dist/esm/index.test.js +53 -0
  55. package/dist/esm/namespaces.d.ts +7 -0
  56. package/dist/esm/namespaces.js +6 -0
  57. package/dist/esm/namespaces.test.d.ts +1 -0
  58. package/dist/esm/namespaces.test.js +15 -0
  59. package/dist/esm/plugins/AwsApiGateway.d.ts +6 -0
  60. package/dist/esm/plugins/AwsApiGateway.js +214 -0
  61. package/dist/esm/plugins/AwsApiGateway.test.d.ts +1 -0
  62. package/dist/esm/plugins/AwsApiGateway.test.js +425 -0
  63. package/dist/esm/plugins/AwsIam.d.ts +32 -0
  64. package/dist/esm/plugins/AwsIam.js +428 -0
  65. package/dist/esm/plugins/AwsIam.test.d.ts +1 -0
  66. package/dist/esm/plugins/AwsIam.test.js +466 -0
  67. package/dist/esm/plugins/AwsS3.d.ts +12 -0
  68. package/dist/esm/plugins/AwsS3.js +103 -0
  69. package/dist/esm/plugins/AwsS3.test.d.ts +1 -0
  70. package/dist/esm/plugins/AwsS3.test.js +100 -0
  71. package/dist/esm/plugins/AwsSns.d.ts +6 -0
  72. package/dist/esm/plugins/AwsSns.js +48 -0
  73. package/dist/esm/plugins/AwsSns.test.d.ts +1 -0
  74. package/dist/esm/plugins/AwsSns.test.js +53 -0
  75. package/dist/esm/plugins/AwsTransferFamily.d.ts +6 -0
  76. package/dist/esm/plugins/AwsTransferFamily.js +101 -0
  77. package/dist/esm/plugins/AwsTransferFamily.test.d.ts +1 -0
  78. package/dist/esm/plugins/AwsTransferFamily.test.js +277 -0
  79. package/dist/esm/rules/dot.d.ts +3 -0
  80. package/dist/esm/rules/dot.js +34 -0
  81. package/dist/esm/rules/dot.test.d.ts +1 -0
  82. package/dist/esm/rules/dot.test.js +37 -0
  83. package/dist/esm/rules/general.d.ts +3 -0
  84. package/dist/esm/rules/general.js +67 -0
  85. package/dist/esm/rules/general.test.d.ts +1 -0
  86. package/dist/esm/rules/general.test.js +42 -0
  87. package/dist/esm/rulesets/dot.d.ts +3 -0
  88. package/dist/esm/rulesets/dot.js +23 -0
  89. package/dist/esm/rulesets/dot.test.d.ts +1 -0
  90. package/dist/esm/rulesets/dot.test.js +43 -0
  91. package/package.json +45 -0
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@terra-graph/core");
4
+ const AwsIam_js_1 = require("./AwsIam.js");
5
+ const buildPhases = (options = {}) => {
6
+ const plugin = new AwsIam_js_1.AwsIamGraphPlugin();
7
+ const result = plugin.build({
8
+ options,
9
+ namedRules: new core_1.NamedRuleRegistry(),
10
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
11
+ });
12
+ return (result.phases ?? []).map((phase) => ({
13
+ phase: phase.phase,
14
+ rules: phase.rules.map((rule) => rule.serialize()),
15
+ }));
16
+ };
17
+ describe('AwsIamGraphPlugin.build', () => {
18
+ it('shoud default to a roles_only projection without semantics', () => {
19
+ const phases = buildPhases();
20
+ expect(phases).toHaveLength(5);
21
+ expect(phases.map((phase) => phase.phase)).toStrictEqual([
22
+ 'normalize',
23
+ 'main',
24
+ 'main',
25
+ 'main',
26
+ 'cleanup',
27
+ ]);
28
+ expect(phases[0]?.rules).toHaveLength(9);
29
+ expect(phases[0]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
30
+ expect(phases[1]?.rules[0]).toStrictEqual({
31
+ id: 'NodeProperties',
32
+ config: {
33
+ node: {
34
+ and: [
35
+ {
36
+ attr: {
37
+ key: 'terraform.kind',
38
+ in: ['resource', 'data'],
39
+ },
40
+ },
41
+ {
42
+ attr: {
43
+ key: 'terraform.resource',
44
+ startsWith: 'aws_iam_',
45
+ },
46
+ },
47
+ {
48
+ attr: {
49
+ key: 'terraform.moduleAddress',
50
+ exists: true,
51
+ },
52
+ },
53
+ ],
54
+ },
55
+ options: {
56
+ hints: {
57
+ label: {
58
+ end: {
59
+ from: 'terraform.name',
60
+ },
61
+ },
62
+ },
63
+ },
64
+ },
65
+ });
66
+ expect(phases[2]?.rules[0]).toStrictEqual({
67
+ id: 'RemoveNodeAndReconnectEdges',
68
+ config: {
69
+ node: {
70
+ attr: {
71
+ key: 'terraform.resource',
72
+ in: ['aws_iam_role_policy_attachment', 'aws_iam_policy_attachment'],
73
+ },
74
+ },
75
+ },
76
+ });
77
+ expect(phases[3]?.rules[0]).toStrictEqual({
78
+ id: 'RemoveNodeAndReconnectEdges',
79
+ config: {
80
+ node: {
81
+ and: [
82
+ {
83
+ attr: {
84
+ key: 'terraform.resource',
85
+ startsWith: 'aws_iam_',
86
+ },
87
+ },
88
+ {
89
+ not: {
90
+ attr: {
91
+ key: 'terraform.resource',
92
+ in: ['aws_iam_role'],
93
+ },
94
+ },
95
+ },
96
+ ],
97
+ },
98
+ },
99
+ });
100
+ expect(phases[4]?.rules).toHaveLength(9);
101
+ expect(phases[4]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
102
+ });
103
+ it('shoud keep attachments and policies when configured for roles_policies', () => {
104
+ const phases = buildPhases({
105
+ mode: 'roles_policies',
106
+ attachments: 'keep',
107
+ });
108
+ expect(phases).toHaveLength(4);
109
+ expect(phases[0]?.phase).toBe('normalize');
110
+ expect(phases[0]?.rules).toHaveLength(9);
111
+ expect(phases[1]?.phase).toBe('main');
112
+ expect(phases[1]?.rules[0]?.id).toBe('NodeProperties');
113
+ expect(phases[2]?.phase).toBe('main');
114
+ expect(phases[2]?.rules[0]).toStrictEqual({
115
+ id: 'RemoveNodeAndReconnectEdges',
116
+ config: {
117
+ node: {
118
+ and: [
119
+ {
120
+ attr: {
121
+ key: 'terraform.resource',
122
+ startsWith: 'aws_iam_',
123
+ },
124
+ },
125
+ {
126
+ not: {
127
+ attr: {
128
+ key: 'terraform.resource',
129
+ in: [
130
+ 'aws_iam_role',
131
+ 'aws_iam_policy',
132
+ 'aws_iam_role_policy',
133
+ 'aws_iam_role_policy_attachment',
134
+ 'aws_iam_policy_attachment',
135
+ ],
136
+ },
137
+ },
138
+ },
139
+ ],
140
+ },
141
+ },
142
+ });
143
+ expect(phases[3]?.phase).toBe('cleanup');
144
+ expect(phases[3]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
145
+ });
146
+ it('shoud build no phases for full mode defaults', () => {
147
+ const phases = buildPhases({
148
+ mode: 'full',
149
+ });
150
+ expect(phases).toHaveLength(3);
151
+ expect(phases[0]?.phase).toBe('normalize');
152
+ expect(phases[0]?.rules).toHaveLength(9);
153
+ expect(phases[1]?.phase).toBe('main');
154
+ expect(phases[1]?.rules[0]?.id).toBe('NodeProperties');
155
+ expect(phases[2]?.phase).toBe('cleanup');
156
+ expect(phases[2]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
157
+ });
158
+ it('shoud support convert_to_edge attachments with policy document removal in full mode', () => {
159
+ const phases = buildPhases({
160
+ mode: 'full',
161
+ attachments: 'convert_to_edge',
162
+ policyDocuments: 'none',
163
+ });
164
+ expect(phases.map((phase) => phase.phase)).toStrictEqual([
165
+ 'normalize',
166
+ 'main',
167
+ 'main',
168
+ 'main',
169
+ 'main',
170
+ 'cleanup',
171
+ ]);
172
+ expect(phases.map((phase) => phase.rules[0]?.id)).toStrictEqual([
173
+ 'EdgeReverse',
174
+ 'NodeProperties',
175
+ 'ConvertNodeToEdge',
176
+ 'RemoveNodeAndReconnectEdges',
177
+ 'RemoveNodeAndReconnectEdges',
178
+ 'EdgeReverse',
179
+ ]);
180
+ expect(phases[4]?.rules[0]).toStrictEqual({
181
+ id: 'RemoveNodeAndReconnectEdges',
182
+ config: {
183
+ node: {
184
+ attr: {
185
+ key: 'terraform.resource',
186
+ eq: 'aws_iam_policy_document',
187
+ },
188
+ },
189
+ },
190
+ });
191
+ });
192
+ it('shoud keep only trust policy documents when trust_only is configured', () => {
193
+ const phases = buildPhases({
194
+ mode: 'full',
195
+ policyDocuments: 'trust_only',
196
+ });
197
+ expect(phases).toHaveLength(4);
198
+ expect(phases[0]?.phase).toBe('normalize');
199
+ expect(phases[0]?.rules).toHaveLength(9);
200
+ expect(phases[1]?.phase).toBe('main');
201
+ expect(phases[1]?.rules[0]?.id).toBe('NodeProperties');
202
+ expect(phases[2]?.phase).toBe('main');
203
+ expect(phases[2]?.rules[0]).toStrictEqual({
204
+ id: 'RemoveNodeAndReconnectEdges',
205
+ config: {
206
+ node: {
207
+ and: [
208
+ {
209
+ attr: {
210
+ key: 'terraform.resource',
211
+ eq: 'aws_iam_policy_document',
212
+ },
213
+ },
214
+ {
215
+ not: {
216
+ or: [
217
+ {
218
+ edge: {
219
+ in: {
220
+ attr: {
221
+ key: 'terraform.resource',
222
+ eq: 'aws_iam_role',
223
+ },
224
+ },
225
+ },
226
+ },
227
+ {
228
+ edge: {
229
+ out: {
230
+ attr: {
231
+ key: 'terraform.resource',
232
+ eq: 'aws_iam_role',
233
+ },
234
+ },
235
+ },
236
+ },
237
+ ],
238
+ },
239
+ },
240
+ ],
241
+ },
242
+ },
243
+ });
244
+ expect(phases[3]?.phase).toBe('cleanup');
245
+ expect(phases[3]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
246
+ });
247
+ it('shoud keep policy documents in non-full trust_only mode', () => {
248
+ const phases = buildPhases({
249
+ mode: 'roles_only',
250
+ policyDocuments: 'trust_only',
251
+ });
252
+ expect(phases.map((phase) => phase.phase)).toStrictEqual([
253
+ 'normalize',
254
+ 'main',
255
+ 'main',
256
+ 'main',
257
+ 'main',
258
+ 'cleanup',
259
+ ]);
260
+ expect(phases[3]?.rules[0]).toStrictEqual({
261
+ id: 'RemoveNodeAndReconnectEdges',
262
+ config: {
263
+ node: {
264
+ and: [
265
+ {
266
+ attr: {
267
+ key: 'terraform.resource',
268
+ startsWith: 'aws_iam_',
269
+ },
270
+ },
271
+ {
272
+ not: {
273
+ attr: {
274
+ key: 'terraform.resource',
275
+ in: ['aws_iam_role', 'aws_iam_policy_document'],
276
+ },
277
+ },
278
+ },
279
+ ],
280
+ },
281
+ },
282
+ });
283
+ expect(phases[4]?.rules[0]).toStrictEqual({
284
+ id: 'RemoveNodeAndReconnectEdges',
285
+ config: {
286
+ node: {
287
+ and: [
288
+ {
289
+ attr: {
290
+ key: 'terraform.resource',
291
+ eq: 'aws_iam_policy_document',
292
+ },
293
+ },
294
+ {
295
+ not: {
296
+ or: [
297
+ {
298
+ edge: {
299
+ in: {
300
+ attr: {
301
+ key: 'terraform.resource',
302
+ eq: 'aws_iam_role',
303
+ },
304
+ },
305
+ },
306
+ },
307
+ {
308
+ edge: {
309
+ out: {
310
+ attr: {
311
+ key: 'terraform.resource',
312
+ eq: 'aws_iam_role',
313
+ },
314
+ },
315
+ },
316
+ },
317
+ ],
318
+ },
319
+ },
320
+ ],
321
+ },
322
+ },
323
+ });
324
+ });
325
+ it('shoud throw for invalid option values', () => {
326
+ const plugin = new AwsIam_js_1.AwsIamGraphPlugin();
327
+ expect(() => plugin.build({
328
+ options: { mode: 'invalid' },
329
+ namedRules: new core_1.NamedRuleRegistry(),
330
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
331
+ })).toThrow(`${AwsIam_js_1.AwsIamGraphPlugin.id} options.mode must be one of: roles_only, roles_policies, full`);
332
+ expect(() => plugin.build({
333
+ options: {
334
+ removeOrphans: 'yes',
335
+ },
336
+ namedRules: new core_1.NamedRuleRegistry(),
337
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
338
+ })).toThrow(`${AwsIam_js_1.AwsIamGraphPlugin.id} options.removeOrphans must be a boolean`);
339
+ });
340
+ it('shoud throw for invalid attachment mode values', () => {
341
+ const plugin = new AwsIam_js_1.AwsIamGraphPlugin();
342
+ expect(() => plugin.build({
343
+ options: {
344
+ attachments: 'invalid',
345
+ },
346
+ namedRules: new core_1.NamedRuleRegistry(),
347
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
348
+ })).toThrow(`${AwsIam_js_1.AwsIamGraphPlugin.id} options.attachments must be one of: remove, convert_to_edge, keep`);
349
+ });
350
+ it('shoud throw for invalid policy document mode values', () => {
351
+ const plugin = new AwsIam_js_1.AwsIamGraphPlugin();
352
+ expect(() => plugin.build({
353
+ options: {
354
+ policyDocuments: 'invalid',
355
+ },
356
+ namedRules: new core_1.NamedRuleRegistry(),
357
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
358
+ })).toThrow(`${AwsIam_js_1.AwsIamGraphPlugin.id} options.policyDocuments must be one of: none, trust_only, all`);
359
+ });
360
+ it('shoud keep attachment resources when full mode is configured as keep', () => {
361
+ const phases = buildPhases({
362
+ mode: 'full',
363
+ attachments: 'keep',
364
+ });
365
+ expect(phases).toHaveLength(3);
366
+ expect(phases.map((phase) => phase.phase)).toStrictEqual(['normalize', 'main', 'cleanup']);
367
+ expect(phases[1]?.rules).toHaveLength(1);
368
+ expect(phases[1]?.rules[0]?.id).toBe('NodeProperties');
369
+ expect(phases[2]?.rules).toHaveLength(9);
370
+ expect(phases[2]?.rules.every((rule) => rule.id === 'EdgeReverse')).toBe(true);
371
+ });
372
+ it('shoud remove attachment nodes explicitly when full mode uses remove', () => {
373
+ const phases = buildPhases({
374
+ mode: 'full',
375
+ attachments: 'remove',
376
+ });
377
+ expect(phases).toHaveLength(4);
378
+ expect(phases.map((phase) => phase.phase)).toStrictEqual([
379
+ 'normalize',
380
+ 'main',
381
+ 'main',
382
+ 'cleanup',
383
+ ]);
384
+ expect(phases[2]?.rules[0]).toStrictEqual({
385
+ id: 'RemoveNodeAndReconnectEdges',
386
+ config: {
387
+ node: {
388
+ attr: {
389
+ key: 'terraform.resource',
390
+ in: ['aws_iam_role_policy_attachment', 'aws_iam_policy_attachment'],
391
+ },
392
+ },
393
+ },
394
+ });
395
+ });
396
+ it('shoud add a final orphan cleanup phase when removeOrphans is enabled', () => {
397
+ const phases = buildPhases({
398
+ mode: 'roles_only',
399
+ removeOrphans: true,
400
+ });
401
+ expect(phases).toHaveLength(6);
402
+ expect(phases.map((phase) => phase.phase)).toStrictEqual([
403
+ 'normalize',
404
+ 'main',
405
+ 'main',
406
+ 'main',
407
+ 'cleanup',
408
+ 'cleanup',
409
+ ]);
410
+ expect(phases[5]?.rules[0]).toStrictEqual({
411
+ id: 'RemoveLeafChain',
412
+ config: {
413
+ node: {
414
+ or: [
415
+ {
416
+ and: [
417
+ {
418
+ attr: {
419
+ key: 'terraform.kind',
420
+ eq: 'resource',
421
+ },
422
+ },
423
+ {
424
+ attr: {
425
+ key: 'terraform.resource',
426
+ in: [
427
+ 'aws_iam_role',
428
+ 'aws_iam_policy',
429
+ 'aws_iam_role_policy',
430
+ 'aws_iam_role_policy_attachment',
431
+ 'aws_iam_policy_attachment',
432
+ ],
433
+ },
434
+ },
435
+ ],
436
+ },
437
+ {
438
+ and: [
439
+ {
440
+ attr: {
441
+ key: 'terraform.kind',
442
+ eq: 'data',
443
+ },
444
+ },
445
+ {
446
+ attr: {
447
+ key: 'terraform.resource',
448
+ in: ['aws_iam_policy_document', 'aws_iam_policy'],
449
+ },
450
+ },
451
+ ],
452
+ },
453
+ ],
454
+ },
455
+ },
456
+ });
457
+ });
458
+ it('shoud not add orphan cleanup when removeOrphans is false', () => {
459
+ const phases = buildPhases({
460
+ mode: 'roles_only',
461
+ removeOrphans: false,
462
+ });
463
+ expect(phases).toHaveLength(5);
464
+ expect(phases.map((phase) => phase.phase)).toContain('cleanup');
465
+ expect(phases.map((phase) => phase.rules[0]?.id)).not.toContain('RemoveLeafChain');
466
+ expect(phases[4]?.rules[0]?.id).toBe('EdgeReverse');
467
+ });
468
+ });
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AwsS3 = void 0;
4
+ const core_1 = require("@terra-graph/core");
5
+ const namespaces_js_1 = require("../namespaces.js");
6
+ const S3_DEFAULT_KEEP_RESOURCES = ['aws_s3_bucket', 'aws_s3_bucket_notification'];
7
+ // TODO: this feels like part of conventions not a usefule plugin
8
+ class AwsS3 extends core_1.GraphPlugin {
9
+ static id = (0, namespaces_js_1.pluginId)(`aws.${AwsS3.name}`);
10
+ constructor(options = {}) {
11
+ const keepResources = Array.isArray(options.keepResources)
12
+ ? options.keepResources
13
+ : S3_DEFAULT_KEEP_RESOURCES;
14
+ super(AwsS3.id, {
15
+ keepResources: [...keepResources],
16
+ });
17
+ }
18
+ build({ options, }) {
19
+ const keepResources = Array.isArray(options.keepResources)
20
+ ? options.keepResources
21
+ : S3_DEFAULT_KEEP_RESOURCES;
22
+ return {
23
+ phases: [
24
+ {
25
+ phase: 'pre',
26
+ rules: [
27
+ new core_1.RemoveNodeAndReconnectEdges({
28
+ node: {
29
+ and: [
30
+ {
31
+ attr: {
32
+ key: 'terraform.resource',
33
+ startsWith: 'aws_s3_',
34
+ },
35
+ },
36
+ {
37
+ not: {
38
+ attr: {
39
+ key: 'terraform.resource',
40
+ in: keepResources,
41
+ },
42
+ },
43
+ },
44
+ ],
45
+ },
46
+ }),
47
+ // new EdgeReverse({
48
+ // edge: {
49
+ // from: {
50
+ // attr: {
51
+ // key: 'terraform.resource',
52
+ // eq: 'aws_s3_bucket',
53
+ // },
54
+ // },
55
+ // to: {
56
+ // attr: {
57
+ // key: 'terraform.resource',
58
+ // eq: 'aws_s3_bucket_notification',
59
+ // },
60
+ // },
61
+ // },
62
+ // }),
63
+ ],
64
+ },
65
+ {
66
+ phase: 'pre',
67
+ rules: [
68
+ new core_1.RemoveNode({
69
+ node: {
70
+ and: [
71
+ {
72
+ attr: {
73
+ key: 'terraform.resource',
74
+ eq: 'aws_s3_bucket_object',
75
+ },
76
+ },
77
+ {
78
+ not: {
79
+ attr: {
80
+ key: 'terraform.resource',
81
+ in: keepResources,
82
+ },
83
+ },
84
+ },
85
+ ],
86
+ },
87
+ }),
88
+ ],
89
+ },
90
+ {
91
+ phase: 'main',
92
+ rules: [
93
+ // new ConvertNodeToEdge({
94
+ // node: {
95
+ // attr: {
96
+ // key: 'terraform.resource',
97
+ // eq: 'aws_s3_bucket_notification',
98
+ // },
99
+ // },
100
+ // }),
101
+ ],
102
+ },
103
+ ],
104
+ };
105
+ }
106
+ }
107
+ exports.AwsS3 = AwsS3;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@terra-graph/core");
4
+ const AwsS3_js_1 = require("./AwsS3.js");
5
+ const buildPhases = (options = {}) => {
6
+ const plugin = new AwsS3_js_1.AwsS3();
7
+ const result = plugin.build({
8
+ options,
9
+ namedRules: new core_1.NamedRuleRegistry(),
10
+ namedRuleSets: new core_1.NamedRuleSetRegistry(),
11
+ });
12
+ return (result.phases ?? []).map((phase) => ({
13
+ phase: phase.phase,
14
+ rules: phase.rules.map((rule) => rule.serialize()),
15
+ }));
16
+ };
17
+ describe('AwsS3.build', () => {
18
+ it('shoud remove non-default s3 resources and keep aws_s3_bucket and notifications', () => {
19
+ const phases = buildPhases();
20
+ expect(phases).toHaveLength(3);
21
+ expect(phases.map((phase) => phase.phase)).toStrictEqual(['pre', 'pre', 'main']);
22
+ expect(phases[0]?.rules[0]).toStrictEqual({
23
+ id: 'RemoveNodeAndReconnectEdges',
24
+ config: {
25
+ node: {
26
+ and: [
27
+ {
28
+ attr: {
29
+ key: 'terraform.resource',
30
+ startsWith: 'aws_s3_',
31
+ },
32
+ },
33
+ {
34
+ not: {
35
+ attr: {
36
+ key: 'terraform.resource',
37
+ in: ['aws_s3_bucket', 'aws_s3_bucket_notification'],
38
+ },
39
+ },
40
+ },
41
+ ],
42
+ },
43
+ },
44
+ });
45
+ expect(phases[1]?.rules[0]).toStrictEqual({
46
+ id: 'RemoveNode',
47
+ config: {
48
+ node: {
49
+ and: [
50
+ {
51
+ attr: {
52
+ key: 'terraform.resource',
53
+ eq: 'aws_s3_bucket_object',
54
+ },
55
+ },
56
+ {
57
+ not: {
58
+ attr: {
59
+ key: 'terraform.resource',
60
+ in: ['aws_s3_bucket', 'aws_s3_bucket_notification'],
61
+ },
62
+ },
63
+ },
64
+ ],
65
+ },
66
+ },
67
+ });
68
+ expect(phases[2]?.rules).toHaveLength(0);
69
+ });
70
+ it('shoud keep custom resources when keepResources is configured', () => {
71
+ const keepResources = ['aws_s3_bucket', 'aws_s3_access_point'];
72
+ const phases = buildPhases({ keepResources });
73
+ expect(phases[0]?.rules[0]).toStrictEqual({
74
+ id: 'RemoveNodeAndReconnectEdges',
75
+ config: {
76
+ node: {
77
+ and: [
78
+ {
79
+ attr: {
80
+ key: 'terraform.resource',
81
+ startsWith: 'aws_s3_',
82
+ },
83
+ },
84
+ {
85
+ not: {
86
+ attr: {
87
+ key: 'terraform.resource',
88
+ in: keepResources,
89
+ },
90
+ },
91
+ },
92
+ ],
93
+ },
94
+ },
95
+ });
96
+ });
97
+ it('shoud use custom constructor keepResources when provided', () => {
98
+ const keepResources = ['aws_s3_bucket', 'aws_s3_bucket_notification', 'aws_s3_access_point'];
99
+ const plugin = new AwsS3_js_1.AwsS3({ keepResources });
100
+ expect(plugin.defaults).toStrictEqual({ keepResources });
101
+ });
102
+ });