codify-plugin-lib 1.0.75 → 1.0.77
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/.eslintrc.json +11 -4
- package/.github/workflows/release.yaml +19 -0
- package/.github/workflows/unit-test-ci.yaml +19 -0
- package/dist/entities/plugin.d.ts +1 -1
- package/dist/entities/plugin.js +5 -5
- package/dist/entities/resource-options.d.ts +6 -6
- package/dist/entities/resource-options.js +7 -9
- package/dist/entities/resource.d.ts +2 -3
- package/dist/entities/resource.js +2 -2
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +7 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +9 -9
- package/dist/messages/handlers.d.ts +1 -1
- package/dist/messages/handlers.js +25 -24
- package/dist/plan/change-set.d.ts +37 -0
- package/dist/plan/change-set.js +146 -0
- package/dist/plan/plan-types.d.ts +23 -0
- package/dist/plan/plan-types.js +1 -0
- package/dist/plan/plan.d.ts +59 -0
- package/dist/plan/plan.js +228 -0
- package/dist/plugin/plugin.d.ts +17 -0
- package/dist/plugin/plugin.js +83 -0
- package/dist/resource/config-parser.d.ts +14 -0
- package/dist/resource/config-parser.js +48 -0
- package/dist/resource/parsed-resource-settings.d.ts +26 -0
- package/dist/resource/parsed-resource-settings.js +126 -0
- package/dist/resource/resource-controller.d.ts +30 -0
- package/dist/resource/resource-controller.js +247 -0
- package/dist/resource/resource-settings.d.ts +149 -0
- package/dist/resource/resource-settings.js +9 -0
- package/dist/resource/resource.d.ts +137 -0
- package/dist/resource/resource.js +44 -0
- package/dist/resource/stateful-parameter.d.ts +164 -0
- package/dist/resource/stateful-parameter.js +94 -0
- package/dist/utils/utils.d.ts +19 -3
- package/dist/utils/utils.js +52 -3
- package/package.json +6 -4
- package/src/index.ts +10 -11
- package/src/messages/handlers.test.ts +21 -42
- package/src/messages/handlers.ts +28 -27
- package/src/plan/change-set.test.ts +220 -0
- package/src/plan/change-set.ts +225 -0
- package/src/plan/plan-types.ts +27 -0
- package/src/{entities → plan}/plan.test.ts +35 -29
- package/src/plan/plan.ts +353 -0
- package/src/{entities → plugin}/plugin.test.ts +14 -13
- package/src/{entities → plugin}/plugin.ts +32 -27
- package/src/resource/config-parser.ts +77 -0
- package/src/{entities/resource-options.test.ts → resource/parsed-resource-settings.test.ts} +8 -7
- package/src/resource/parsed-resource-settings.ts +179 -0
- package/src/{entities/resource-stateful-mode.test.ts → resource/resource-controller-stateful-mode.test.ts} +36 -39
- package/src/{entities/resource.test.ts → resource/resource-controller.test.ts} +116 -176
- package/src/resource/resource-controller.ts +340 -0
- package/src/resource/resource-settings.test.ts +494 -0
- package/src/resource/resource-settings.ts +192 -0
- package/src/resource/resource.ts +149 -0
- package/src/resource/stateful-parameter.test.ts +93 -0
- package/src/resource/stateful-parameter.ts +217 -0
- package/src/utils/test-utils.test.ts +87 -0
- package/src/utils/utils.test.ts +2 -2
- package/src/utils/utils.ts +51 -5
- package/tsconfig.json +0 -1
- package/vitest.config.ts +10 -0
- package/src/entities/change-set.test.ts +0 -155
- package/src/entities/change-set.ts +0 -244
- package/src/entities/plan-types.ts +0 -44
- package/src/entities/plan.ts +0 -178
- package/src/entities/resource-options.ts +0 -156
- package/src/entities/resource-parameters.test.ts +0 -604
- package/src/entities/resource-types.ts +0 -31
- package/src/entities/resource.ts +0 -471
- package/src/entities/stateful-parameter.test.ts +0 -114
- package/src/entities/stateful-parameter.ts +0 -92
- package/src/entities/transform-parameter.ts +0 -13
- /package/src/{entities/errors.ts → errors.ts} +0 -0
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { ArrayStatefulParameter, StatefulParameter, StatefulParameterOptions } from './stateful-parameter.js';
|
|
3
|
-
import { Plan } from './plan.js';
|
|
4
|
-
import { spy } from 'sinon';
|
|
5
|
-
import { ParameterOperation, ResourceOperation } from 'codify-schemas';
|
|
6
|
-
import { TestConfig, TestResource } from './resource.test.js';
|
|
7
|
-
import { TransformParameter } from './transform-parameter.js';
|
|
8
|
-
|
|
9
|
-
export class TestParameter extends StatefulParameter<TestConfig, string> {
|
|
10
|
-
constructor(options?: StatefulParameterOptions<string>) {
|
|
11
|
-
super(options ?? {})
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
applyAdd(valueToAdd: string, plan: Plan<TestConfig>): Promise<void> {
|
|
15
|
-
return Promise.resolve();
|
|
16
|
-
}
|
|
17
|
-
applyModify(newValue: string, previousValue: string, allowDeletes: boolean, plan: Plan<TestConfig>): Promise<void> {
|
|
18
|
-
return Promise.resolve();
|
|
19
|
-
}
|
|
20
|
-
applyRemove(valueToRemove: string, plan: Plan<TestConfig>): Promise<void> {
|
|
21
|
-
return Promise.resolve();
|
|
22
|
-
}
|
|
23
|
-
async refresh(): Promise<string | null> {
|
|
24
|
-
return '';
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
describe('Resource parameter tests', () => {
|
|
29
|
-
it ('Generates a resource plan that includes stateful parameters (create)', async () => {
|
|
30
|
-
const statefulParameter = spy(new class extends TestParameter {
|
|
31
|
-
async refresh(): Promise<string | null> {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
const resource = new class extends TestResource {
|
|
37
|
-
constructor() {
|
|
38
|
-
super({
|
|
39
|
-
type: 'resource',
|
|
40
|
-
parameterOptions: {
|
|
41
|
-
propA: { statefulParameter }
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async refresh(): Promise<any> {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const plan = await resource.plan({
|
|
52
|
-
type: 'resource',
|
|
53
|
-
propA: 'a',
|
|
54
|
-
propB: 10
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
expect(statefulParameter.refresh.notCalled).to.be.true;
|
|
58
|
-
expect(plan.currentConfig).to.be.null;
|
|
59
|
-
expect(plan.desiredConfig).toMatchObject({
|
|
60
|
-
type: 'resource',
|
|
61
|
-
propA: 'a',
|
|
62
|
-
propB: 10
|
|
63
|
-
})
|
|
64
|
-
expect(plan.changeSet.operation).to.eq(ResourceOperation.CREATE);
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('supports the creation of stateful parameters', async () => {
|
|
68
|
-
|
|
69
|
-
const statefulParameter = new class extends TestParameter {
|
|
70
|
-
async refresh(): Promise<string | null> {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const statefulParameterSpy = spy(statefulParameter);
|
|
76
|
-
|
|
77
|
-
const resource = new class extends TestResource {
|
|
78
|
-
constructor() {
|
|
79
|
-
super({
|
|
80
|
-
type: 'resource',
|
|
81
|
-
parameterOptions: {
|
|
82
|
-
propA: { statefulParameter: statefulParameterSpy }
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const resourceSpy = spy(resource);
|
|
89
|
-
const result = await resourceSpy.apply(
|
|
90
|
-
Plan.create<TestConfig>(
|
|
91
|
-
{ propA: 'a', propB: 0, propC: 'b' },
|
|
92
|
-
null,
|
|
93
|
-
{ type: 'resource' },
|
|
94
|
-
{ statefulMode: false },
|
|
95
|
-
)
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
expect(statefulParameterSpy.applyAdd.calledOnce).to.be.true;
|
|
99
|
-
expect(resourceSpy.applyCreate.calledOnce).to.be.true;
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('supports the modification of stateful parameters', async () => {
|
|
103
|
-
const statefulParameter = new class extends TestParameter {
|
|
104
|
-
async refresh(): Promise<string | null> {
|
|
105
|
-
return 'b';
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const statefulParameterSpy = spy(statefulParameter);
|
|
110
|
-
|
|
111
|
-
const resource = new class extends TestResource {
|
|
112
|
-
|
|
113
|
-
constructor() {
|
|
114
|
-
super({
|
|
115
|
-
type: 'resource',
|
|
116
|
-
parameterOptions: {
|
|
117
|
-
propA: { statefulParameter: statefulParameterSpy },
|
|
118
|
-
propB: { modifyOnChange: true },
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
124
|
-
return { propB: -1, propC: 'b' }
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const plan = await resource.plan({ type: 'resource', propA: 'a', propB: 0, propC: 'b' })
|
|
129
|
-
|
|
130
|
-
const resourceSpy = spy(resource);
|
|
131
|
-
const result = await resourceSpy.apply(plan);
|
|
132
|
-
|
|
133
|
-
expect(statefulParameterSpy.applyModify.calledOnce).to.be.true;
|
|
134
|
-
expect(resourceSpy.applyModify.calledOnce).to.be.true;
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('Allows stateful parameters to have default values', async () => {
|
|
138
|
-
const statefulParameter = spy(new class extends TestParameter {
|
|
139
|
-
constructor() {
|
|
140
|
-
super({
|
|
141
|
-
default: 'abc'
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async refresh(): Promise<string | null> {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const resource = new class extends TestResource {
|
|
151
|
-
constructor() {
|
|
152
|
-
super({
|
|
153
|
-
type: 'resource',
|
|
154
|
-
parameterOptions: {
|
|
155
|
-
propA: { statefulParameter }
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async refresh(): Promise<any> {
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const plan = await resource.plan({
|
|
166
|
-
type: 'resource',
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
expect(statefulParameter.refresh.notCalled).to.be.true;
|
|
170
|
-
expect(plan.currentConfig).to.be.null;
|
|
171
|
-
expect(plan.desiredConfig).toMatchObject({
|
|
172
|
-
type: 'resource',
|
|
173
|
-
propA: 'abc',
|
|
174
|
-
})
|
|
175
|
-
expect(plan.changeSet.operation).to.eq(ResourceOperation.CREATE);
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it('Filters array results in stateless mode to prevent modify from being called', async () => {
|
|
179
|
-
const statefulParameter = new class extends TestParameter {
|
|
180
|
-
async refresh(): Promise<any | null> {
|
|
181
|
-
return ['a', 'b', 'c', 'd']
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const statefulParameterSpy = spy(statefulParameter);
|
|
186
|
-
|
|
187
|
-
const resource = new class extends TestResource {
|
|
188
|
-
constructor() {
|
|
189
|
-
super({
|
|
190
|
-
type: 'resource',
|
|
191
|
-
parameterOptions: {
|
|
192
|
-
propA: { statefulParameter: statefulParameterSpy },
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
198
|
-
return {};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const plan = await resource.plan({ type: 'resource', propA: ['a', 'b'] } as any)
|
|
203
|
-
|
|
204
|
-
expect(plan).toMatchObject({
|
|
205
|
-
changeSet: {
|
|
206
|
-
operation: ResourceOperation.NOOP,
|
|
207
|
-
}
|
|
208
|
-
})
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('Filters array results in stateless mode to prevent modify from being called', async () => {
|
|
212
|
-
const statefulParameter = new class extends TestParameter {
|
|
213
|
-
async refresh(): Promise<any | null> {
|
|
214
|
-
return ['a', 'b']
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const statefulParameterSpy = spy(statefulParameter);
|
|
219
|
-
|
|
220
|
-
const resource = new class extends TestResource {
|
|
221
|
-
constructor() {
|
|
222
|
-
super({
|
|
223
|
-
type: 'resource',
|
|
224
|
-
parameterOptions: {
|
|
225
|
-
propA: { statefulParameter: statefulParameterSpy }
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
231
|
-
return {};
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const plan = await resource.plan({ type: 'resource', propA: ['a', 'b', 'c', 'd'] } as any)
|
|
236
|
-
|
|
237
|
-
expect(plan).toMatchObject({
|
|
238
|
-
changeSet: {
|
|
239
|
-
operation: ResourceOperation.MODIFY,
|
|
240
|
-
}
|
|
241
|
-
})
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
it('Uses isElementEqual for stateless mode filtering if available', async () => {
|
|
245
|
-
const statefulParameter = new class extends ArrayStatefulParameter<TestConfig, string> {
|
|
246
|
-
constructor() {
|
|
247
|
-
super({
|
|
248
|
-
isElementEqual: (desired, current) => current.includes(desired),
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async refresh(): Promise<any | null> {
|
|
253
|
-
return ['3.11.9']
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async applyAddItem(item: string, plan: Plan<TestConfig>): Promise<void> {}
|
|
257
|
-
async applyRemoveItem(item: string, plan: Plan<TestConfig>): Promise<void> {}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const statefulParameterSpy = spy(statefulParameter);
|
|
261
|
-
|
|
262
|
-
const resource = new class extends TestResource {
|
|
263
|
-
constructor() {
|
|
264
|
-
super({
|
|
265
|
-
type: 'resource',
|
|
266
|
-
parameterOptions: {
|
|
267
|
-
propA: { statefulParameter: statefulParameterSpy }
|
|
268
|
-
},
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
273
|
-
return {};
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const plan = await resource.plan({ type: 'resource', propA: ['3.11'] } as any)
|
|
278
|
-
|
|
279
|
-
expect(plan).toMatchObject({
|
|
280
|
-
changeSet: {
|
|
281
|
-
operation: ResourceOperation.NOOP,
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
it('Plans stateful parameters in the order specified', async () => {
|
|
287
|
-
const statefulParameterA = spy(new class extends TestParameter {
|
|
288
|
-
async refresh(): Promise<any | null> {
|
|
289
|
-
return performance.now()
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
const statefulParameterB = spy(new class extends TestParameter {
|
|
294
|
-
async refresh(): Promise<any | null> {
|
|
295
|
-
return performance.now()
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
const statefulParameterC = spy(new class extends TestParameter {
|
|
300
|
-
async refresh(): Promise<any | null> {
|
|
301
|
-
return performance.now()
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
const statefulParameterD = spy(new class extends TestParameter {
|
|
306
|
-
async refresh(): Promise<any | null> {
|
|
307
|
-
return performance.now()
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
const statefulParameterE = spy(new class extends TestParameter {
|
|
312
|
-
async refresh(): Promise<any | null> {
|
|
313
|
-
return performance.now()
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
const resource = spy(new class extends TestResource {
|
|
318
|
-
constructor() {
|
|
319
|
-
super({
|
|
320
|
-
type: 'resourceType',
|
|
321
|
-
parameterOptions: {
|
|
322
|
-
propA: { statefulParameter: statefulParameterA, order: 3},
|
|
323
|
-
propB: { statefulParameter: statefulParameterB, order: 1 },
|
|
324
|
-
propC: { statefulParameter: statefulParameterC, order: 2 },
|
|
325
|
-
propD: { statefulParameter: statefulParameterD },
|
|
326
|
-
propE: { statefulParameter: statefulParameterE }
|
|
327
|
-
},
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
332
|
-
return {};
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
const plan = await resource.plan({
|
|
337
|
-
type: 'resourceType',
|
|
338
|
-
propA: 'propA',
|
|
339
|
-
propB: 10,
|
|
340
|
-
propC: 'propC',
|
|
341
|
-
propD: 'propD',
|
|
342
|
-
propE: 'propE',
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
expect(plan.currentConfig?.propB).to.be.lessThan(plan.currentConfig?.propC as any);
|
|
346
|
-
expect(plan.currentConfig?.propC).to.be.lessThan(plan.currentConfig?.propA as any);
|
|
347
|
-
expect(plan.currentConfig?.propA).to.be.lessThan(plan.currentConfig?.propD as any);
|
|
348
|
-
expect(plan.currentConfig?.propD).to.be.lessThan(plan.currentConfig?.propE as any);
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
it('Applies stateful parameters in the order specified', async () => {
|
|
352
|
-
let timestampA;
|
|
353
|
-
const statefulParameterA = spy(new class extends TestParameter {
|
|
354
|
-
applyAdd = async (): Promise<void> => { timestampA = performance.now(); }
|
|
355
|
-
applyModify = async (): Promise<void> => { timestampA = performance.now(); }
|
|
356
|
-
applyRemove = async (): Promise<void> => { timestampA = performance.now(); }
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
let timestampB
|
|
360
|
-
const statefulParameterB = spy(new class extends TestParameter {
|
|
361
|
-
applyAdd = async (): Promise<void> => { timestampB = performance.now(); }
|
|
362
|
-
applyModify = async (): Promise<void> => { timestampB = performance.now(); }
|
|
363
|
-
applyRemove = async (): Promise<void> => { timestampB = performance.now(); }
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
let timestampC
|
|
367
|
-
const statefulParameterC = spy(new class extends TestParameter {
|
|
368
|
-
applyAdd = async (): Promise<void> => { timestampC = performance.now(); }
|
|
369
|
-
applyModify = async (): Promise<void> => { timestampC = performance.now(); }
|
|
370
|
-
applyRemove = async (): Promise<void> => { timestampC = performance.now(); }
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
const resource = spy(new class extends TestResource {
|
|
374
|
-
constructor() {
|
|
375
|
-
super({
|
|
376
|
-
type: 'resourceType',
|
|
377
|
-
parameterOptions: {
|
|
378
|
-
propA: { statefulParameter: statefulParameterA, order: 3},
|
|
379
|
-
propB: { statefulParameter: statefulParameterB, order: 1 },
|
|
380
|
-
propC: { statefulParameter: statefulParameterC, order: 2 },
|
|
381
|
-
},
|
|
382
|
-
callStatefulParameterRemoveOnDestroy: true,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
await resource.apply(
|
|
388
|
-
Plan.fromResponse({
|
|
389
|
-
resourceType: 'resourceType',
|
|
390
|
-
operation: ResourceOperation.CREATE,
|
|
391
|
-
parameters: [
|
|
392
|
-
{ name: 'propA', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
|
|
393
|
-
{ name: 'propB', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
|
|
394
|
-
{ name: 'propC', operation: ParameterOperation.ADD, previousValue: null, newValue: null },
|
|
395
|
-
]
|
|
396
|
-
}, {}) as any
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
expect(timestampB).to.be.lessThan(timestampC as any);
|
|
400
|
-
expect(timestampC).to.be.lessThan(timestampA as any);
|
|
401
|
-
timestampA = 0;
|
|
402
|
-
timestampB = 0;
|
|
403
|
-
timestampC = 0;
|
|
404
|
-
|
|
405
|
-
await resource.apply(
|
|
406
|
-
Plan.fromResponse({
|
|
407
|
-
resourceType: 'resourceType',
|
|
408
|
-
operation: ResourceOperation.MODIFY,
|
|
409
|
-
parameters: [
|
|
410
|
-
{ name: 'propA', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
|
|
411
|
-
{ name: 'propB', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
|
|
412
|
-
{ name: 'propC', operation: ParameterOperation.MODIFY, previousValue: null, newValue: null },
|
|
413
|
-
]
|
|
414
|
-
}, {}) as any
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
expect(timestampB).to.be.lessThan(timestampC as any);
|
|
418
|
-
expect(timestampC).to.be.lessThan(timestampA as any);
|
|
419
|
-
timestampA = 0;
|
|
420
|
-
timestampB = 0;
|
|
421
|
-
timestampC = 0;
|
|
422
|
-
|
|
423
|
-
await resource.apply(
|
|
424
|
-
Plan.fromResponse({
|
|
425
|
-
resourceType: 'resourceType',
|
|
426
|
-
operation: ResourceOperation.DESTROY,
|
|
427
|
-
parameters: [
|
|
428
|
-
{ name: 'propA', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
|
|
429
|
-
{ name: 'propB', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
|
|
430
|
-
{ name: 'propC', operation: ParameterOperation.REMOVE, previousValue: null, newValue: null },
|
|
431
|
-
]
|
|
432
|
-
}, {}) as any
|
|
433
|
-
);
|
|
434
|
-
|
|
435
|
-
expect(timestampB).to.be.lessThan(timestampC as any);
|
|
436
|
-
expect(timestampC).to.be.lessThan(timestampA as any);
|
|
437
|
-
timestampA = 0;
|
|
438
|
-
timestampB = 0;
|
|
439
|
-
timestampC = 0;
|
|
440
|
-
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
it('Supports transform parameters', async () => {
|
|
444
|
-
const transformParameter = new class extends TransformParameter<TestConfig> {
|
|
445
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
446
|
-
return {
|
|
447
|
-
propA: 'propA',
|
|
448
|
-
propB: 10,
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const resource = spy(new class extends TestResource {
|
|
454
|
-
constructor() {
|
|
455
|
-
super({
|
|
456
|
-
type: 'resourceType',
|
|
457
|
-
parameterOptions: {
|
|
458
|
-
propC: { transformParameter }
|
|
459
|
-
},
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
464
|
-
return {
|
|
465
|
-
propA: 'propA',
|
|
466
|
-
propB: 10,
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
const plan = await resource.plan({ type: 'resourceType', propC: 'abc' } as any);
|
|
472
|
-
|
|
473
|
-
expect(resource.refresh.called).to.be.true;
|
|
474
|
-
expect(resource.refresh.getCall(0).firstArg['propA']).to.exist;
|
|
475
|
-
expect(resource.refresh.getCall(0).firstArg['propB']).to.exist;
|
|
476
|
-
expect(resource.refresh.getCall(0).firstArg['propC']).to.not.exist;
|
|
477
|
-
|
|
478
|
-
expect(plan.desiredConfig?.propA).to.eq('propA');
|
|
479
|
-
expect(plan.desiredConfig?.propB).to.eq(10);
|
|
480
|
-
expect(plan.desiredConfig?.propC).to.be.undefined;
|
|
481
|
-
|
|
482
|
-
expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
|
|
483
|
-
})
|
|
484
|
-
|
|
485
|
-
it('Does not call transform parameters unless they are specified in the user config', async () => {
|
|
486
|
-
const transformParameter = spy(new class extends TransformParameter<TestConfig> {
|
|
487
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
488
|
-
return {
|
|
489
|
-
propA: 'propA',
|
|
490
|
-
propB: 10,
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
})
|
|
494
|
-
|
|
495
|
-
const resource = spy(new class extends TestResource {
|
|
496
|
-
constructor() {
|
|
497
|
-
super({
|
|
498
|
-
type: 'resourceType',
|
|
499
|
-
parameterOptions: {
|
|
500
|
-
propC: { transformParameter }
|
|
501
|
-
},
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
506
|
-
return {
|
|
507
|
-
propA: 'propA',
|
|
508
|
-
propB: 10,
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
const plan = await resource.plan({ type: 'resourceType', propA: 'propA', propB: 10 } as any);
|
|
514
|
-
|
|
515
|
-
expect(transformParameter.transform.called).to.be.false;
|
|
516
|
-
expect(resource.refresh.getCall(0).firstArg['propA']).to.exist;
|
|
517
|
-
expect(resource.refresh.getCall(0).firstArg['propB']).to.exist;
|
|
518
|
-
|
|
519
|
-
expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('Plans transform parameters in the order specified', async () => {
|
|
523
|
-
const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
|
|
524
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
525
|
-
return { propD: performance.now() as any }
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
const transformParameterB = spy(new class extends TransformParameter<TestConfig> {
|
|
530
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
531
|
-
return { propE: performance.now() }
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
const transformParameterC = spy(new class extends TransformParameter<TestConfig> {
|
|
536
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
537
|
-
return { propF: performance.now() as any }
|
|
538
|
-
}
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
const resource = spy(new class extends TestResource {
|
|
542
|
-
constructor() {
|
|
543
|
-
super({
|
|
544
|
-
type: 'resourceType',
|
|
545
|
-
parameterOptions: {
|
|
546
|
-
propA: { transformParameter: transformParameterA, order: 3},
|
|
547
|
-
propB: { transformParameter: transformParameterB, order: 1 },
|
|
548
|
-
propC: { transformParameter: transformParameterC, order: 2 },
|
|
549
|
-
},
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
554
|
-
return { propD: 'propD', propE: 10, propF: 'propF' };
|
|
555
|
-
}
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
const plan = await resource.plan({
|
|
559
|
-
type: 'resourceType',
|
|
560
|
-
propA: 'propA',
|
|
561
|
-
propB: 10,
|
|
562
|
-
propC: 'propC',
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
expect(plan.desiredConfig?.propE).to.be.lessThan(plan.desiredConfig?.propF as any);
|
|
566
|
-
expect(plan.desiredConfig?.propF).to.be.lessThan(plan.desiredConfig?.propD as any);
|
|
567
|
-
})
|
|
568
|
-
|
|
569
|
-
it('Plans transform even for creating new resources', async () => {
|
|
570
|
-
const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
|
|
571
|
-
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
572
|
-
return { propD: 'abc', propE: 10 }
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
|
|
576
|
-
const resource = spy(new class extends TestResource {
|
|
577
|
-
constructor() {
|
|
578
|
-
super({
|
|
579
|
-
type: 'resourceType',
|
|
580
|
-
parameterOptions: {
|
|
581
|
-
propA: { transformParameter: transformParameterA },
|
|
582
|
-
},
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
587
|
-
return null;
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
const plan = await resource.plan({
|
|
592
|
-
type: 'resourceType',
|
|
593
|
-
propA: 'propA',
|
|
594
|
-
propB: 10,
|
|
595
|
-
propC: 'propC',
|
|
596
|
-
});
|
|
597
|
-
expect(plan.currentConfig).to.be.null;
|
|
598
|
-
expect(plan.desiredConfig).toMatchObject({
|
|
599
|
-
type: 'resourceType',
|
|
600
|
-
propD: 'abc',
|
|
601
|
-
propE: 10,
|
|
602
|
-
})
|
|
603
|
-
})
|
|
604
|
-
})
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export type ErrorMessage = string;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Customize properties for specific parameters. This will alter the way the library process changes to the parameter.
|
|
5
|
-
*/
|
|
6
|
-
export interface ResourceParameterOptions {
|
|
7
|
-
/**
|
|
8
|
-
* Default value for the parameter. If a value is not provided in the config, the library will use this value.
|
|
9
|
-
*/
|
|
10
|
-
default?: unknown;
|
|
11
|
-
/**
|
|
12
|
-
* Customize the equality comparison for a parameter.
|
|
13
|
-
* @param desired
|
|
14
|
-
* @param current
|
|
15
|
-
*/
|
|
16
|
-
isEqual?: (desired: any, current: any) => boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Chose if the resource should be re-created or modified if this parameter is changed. Defaults to false (re-create).
|
|
19
|
-
*/
|
|
20
|
-
modifyOnChange?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @param
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
export interface ResourceDefinition {
|
|
28
|
-
[x: string]: {
|
|
29
|
-
type: string;
|
|
30
|
-
}
|
|
31
|
-
}
|