codify-plugin-lib 1.0.51 → 1.0.53
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/dist/entities/plan.js +34 -33
- package/dist/entities/plugin.js +2 -2
- package/dist/entities/resource-options.js +2 -2
- package/dist/entities/resource-types.d.ts +1 -1
- package/dist/entities/resource.js +4 -4
- package/package.json +1 -1
- package/src/entities/plan.test.ts +1 -3
- package/src/entities/plan.ts +40 -37
- package/src/entities/plugin.ts +3 -3
- package/src/entities/resource-options.test.ts +23 -0
- package/src/entities/resource-options.ts +2 -2
- package/src/entities/resource-parameters.test.ts +37 -0
- package/src/entities/resource-types.ts +1 -1
- package/src/entities/resource.test.ts +19 -2
- package/src/entities/resource.ts +5 -4
package/dist/entities/plan.js
CHANGED
|
@@ -58,39 +58,40 @@ export class Plan {
|
|
|
58
58
|
Object.entries(defaultValues)
|
|
59
59
|
.forEach(([key, defaultValue]) => {
|
|
60
60
|
const configValueExists = data
|
|
61
|
-
|
|
62
|
-
.
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
61
|
+
.parameters
|
|
62
|
+
.some((p) => p.name === key);
|
|
63
|
+
if (configValueExists) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
switch (data.operation) {
|
|
67
|
+
case ResourceOperation.CREATE: {
|
|
68
|
+
data.parameters.push({
|
|
69
|
+
name: key,
|
|
70
|
+
operation: ParameterOperation.ADD,
|
|
71
|
+
previousValue: null,
|
|
72
|
+
newValue: defaultValue,
|
|
73
|
+
});
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case ResourceOperation.DESTROY: {
|
|
77
|
+
data.parameters.push({
|
|
78
|
+
name: key,
|
|
79
|
+
operation: ParameterOperation.REMOVE,
|
|
80
|
+
previousValue: defaultValue,
|
|
81
|
+
newValue: null,
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case ResourceOperation.MODIFY:
|
|
86
|
+
case ResourceOperation.RECREATE:
|
|
87
|
+
case ResourceOperation.NOOP: {
|
|
88
|
+
data.parameters.push({
|
|
89
|
+
name: key,
|
|
90
|
+
operation: ParameterOperation.NOOP,
|
|
91
|
+
previousValue: defaultValue,
|
|
92
|
+
newValue: defaultValue,
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
});
|
package/dist/entities/plugin.js
CHANGED
|
@@ -66,10 +66,10 @@ export class Plugin {
|
|
|
66
66
|
return this.planStorage.get(planId);
|
|
67
67
|
}
|
|
68
68
|
if (!planRequest?.resourceType || !this.resources.has(planRequest.resourceType)) {
|
|
69
|
-
throw new Error('Malformed plan. Resource type must be supplied');
|
|
69
|
+
throw new Error('Malformed plan. Resource type must be supplied or resource type was not found');
|
|
70
70
|
}
|
|
71
71
|
const resource = this.resources.get(planRequest.resourceType);
|
|
72
|
-
return Plan.fromResponse(data.plan, resource
|
|
72
|
+
return Plan.fromResponse(data.plan, resource.defaultValues);
|
|
73
73
|
}
|
|
74
74
|
async crossValidateResources(configs) { }
|
|
75
75
|
}
|
|
@@ -46,8 +46,8 @@ export class ResourceOptionsParser {
|
|
|
46
46
|
return {};
|
|
47
47
|
}
|
|
48
48
|
return Object.fromEntries([...this.resourceParameters.entries()]
|
|
49
|
-
.filter(([, rp]) => rp.
|
|
50
|
-
.map(([name, rp]) => [name, rp.
|
|
49
|
+
.filter(([, rp]) => rp.default !== undefined)
|
|
50
|
+
.map(([name, rp]) => [name, rp.default]));
|
|
51
51
|
}
|
|
52
52
|
get statefulParameterOrder() {
|
|
53
53
|
const entries = Object.entries(this.options.parameterOptions ?? {})
|
|
@@ -3,7 +3,7 @@ export type ErrorMessage = string;
|
|
|
3
3
|
export interface ResourceParameterOptions {
|
|
4
4
|
planOperation?: ResourceOperation.MODIFY | ResourceOperation.RECREATE;
|
|
5
5
|
isEqual?: (desired: any, current: any) => boolean;
|
|
6
|
-
|
|
6
|
+
default?: unknown;
|
|
7
7
|
}
|
|
8
8
|
export interface ResourceDefinition {
|
|
9
9
|
[x: string]: {
|
|
@@ -55,9 +55,9 @@ export class Resource {
|
|
|
55
55
|
parameterOptions: this.parameterOptions,
|
|
56
56
|
};
|
|
57
57
|
const parsedConfig = new ConfigParser(desiredConfig, this.statefulParameters, this.transformParameters);
|
|
58
|
-
const { parameters: desiredParameters, resourceMetadata, resourceParameters, statefulParameters } = parsedConfig;
|
|
58
|
+
const { parameters: desiredParameters, resourceMetadata, resourceParameters, statefulParameters, transformParameters, } = parsedConfig;
|
|
59
59
|
this.addDefaultValues(resourceParameters);
|
|
60
|
-
await this.applyTransformParameters(resourceParameters);
|
|
60
|
+
await this.applyTransformParameters(transformParameters, resourceParameters);
|
|
61
61
|
const currentParameters = await this.refreshResourceParameters(resourceParameters);
|
|
62
62
|
if (currentParameters == null) {
|
|
63
63
|
return Plan.create(desiredParameters, null, resourceMetadata, planOptions);
|
|
@@ -151,8 +151,8 @@ Missing: ${[...desiredKeys].filter((k) => !refreshKeys.has(k))};
|
|
|
151
151
|
Additional: ${[...refreshKeys].filter(k => !desiredKeys.has(k))};`);
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
async applyTransformParameters(desired) {
|
|
155
|
-
const orderedEntries = [...
|
|
154
|
+
async applyTransformParameters(transformParameters, desired) {
|
|
155
|
+
const orderedEntries = [...Object.entries(transformParameters)]
|
|
156
156
|
.sort(([keyA], [keyB]) => this.transformParameterOrder.get(keyA) - this.transformParameterOrder.get(keyB));
|
|
157
157
|
for (const [key, tp] of orderedEntries) {
|
|
158
158
|
if (desired[key] !== null) {
|
package/package.json
CHANGED
package/src/entities/plan.ts
CHANGED
|
@@ -97,43 +97,46 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
97
97
|
function addDefaultValues(): void {
|
|
98
98
|
Object.entries(defaultValues)
|
|
99
99
|
.forEach(([key, defaultValue]) => {
|
|
100
|
-
const configValueExists = data
|
|
101
|
-
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
100
|
+
const configValueExists = data!
|
|
101
|
+
.parameters
|
|
102
|
+
.some((p) => p.name === key);
|
|
103
|
+
|
|
104
|
+
// Only set default values if the value does not exist in the config
|
|
105
|
+
if (configValueExists) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
switch (data!.operation) {
|
|
110
|
+
case ResourceOperation.CREATE: {
|
|
111
|
+
data!.parameters.push({
|
|
112
|
+
name: key,
|
|
113
|
+
operation: ParameterOperation.ADD,
|
|
114
|
+
previousValue: null,
|
|
115
|
+
newValue: defaultValue,
|
|
116
|
+
});
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
case ResourceOperation.DESTROY: {
|
|
121
|
+
data!.parameters.push({
|
|
122
|
+
name: key,
|
|
123
|
+
operation: ParameterOperation.REMOVE,
|
|
124
|
+
previousValue: defaultValue,
|
|
125
|
+
newValue: null,
|
|
126
|
+
});
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
case ResourceOperation.MODIFY:
|
|
131
|
+
case ResourceOperation.RECREATE:
|
|
132
|
+
case ResourceOperation.NOOP: {
|
|
133
|
+
data!.parameters.push({
|
|
134
|
+
name: key,
|
|
135
|
+
operation: ParameterOperation.NOOP,
|
|
136
|
+
previousValue: defaultValue,
|
|
137
|
+
newValue: defaultValue,
|
|
138
|
+
});
|
|
139
|
+
break;
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
142
|
});
|
package/src/entities/plugin.ts
CHANGED
|
@@ -95,11 +95,11 @@ export class Plugin {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (!planRequest?.resourceType || !this.resources.has(planRequest.resourceType)) {
|
|
98
|
-
throw new Error('Malformed plan. Resource type must be supplied');
|
|
98
|
+
throw new Error('Malformed plan. Resource type must be supplied or resource type was not found');
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
const resource = this.resources.get(planRequest.resourceType)
|
|
102
|
-
return Plan.fromResponse(data.plan, resource
|
|
101
|
+
const resource = this.resources.get(planRequest.resourceType)!;
|
|
102
|
+
return Plan.fromResponse(data.plan, resource.defaultValues);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
protected async crossValidateResources(configs: ResourceConfig[]): Promise<void> {}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { ResourceOptions, ResourceOptionsParser } from './resource-options.js';
|
|
3
|
+
import { TestConfig } from './resource.test.js';
|
|
4
|
+
|
|
5
|
+
describe('Resource options parser tests', () => {
|
|
6
|
+
it('Parses default values from options', () => {
|
|
7
|
+
const option: ResourceOptions<TestConfig> = {
|
|
8
|
+
type: 'typeId',
|
|
9
|
+
parameterOptions: {
|
|
10
|
+
propA: { default: 'propA' },
|
|
11
|
+
propB: { default: 'propB' },
|
|
12
|
+
propC: { isEqual: () => true },
|
|
13
|
+
propD: { },
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const result = new ResourceOptionsParser(option);
|
|
18
|
+
expect(result.defaultValues).to.deep.eq({
|
|
19
|
+
propA: 'propA',
|
|
20
|
+
propB: 'propB'
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
})
|
|
@@ -113,8 +113,8 @@ export class ResourceOptionsParser<T extends StringIndexedObject> {
|
|
|
113
113
|
|
|
114
114
|
return Object.fromEntries(
|
|
115
115
|
[...this.resourceParameters.entries()]
|
|
116
|
-
.filter(([, rp]) => rp.
|
|
117
|
-
.map(([name, rp]) => [name, rp.
|
|
116
|
+
.filter(([, rp]) => rp.default !== undefined)
|
|
117
|
+
.map(([name, rp]) => [name, rp.default])
|
|
118
118
|
) as Partial<Record<keyof T, unknown>>;
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -407,6 +407,43 @@ describe('Resource parameters tests', () => {
|
|
|
407
407
|
expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
|
|
408
408
|
})
|
|
409
409
|
|
|
410
|
+
it('Does not call transform parameters unless they are specified in the user config', async () => {
|
|
411
|
+
const transformParameter = spy(new class extends TransformParameter<TestConfig> {
|
|
412
|
+
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
413
|
+
return {
|
|
414
|
+
propA: 'propA',
|
|
415
|
+
propB: 10,
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
const resource = spy(new class extends TestResource {
|
|
421
|
+
constructor() {
|
|
422
|
+
super({
|
|
423
|
+
type: 'resourceType',
|
|
424
|
+
parameterOptions: {
|
|
425
|
+
propC: { transformParameter }
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
431
|
+
return {
|
|
432
|
+
propA: 'propA',
|
|
433
|
+
propB: 10,
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
const plan = await resource.plan({ type: 'resourceType', propA: 'propA', propB: 10 } as any);
|
|
439
|
+
|
|
440
|
+
expect(transformParameter.transform.called).to.be.false;
|
|
441
|
+
expect(resource.refresh.getCall(0).firstArg.has('propA')).to.be.true;
|
|
442
|
+
expect(resource.refresh.getCall(0).firstArg.has('propB')).to.be.true;
|
|
443
|
+
|
|
444
|
+
expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
|
|
445
|
+
})
|
|
446
|
+
|
|
410
447
|
it('Plans transform parameters in the order specified', async () => {
|
|
411
448
|
const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
|
|
412
449
|
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
@@ -296,7 +296,7 @@ describe('Resource tests', () => {
|
|
|
296
296
|
super({
|
|
297
297
|
type: 'type',
|
|
298
298
|
parameterOptions: {
|
|
299
|
-
propA: {
|
|
299
|
+
propA: { default: 'propADefault' }
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
302
|
}
|
|
@@ -325,7 +325,7 @@ describe('Resource tests', () => {
|
|
|
325
325
|
super({
|
|
326
326
|
type: 'type',
|
|
327
327
|
parameterOptions: {
|
|
328
|
-
propA: {
|
|
328
|
+
propA: { default: 'propADefault' }
|
|
329
329
|
}
|
|
330
330
|
});
|
|
331
331
|
}
|
|
@@ -346,4 +346,21 @@ describe('Resource tests', () => {
|
|
|
346
346
|
expect(plan.desiredConfig.propA).to.eq('propA');
|
|
347
347
|
expect(plan.changeSet.operation).to.eq(ResourceOperation.RECREATE);
|
|
348
348
|
});
|
|
349
|
+
|
|
350
|
+
it('Sets the default value properly on the resource', () => {
|
|
351
|
+
const resource = new class extends TestResource {
|
|
352
|
+
constructor() {
|
|
353
|
+
super({
|
|
354
|
+
type: 'type',
|
|
355
|
+
parameterOptions: {
|
|
356
|
+
propA: { default: 'propADefault' }
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
expect(resource.defaultValues).to.deep.eq({
|
|
363
|
+
propA: 'propADefault',
|
|
364
|
+
})
|
|
365
|
+
})
|
|
349
366
|
});
|
package/src/entities/resource.ts
CHANGED
|
@@ -89,11 +89,12 @@ export abstract class Resource<T extends StringIndexedObject> {
|
|
|
89
89
|
parameters: desiredParameters,
|
|
90
90
|
resourceMetadata,
|
|
91
91
|
resourceParameters,
|
|
92
|
-
statefulParameters
|
|
92
|
+
statefulParameters,
|
|
93
|
+
transformParameters,
|
|
93
94
|
} = parsedConfig;
|
|
94
95
|
|
|
95
96
|
this.addDefaultValues(resourceParameters);
|
|
96
|
-
await this.applyTransformParameters(resourceParameters);
|
|
97
|
+
await this.applyTransformParameters(transformParameters, resourceParameters);
|
|
97
98
|
|
|
98
99
|
// Refresh resource parameters. This refreshes the parameters that configure the resource itself
|
|
99
100
|
const currentParameters = await this.refreshResourceParameters(resourceParameters);
|
|
@@ -223,8 +224,8 @@ Additional: ${[...refreshKeys].filter(k => !desiredKeys.has(k))};`
|
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
226
|
|
|
226
|
-
private async applyTransformParameters(desired: Partial<T>): Promise<void> {
|
|
227
|
-
const orderedEntries = [...
|
|
227
|
+
private async applyTransformParameters(transformParameters: Partial<T>, desired: Partial<T>): Promise<void> {
|
|
228
|
+
const orderedEntries = [...Object.entries(transformParameters)]
|
|
228
229
|
.sort(([keyA], [keyB]) => this.transformParameterOrder.get(keyA)! - this.transformParameterOrder.get(keyB)!)
|
|
229
230
|
|
|
230
231
|
for (const [key, tp] of orderedEntries) {
|