codify-plugin-lib 1.0.134 → 1.0.136
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/resource/parsed-resource-settings.d.ts +3 -3
- package/dist/resource/parsed-resource-settings.js +3 -3
- package/dist/resource/resource-controller.js +11 -5
- package/dist/resource/resource-settings.d.ts +2 -2
- package/dist/resource/resource-settings.js +5 -5
- package/package.json +1 -1
- package/src/resource/parsed-resource-settings.ts +6 -5
- package/src/resource/resource-controller.test.ts +176 -3
- package/src/resource/resource-controller.ts +13 -5
- package/src/resource/resource-settings.test.ts +22 -10
- package/src/resource/resource-settings.ts +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JSONSchemaType } from 'ajv';
|
|
2
2
|
import { StringIndexedObject } from 'codify-schemas';
|
|
3
3
|
import { StatefulParameterController } from '../stateful-parameter/stateful-parameter-controller.js';
|
|
4
|
-
import { ArrayParameterSetting, DefaultParameterSetting,
|
|
4
|
+
import { ArrayParameterSetting, DefaultParameterSetting, InputTransformation, ResourceSettings } from './resource-settings.js';
|
|
5
5
|
export interface ParsedStatefulParameterSetting extends DefaultParameterSetting {
|
|
6
6
|
type: 'stateful';
|
|
7
7
|
controller: StatefulParameterController<any, unknown>;
|
|
@@ -25,14 +25,14 @@ export declare class ParsedResourceSettings<T extends StringIndexedObject> imple
|
|
|
25
25
|
} | boolean;
|
|
26
26
|
removeStatefulParametersBeforeDestroy?: boolean | undefined;
|
|
27
27
|
dependencies?: string[] | undefined;
|
|
28
|
-
|
|
28
|
+
transformation?: InputTransformation;
|
|
29
29
|
private settings;
|
|
30
30
|
constructor(settings: ResourceSettings<T>);
|
|
31
31
|
get typeId(): string;
|
|
32
32
|
get statefulParameters(): Map<keyof T, StatefulParameterController<T, T[keyof T]>>;
|
|
33
33
|
get parameterSettings(): Record<keyof T, ParsedParameterSetting>;
|
|
34
34
|
get defaultValues(): Partial<Record<keyof T, unknown>>;
|
|
35
|
-
get inputTransformations(): Partial<Record<keyof T,
|
|
35
|
+
get inputTransformations(): Partial<Record<keyof T, InputTransformation>>;
|
|
36
36
|
get statefulParameterOrder(): Map<keyof T, number>;
|
|
37
37
|
private validateSettings;
|
|
38
38
|
private validateParameterEqualsFn;
|
|
@@ -7,7 +7,7 @@ export class ParsedResourceSettings {
|
|
|
7
7
|
allowMultiple;
|
|
8
8
|
removeStatefulParametersBeforeDestroy;
|
|
9
9
|
dependencies;
|
|
10
|
-
|
|
10
|
+
transformation;
|
|
11
11
|
settings;
|
|
12
12
|
constructor(settings) {
|
|
13
13
|
this.settings = settings;
|
|
@@ -16,7 +16,7 @@ export class ParsedResourceSettings {
|
|
|
16
16
|
this.allowMultiple = settings.allowMultiple;
|
|
17
17
|
this.removeStatefulParametersBeforeDestroy = settings.removeStatefulParametersBeforeDestroy;
|
|
18
18
|
this.dependencies = settings.dependencies;
|
|
19
|
-
this.
|
|
19
|
+
this.transformation = settings.transformation;
|
|
20
20
|
this.validateSettings();
|
|
21
21
|
}
|
|
22
22
|
get typeId() {
|
|
@@ -83,7 +83,7 @@ export class ParsedResourceSettings {
|
|
|
83
83
|
}
|
|
84
84
|
return Object.fromEntries(Object.entries(this.settings.parameterSettings)
|
|
85
85
|
.filter(([_, v]) => resolveParameterTransformFn(v) !== undefined)
|
|
86
|
-
.map(([k, v]) => [k, resolveParameterTransformFn(v)
|
|
86
|
+
.map(([k, v]) => [k, resolveParameterTransformFn(v)]));
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
get statefulParameterOrder() {
|
|
@@ -174,7 +174,9 @@ export class ResourceController {
|
|
|
174
174
|
?? null;
|
|
175
175
|
}
|
|
176
176
|
const statefulCurrentParameters = await this.refreshStatefulParameters(allStatefulParameters, parametersToRefresh);
|
|
177
|
-
|
|
177
|
+
const resultParameters = { ...currentParametersArray[0], ...statefulCurrentParameters };
|
|
178
|
+
await this.applyTransformParameters(resultParameters, true);
|
|
179
|
+
return [{ core, parameters: resultParameters }];
|
|
178
180
|
}
|
|
179
181
|
async applyCreate(plan) {
|
|
180
182
|
await this.resource.create(plan);
|
|
@@ -236,7 +238,7 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
236
238
|
`);
|
|
237
239
|
}
|
|
238
240
|
}
|
|
239
|
-
async applyTransformParameters(config) {
|
|
241
|
+
async applyTransformParameters(config, reverse = false) {
|
|
240
242
|
if (!config) {
|
|
241
243
|
return;
|
|
242
244
|
}
|
|
@@ -244,10 +246,14 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
244
246
|
if (config[key] === undefined || !inputTransformation) {
|
|
245
247
|
continue;
|
|
246
248
|
}
|
|
247
|
-
config[key] =
|
|
249
|
+
config[key] = reverse
|
|
250
|
+
? await inputTransformation.from(config[key])
|
|
251
|
+
: await inputTransformation.to(config[key]);
|
|
248
252
|
}
|
|
249
|
-
if (this.settings.
|
|
250
|
-
const transformed =
|
|
253
|
+
if (this.settings.transformation) {
|
|
254
|
+
const transformed = reverse
|
|
255
|
+
? await this.settings.transformation.from({ ...config })
|
|
256
|
+
: await this.settings.transformation.to({ ...config });
|
|
251
257
|
Object.keys(config).forEach((k) => delete config[k]);
|
|
252
258
|
Object.assign(config, transformed);
|
|
253
259
|
}
|
|
@@ -66,7 +66,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
66
66
|
*
|
|
67
67
|
* @param desired
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
transformation?: InputTransformation;
|
|
70
70
|
/**
|
|
71
71
|
* Customize the import and destory behavior of the resource. By default, <code>codify import</code> and <code>codify destroy</code> will call
|
|
72
72
|
* `refresh()` with every parameter set to null and return the result of the refresh as the imported config. It looks for required parameters
|
|
@@ -151,7 +151,7 @@ export interface DefaultParameterSetting {
|
|
|
151
151
|
*
|
|
152
152
|
* @param input The original parameter value from the desired config.
|
|
153
153
|
*/
|
|
154
|
-
|
|
154
|
+
transformation?: InputTransformation;
|
|
155
155
|
/**
|
|
156
156
|
* Customize the equality comparison for a parameter. This is used in the diffing algorithm for generating the plan.
|
|
157
157
|
* This value will override the pre-set equality function from the type. Return true if the desired value is
|
|
@@ -54,17 +54,17 @@ const ParameterTransformationDefaults = {
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
export function resolveParameterTransformFn(parameter) {
|
|
57
|
-
if (parameter.type === 'stateful' && !parameter.
|
|
57
|
+
if (parameter.type === 'stateful' && !parameter.transformation) {
|
|
58
58
|
const sp = parameter.definition.getSettings();
|
|
59
|
-
if (sp.
|
|
60
|
-
return parameter.definition?.getSettings()?.
|
|
59
|
+
if (sp.transformation) {
|
|
60
|
+
return parameter.definition?.getSettings()?.transformation;
|
|
61
61
|
}
|
|
62
62
|
return sp.type ? ParameterTransformationDefaults[sp.type] : undefined;
|
|
63
63
|
}
|
|
64
64
|
if (parameter.type === 'array'
|
|
65
65
|
&& parameter.itemType
|
|
66
66
|
&& ParameterTransformationDefaults[parameter.itemType]
|
|
67
|
-
&& !parameter.
|
|
67
|
+
&& !parameter.transformation) {
|
|
68
68
|
const itemType = parameter.itemType;
|
|
69
69
|
const itemTransformation = ParameterTransformationDefaults[itemType];
|
|
70
70
|
return {
|
|
@@ -76,5 +76,5 @@ export function resolveParameterTransformFn(parameter) {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
-
return parameter.
|
|
79
|
+
return parameter.transformation ?? ParameterTransformationDefaults[parameter.type] ?? undefined;
|
|
80
80
|
}
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import { StatefulParameterController } from '../stateful-parameter/stateful-para
|
|
|
5
5
|
import {
|
|
6
6
|
ArrayParameterSetting,
|
|
7
7
|
DefaultParameterSetting,
|
|
8
|
+
InputTransformation,
|
|
8
9
|
ParameterSetting,
|
|
9
10
|
resolveElementEqualsFn,
|
|
10
11
|
resolveEqualsFn,
|
|
@@ -43,7 +44,7 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
43
44
|
|
|
44
45
|
removeStatefulParametersBeforeDestroy?: boolean | undefined;
|
|
45
46
|
dependencies?: string[] | undefined;
|
|
46
|
-
|
|
47
|
+
transformation?: InputTransformation;
|
|
47
48
|
private settings: ResourceSettings<T>;
|
|
48
49
|
|
|
49
50
|
constructor(settings: ResourceSettings<T>) {
|
|
@@ -53,7 +54,7 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
53
54
|
this.allowMultiple = settings.allowMultiple;
|
|
54
55
|
this.removeStatefulParametersBeforeDestroy = settings.removeStatefulParametersBeforeDestroy;
|
|
55
56
|
this.dependencies = settings.dependencies;
|
|
56
|
-
this.
|
|
57
|
+
this.transformation = settings.transformation;
|
|
57
58
|
|
|
58
59
|
this.validateSettings();
|
|
59
60
|
}
|
|
@@ -136,7 +137,7 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
136
137
|
});
|
|
137
138
|
}
|
|
138
139
|
|
|
139
|
-
get inputTransformations(): Partial<Record<keyof T,
|
|
140
|
+
get inputTransformations(): Partial<Record<keyof T, InputTransformation>> {
|
|
140
141
|
return this.getFromCacheOrCreate('inputTransformations', () => {
|
|
141
142
|
if (!this.settings.parameterSettings) {
|
|
142
143
|
return {};
|
|
@@ -145,8 +146,8 @@ export class ParsedResourceSettings<T extends StringIndexedObject> implements Re
|
|
|
145
146
|
return Object.fromEntries(
|
|
146
147
|
Object.entries(this.settings.parameterSettings)
|
|
147
148
|
.filter(([_, v]) => resolveParameterTransformFn(v!) !== undefined)
|
|
148
|
-
.map(([k, v]) => [k, resolveParameterTransformFn(v!)
|
|
149
|
-
) as Record<keyof T,
|
|
149
|
+
.map(([k, v]) => [k, resolveParameterTransformFn(v!)] as const)
|
|
150
|
+
) as Record<keyof T, InputTransformation>;
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
153
|
|
|
@@ -7,7 +7,7 @@ import { CreatePlan, DestroyPlan, ModifyPlan } from '../plan/plan-types.js';
|
|
|
7
7
|
import { ParameterChange } from '../plan/change-set.js';
|
|
8
8
|
import { ResourceController } from './resource-controller.js';
|
|
9
9
|
import { TestConfig, testPlan, TestResource, TestStatefulParameter } from '../utils/test-utils.test.js';
|
|
10
|
-
import { untildify } from '../utils/utils.js';
|
|
10
|
+
import { tildify, untildify } from '../utils/utils.js';
|
|
11
11
|
import { ArrayStatefulParameter, StatefulParameter } from '../stateful-parameter/stateful-parameter.js';
|
|
12
12
|
import { Plan } from '../plan/plan.js';
|
|
13
13
|
|
|
@@ -20,9 +20,8 @@ describe('Resource tests', () => {
|
|
|
20
20
|
id: 'type',
|
|
21
21
|
dependencies: ['homebrew', 'python'],
|
|
22
22
|
parameterSettings: {
|
|
23
|
-
propA: { canModify: true,
|
|
23
|
+
propA: { canModify: true, transformation: { to: (input) => untildify(input), from: (input) => tildify(input) } },
|
|
24
24
|
},
|
|
25
|
-
inputTransformation: (config) => ({ propA: config.propA, propC: config.propB }),
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
|
|
@@ -535,4 +534,178 @@ describe('Resource tests', () => {
|
|
|
535
534
|
expect(parameter1.modify.calledOnce).to.be.true;
|
|
536
535
|
expect(parameter2.addItem.calledOnce).to.be.true;
|
|
537
536
|
});
|
|
537
|
+
|
|
538
|
+
it('Applies reverse input transformations for imports', async () => {
|
|
539
|
+
const resource = new class extends TestResource {
|
|
540
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
541
|
+
return {
|
|
542
|
+
id: 'resourceType',
|
|
543
|
+
parameterSettings: {
|
|
544
|
+
propD: {
|
|
545
|
+
type: 'array',
|
|
546
|
+
transformation: {
|
|
547
|
+
to: (hosts: Record<string, unknown>[]) => hosts.map((h) => Object.fromEntries(
|
|
548
|
+
Object.entries(h)
|
|
549
|
+
.map(([k, v]) => [
|
|
550
|
+
k,
|
|
551
|
+
typeof v === 'boolean'
|
|
552
|
+
? (v ? 'yes' : 'no') // The file takes 'yes' or 'no' instead of booleans
|
|
553
|
+
: v,
|
|
554
|
+
])
|
|
555
|
+
)
|
|
556
|
+
),
|
|
557
|
+
from: (hosts: Record<string, unknown>[]) => hosts.map((h) => Object.fromEntries(
|
|
558
|
+
Object.entries(h)
|
|
559
|
+
.map(([k, v]) => [
|
|
560
|
+
k,
|
|
561
|
+
v === 'yes' || v === 'no'
|
|
562
|
+
? (v === 'yes')
|
|
563
|
+
: v,
|
|
564
|
+
])
|
|
565
|
+
))
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async refresh(parameters: Partial<TestConfig>): Promise<Partial<TestConfig> | null> {
|
|
573
|
+
return {
|
|
574
|
+
propD: [
|
|
575
|
+
{
|
|
576
|
+
Host: 'new.com',
|
|
577
|
+
AddKeysToAgent: true,
|
|
578
|
+
IdentityFile: 'id_ed25519'
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
Host: 'github.com',
|
|
582
|
+
AddKeysToAgent: true,
|
|
583
|
+
UseKeychain: true,
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
Match: 'User bob,joe,phil',
|
|
587
|
+
PasswordAuthentication: true,
|
|
588
|
+
}
|
|
589
|
+
],
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const controller = new ResourceController(resource);
|
|
595
|
+
const plan = await controller.import({ type: 'resourceType' }, {});
|
|
596
|
+
|
|
597
|
+
expect(plan![0]).toMatchObject({
|
|
598
|
+
'core': {
|
|
599
|
+
'type': 'resourceType'
|
|
600
|
+
},
|
|
601
|
+
'parameters': {
|
|
602
|
+
'propD': [
|
|
603
|
+
{
|
|
604
|
+
'Host': 'new.com',
|
|
605
|
+
'AddKeysToAgent': true,
|
|
606
|
+
'IdentityFile': 'id_ed25519'
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
'Host': 'github.com',
|
|
610
|
+
'AddKeysToAgent': true,
|
|
611
|
+
'UseKeychain': true
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
'Match': 'User bob,joe,phil',
|
|
615
|
+
'PasswordAuthentication': true
|
|
616
|
+
}
|
|
617
|
+
]
|
|
618
|
+
}
|
|
619
|
+
})
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
it('Applies reverse input transformations for imports (object level)', async () => {
|
|
623
|
+
const resource = new class extends TestResource {
|
|
624
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
625
|
+
return {
|
|
626
|
+
id: 'resourceType',
|
|
627
|
+
parameterSettings: {
|
|
628
|
+
propD: {
|
|
629
|
+
type: 'array',
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
transformation: {
|
|
633
|
+
to: (input: any) => ({
|
|
634
|
+
...input,
|
|
635
|
+
propD: input.propD?.map((h) => Object.fromEntries(
|
|
636
|
+
Object.entries(h)
|
|
637
|
+
.map(([k, v]) => [
|
|
638
|
+
k,
|
|
639
|
+
typeof v === 'boolean'
|
|
640
|
+
? (v ? 'yes' : 'no') // The file takes 'yes' or 'no' instead of booleans
|
|
641
|
+
: v,
|
|
642
|
+
])
|
|
643
|
+
)
|
|
644
|
+
)
|
|
645
|
+
}),
|
|
646
|
+
from: (output: any) => ({
|
|
647
|
+
...output,
|
|
648
|
+
propD: output.propD?.map((h) => Object.fromEntries(
|
|
649
|
+
Object.entries(h)
|
|
650
|
+
.map(([k, v]) => [
|
|
651
|
+
k,
|
|
652
|
+
v === 'yes' || v === 'no'
|
|
653
|
+
? (v === 'yes')
|
|
654
|
+
: v,
|
|
655
|
+
])
|
|
656
|
+
))
|
|
657
|
+
})
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
async refresh(parameters: Partial<TestConfig>): Promise<Partial<TestConfig> | null> {
|
|
663
|
+
return {
|
|
664
|
+
propD: [
|
|
665
|
+
{
|
|
666
|
+
Host: 'new.com',
|
|
667
|
+
AddKeysToAgent: true,
|
|
668
|
+
IdentityFile: 'id_ed25519'
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
Host: 'github.com',
|
|
672
|
+
AddKeysToAgent: true,
|
|
673
|
+
UseKeychain: true,
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
Match: 'User bob,joe,phil',
|
|
677
|
+
PasswordAuthentication: true,
|
|
678
|
+
}
|
|
679
|
+
],
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const controller = new ResourceController(resource);
|
|
685
|
+
const plan = await controller.import({ type: 'resourceType' }, {});
|
|
686
|
+
|
|
687
|
+
expect(plan![0]).toMatchObject({
|
|
688
|
+
'core': {
|
|
689
|
+
'type': 'resourceType'
|
|
690
|
+
},
|
|
691
|
+
'parameters': {
|
|
692
|
+
'propD': [
|
|
693
|
+
{
|
|
694
|
+
'Host': 'new.com',
|
|
695
|
+
'AddKeysToAgent': true,
|
|
696
|
+
'IdentityFile': 'id_ed25519'
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
'Host': 'github.com',
|
|
700
|
+
'AddKeysToAgent': true,
|
|
701
|
+
'UseKeychain': true
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
'Match': 'User bob,joe,phil',
|
|
705
|
+
'PasswordAuthentication': true
|
|
706
|
+
}
|
|
707
|
+
]
|
|
708
|
+
}
|
|
709
|
+
})
|
|
710
|
+
})
|
|
538
711
|
});
|
|
@@ -254,7 +254,10 @@ export class ResourceController<T extends StringIndexedObject> {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
const statefulCurrentParameters = await this.refreshStatefulParameters(allStatefulParameters, parametersToRefresh);
|
|
257
|
-
|
|
257
|
+
const resultParameters = { ...currentParametersArray[0], ...statefulCurrentParameters };
|
|
258
|
+
|
|
259
|
+
await this.applyTransformParameters(resultParameters, true);
|
|
260
|
+
return [{ core, parameters: resultParameters }];
|
|
258
261
|
}
|
|
259
262
|
|
|
260
263
|
private async applyCreate(plan: Plan<T>): Promise<void> {
|
|
@@ -333,7 +336,7 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
333
336
|
}
|
|
334
337
|
}
|
|
335
338
|
|
|
336
|
-
private async applyTransformParameters(config: Partial<T> | null): Promise<void> {
|
|
339
|
+
private async applyTransformParameters(config: Partial<T> | null, reverse = false): Promise<void> {
|
|
337
340
|
if (!config) {
|
|
338
341
|
return;
|
|
339
342
|
}
|
|
@@ -343,11 +346,16 @@ ${JSON.stringify(refresh, null, 2)}
|
|
|
343
346
|
continue;
|
|
344
347
|
}
|
|
345
348
|
|
|
346
|
-
(config as Record<string, unknown>)[key] =
|
|
349
|
+
(config as Record<string, unknown>)[key] = reverse
|
|
350
|
+
? await inputTransformation.from(config[key])
|
|
351
|
+
: await inputTransformation.to(config[key]);
|
|
347
352
|
}
|
|
348
353
|
|
|
349
|
-
if (this.settings.
|
|
350
|
-
const transformed =
|
|
354
|
+
if (this.settings.transformation) {
|
|
355
|
+
const transformed = reverse
|
|
356
|
+
? await this.settings.transformation.from({ ...config })
|
|
357
|
+
: await this.settings.transformation.to({ ...config })
|
|
358
|
+
|
|
351
359
|
Object.keys(config).forEach((k) => delete config[k])
|
|
352
360
|
Object.assign(config, transformed);
|
|
353
361
|
}
|
|
@@ -569,10 +569,16 @@ describe('Resource parameter tests', () => {
|
|
|
569
569
|
getSettings(): ResourceSettings<TestConfig> {
|
|
570
570
|
return {
|
|
571
571
|
id: 'resourceType',
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
572
|
+
transformation: {
|
|
573
|
+
to: (desired) => ({
|
|
574
|
+
propA: 'propA',
|
|
575
|
+
propB: 10,
|
|
576
|
+
}),
|
|
577
|
+
from: (current) => ({
|
|
578
|
+
propA: 'propA',
|
|
579
|
+
propB: 10,
|
|
580
|
+
})
|
|
581
|
+
}
|
|
576
582
|
}
|
|
577
583
|
}
|
|
578
584
|
|
|
@@ -604,10 +610,16 @@ describe('Resource parameter tests', () => {
|
|
|
604
610
|
getSettings(): ResourceSettings<TestConfig> {
|
|
605
611
|
return {
|
|
606
612
|
id: 'resourceType',
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
613
|
+
transformation: {
|
|
614
|
+
to: (desired) => ({
|
|
615
|
+
propA: 'propA',
|
|
616
|
+
propB: 10,
|
|
617
|
+
}),
|
|
618
|
+
from: (desired) => ({
|
|
619
|
+
propA: 'propA',
|
|
620
|
+
propB: 10,
|
|
621
|
+
})
|
|
622
|
+
}
|
|
611
623
|
}
|
|
612
624
|
}
|
|
613
625
|
|
|
@@ -852,7 +864,7 @@ describe('Resource parameter tests', () => {
|
|
|
852
864
|
parameterSettings: {
|
|
853
865
|
propD: {
|
|
854
866
|
type: 'array',
|
|
855
|
-
|
|
867
|
+
transformation: {
|
|
856
868
|
to: (hosts: Record<string, unknown>[]) => hosts.map((h) => Object.fromEntries(
|
|
857
869
|
Object.entries(h)
|
|
858
870
|
.map(([k, v]) => [
|
|
@@ -918,7 +930,7 @@ describe('Resource parameter tests', () => {
|
|
|
918
930
|
getSettings(): any {
|
|
919
931
|
return {
|
|
920
932
|
type: 'array',
|
|
921
|
-
|
|
933
|
+
transformation: {
|
|
922
934
|
to: (hosts: Record<string, unknown>[]) => hosts.map((h) => Object.fromEntries(
|
|
923
935
|
Object.entries(h)
|
|
924
936
|
.map(([k, v]) => [
|
|
@@ -81,7 +81,7 @@ export interface ResourceSettings<T extends StringIndexedObject> {
|
|
|
81
81
|
*
|
|
82
82
|
* @param desired
|
|
83
83
|
*/
|
|
84
|
-
|
|
84
|
+
transformation?: InputTransformation;
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* Customize the import and destory behavior of the resource. By default, <code>codify import</code> and <code>codify destroy</code> will call
|
|
@@ -189,7 +189,7 @@ export interface DefaultParameterSetting {
|
|
|
189
189
|
*
|
|
190
190
|
* @param input The original parameter value from the desired config.
|
|
191
191
|
*/
|
|
192
|
-
|
|
192
|
+
transformation?: InputTransformation;
|
|
193
193
|
|
|
194
194
|
/**
|
|
195
195
|
* Customize the equality comparison for a parameter. This is used in the diffing algorithm for generating the plan.
|
|
@@ -354,10 +354,10 @@ export function resolveParameterTransformFn(
|
|
|
354
354
|
parameter: ParameterSetting
|
|
355
355
|
): InputTransformation | undefined {
|
|
356
356
|
|
|
357
|
-
if (parameter.type === 'stateful' && !parameter.
|
|
357
|
+
if (parameter.type === 'stateful' && !parameter.transformation) {
|
|
358
358
|
const sp = (parameter as StatefulParameterSetting).definition.getSettings();
|
|
359
|
-
if (sp.
|
|
360
|
-
return (parameter as StatefulParameterSetting).definition?.getSettings()?.
|
|
359
|
+
if (sp.transformation) {
|
|
360
|
+
return (parameter as StatefulParameterSetting).definition?.getSettings()?.transformation
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
return sp.type ? ParameterTransformationDefaults[sp.type] : undefined;
|
|
@@ -366,7 +366,7 @@ export function resolveParameterTransformFn(
|
|
|
366
366
|
if (parameter.type === 'array'
|
|
367
367
|
&& (parameter as ArrayParameterSetting).itemType
|
|
368
368
|
&& ParameterTransformationDefaults[(parameter as ArrayParameterSetting).itemType!]
|
|
369
|
-
&& !parameter.
|
|
369
|
+
&& !parameter.transformation
|
|
370
370
|
) {
|
|
371
371
|
const itemType = (parameter as ArrayParameterSetting).itemType!;
|
|
372
372
|
const itemTransformation = ParameterTransformationDefaults[itemType]!;
|
|
@@ -381,5 +381,5 @@ export function resolveParameterTransformFn(
|
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
|
|
384
|
-
return parameter.
|
|
384
|
+
return parameter.transformation ?? ParameterTransformationDefaults[parameter.type as ParameterSettingType] ?? undefined;
|
|
385
385
|
}
|