codify-plugin-lib 1.0.60 → 1.0.61
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/resource.js +2 -2
- package/dist/entities/stateful-parameter.d.ts +7 -8
- package/dist/entities/stateful-parameter.js +0 -2
- package/package.json +1 -1
- package/src/entities/resource-parameters.test.ts +87 -5
- package/src/entities/resource.ts +10 -2
- package/src/entities/stateful-parameter.ts +8 -10
|
@@ -54,13 +54,13 @@ export class Resource {
|
|
|
54
54
|
statefulMode: false,
|
|
55
55
|
parameterOptions: this.parameterOptions,
|
|
56
56
|
};
|
|
57
|
+
this.addDefaultValues(desiredConfig);
|
|
57
58
|
const parsedConfig = new ConfigParser(desiredConfig, this.statefulParameters, this.transformParameters);
|
|
58
59
|
const { parameters: desiredParameters, resourceMetadata, resourceParameters, statefulParameters, transformParameters, } = parsedConfig;
|
|
59
|
-
this.addDefaultValues(resourceParameters);
|
|
60
60
|
await this.applyTransformParameters(transformParameters, resourceParameters);
|
|
61
61
|
const currentParameters = await this.refreshResourceParameters(resourceParameters);
|
|
62
62
|
if (currentParameters == null) {
|
|
63
|
-
return Plan.create(
|
|
63
|
+
return Plan.create({ ...resourceParameters, ...statefulParameters }, null, resourceMetadata, planOptions);
|
|
64
64
|
}
|
|
65
65
|
const statefulCurrentParameters = await this.refreshStatefulParameters(statefulParameters, planOptions.statefulMode);
|
|
66
66
|
return Plan.create({ ...resourceParameters, ...statefulParameters }, { ...currentParameters, ...statefulCurrentParameters }, resourceMetadata, planOptions);
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import { Plan } from './plan.js';
|
|
2
2
|
import { StringIndexedObject } from 'codify-schemas';
|
|
3
|
-
export interface StatefulParameterOptions<
|
|
4
|
-
name: keyof T;
|
|
3
|
+
export interface StatefulParameterOptions<V> {
|
|
5
4
|
isEqual?: (desired: any, current: any) => boolean;
|
|
6
5
|
disableStatelessModeArrayFiltering?: boolean;
|
|
6
|
+
default?: V;
|
|
7
7
|
}
|
|
8
|
-
export interface ArrayStatefulParameterOptions<
|
|
8
|
+
export interface ArrayStatefulParameterOptions<V> extends StatefulParameterOptions<V> {
|
|
9
9
|
isEqual?: (desired: any[], current: any[]) => boolean;
|
|
10
10
|
isElementEqual?: (desired: any, current: any) => boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
|
|
13
|
-
readonly
|
|
14
|
-
|
|
15
|
-
protected constructor(options: StatefulParameterOptions<T>);
|
|
13
|
+
readonly options: StatefulParameterOptions<V>;
|
|
14
|
+
protected constructor(options: StatefulParameterOptions<V>);
|
|
16
15
|
abstract refresh(desired: V | null): Promise<V | null>;
|
|
17
16
|
abstract applyAdd(valueToAdd: V, plan: Plan<T>): Promise<void>;
|
|
18
17
|
abstract applyModify(newValue: V, previousValue: V, allowDeletes: boolean, plan: Plan<T>): Promise<void>;
|
|
19
18
|
abstract applyRemove(valueToRemove: V, plan: Plan<T>): Promise<void>;
|
|
20
19
|
}
|
|
21
20
|
export declare abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any> {
|
|
22
|
-
options: ArrayStatefulParameterOptions<
|
|
23
|
-
constructor(options: ArrayStatefulParameterOptions<
|
|
21
|
+
options: ArrayStatefulParameterOptions<V>;
|
|
22
|
+
constructor(options: ArrayStatefulParameterOptions<V>);
|
|
24
23
|
applyAdd(valuesToAdd: V[], plan: Plan<T>): Promise<void>;
|
|
25
24
|
applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void>;
|
|
26
25
|
applyRemove(valuesToRemove: V[], plan: Plan<T>): Promise<void>;
|
package/package.json
CHANGED
|
@@ -7,10 +7,8 @@ import { TestConfig, TestResource } from './resource.test.js';
|
|
|
7
7
|
import { TransformParameter } from './transform-parameter.js';
|
|
8
8
|
|
|
9
9
|
class TestParameter extends StatefulParameter<TestConfig, string> {
|
|
10
|
-
constructor(options?: StatefulParameterOptions<
|
|
11
|
-
super(options ?? {
|
|
12
|
-
name: 'propA'
|
|
13
|
-
})
|
|
10
|
+
constructor(options?: StatefulParameterOptions<string>) {
|
|
11
|
+
super(options ?? {})
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
applyAdd(valueToAdd: string, plan: Plan<TestConfig>): Promise<void> {
|
|
@@ -140,6 +138,51 @@ describe('Resource parameter tests', () => {
|
|
|
140
138
|
expect(resourceSpy.applyModify.calledOnce).to.be.true;
|
|
141
139
|
})
|
|
142
140
|
|
|
141
|
+
it('Allows stateful parameters to have default values', async () => {
|
|
142
|
+
const statefulParameter = spy(new class extends TestParameter {
|
|
143
|
+
constructor() {
|
|
144
|
+
super({
|
|
145
|
+
default: 'abc'
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async refresh(): Promise<string | null> {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const resource = new class extends TestResource {
|
|
155
|
+
constructor() {
|
|
156
|
+
super({
|
|
157
|
+
type: 'resource',
|
|
158
|
+
parameterOptions: {
|
|
159
|
+
propA: { statefulParameter }
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async refresh(): Promise<any> {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const plan = await resource.plan({
|
|
170
|
+
type: 'resource',
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
expect(statefulParameter.refresh.notCalled).to.be.true;
|
|
174
|
+
expect(plan.currentConfig).toMatchObject({
|
|
175
|
+
type: 'resource',
|
|
176
|
+
propA: null,
|
|
177
|
+
})
|
|
178
|
+
expect(plan.desiredConfig).toMatchObject({
|
|
179
|
+
type: 'resource',
|
|
180
|
+
propA: 'abc',
|
|
181
|
+
})
|
|
182
|
+
expect(plan.changeSet.operation).to.eq(ResourceOperation.CREATE);
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
|
|
143
186
|
it('Filters array results in stateless mode to prevent modify from being called', async () => {
|
|
144
187
|
const statefulParameter = new class extends TestParameter {
|
|
145
188
|
async refresh(): Promise<any | null> {
|
|
@@ -210,7 +253,6 @@ describe('Resource parameter tests', () => {
|
|
|
210
253
|
const statefulParameter = new class extends ArrayStatefulParameter<TestConfig, string> {
|
|
211
254
|
constructor() {
|
|
212
255
|
super({
|
|
213
|
-
name: 'propA',
|
|
214
256
|
isElementEqual: (desired, current) => current.includes(desired),
|
|
215
257
|
});
|
|
216
258
|
}
|
|
@@ -531,4 +573,44 @@ describe('Resource parameter tests', () => {
|
|
|
531
573
|
expect(plan.desiredConfig.propE).to.be.lessThan(plan.desiredConfig.propF as any);
|
|
532
574
|
expect(plan.desiredConfig.propF).to.be.lessThan(plan.desiredConfig.propD as any);
|
|
533
575
|
})
|
|
576
|
+
|
|
577
|
+
it('Plans transform even for creating new resources', async () => {
|
|
578
|
+
const transformParameterA = spy(new class extends TransformParameter<TestConfig> {
|
|
579
|
+
async transform(value: any): Promise<Partial<TestConfig>> {
|
|
580
|
+
return { propD: 'abc', propE: 10 }
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
const resource = spy(new class extends TestResource {
|
|
585
|
+
constructor() {
|
|
586
|
+
super({
|
|
587
|
+
type: 'resourceType',
|
|
588
|
+
parameterOptions: {
|
|
589
|
+
propA: { transformParameter: transformParameterA },
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
const plan = await resource.plan({
|
|
600
|
+
type: 'resourceType',
|
|
601
|
+
propA: 'propA',
|
|
602
|
+
propB: 10,
|
|
603
|
+
propC: 'propC',
|
|
604
|
+
});
|
|
605
|
+
expect(plan.currentConfig).toMatchObject({
|
|
606
|
+
type: 'resourceType',
|
|
607
|
+
propD: null,
|
|
608
|
+
propE: null,
|
|
609
|
+
})
|
|
610
|
+
expect(plan.desiredConfig).toMatchObject({
|
|
611
|
+
type: 'resourceType',
|
|
612
|
+
propD: 'abc',
|
|
613
|
+
propE: 10,
|
|
614
|
+
})
|
|
615
|
+
})
|
|
534
616
|
})
|
package/src/entities/resource.ts
CHANGED
|
@@ -83,6 +83,8 @@ export abstract class Resource<T extends StringIndexedObject> {
|
|
|
83
83
|
parameterOptions: this.parameterOptions,
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
this.addDefaultValues(desiredConfig);
|
|
87
|
+
|
|
86
88
|
// Parse data from the user supplied config
|
|
87
89
|
const parsedConfig = new ConfigParser(desiredConfig, this.statefulParameters, this.transformParameters)
|
|
88
90
|
const {
|
|
@@ -93,7 +95,8 @@ export abstract class Resource<T extends StringIndexedObject> {
|
|
|
93
95
|
transformParameters,
|
|
94
96
|
} = parsedConfig;
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
// Apply transform parameters. Transform parameters turn into other parameters.
|
|
99
|
+
// Ex: csvFile: './location' => { password: 'pass', 'username': 'user' }
|
|
97
100
|
await this.applyTransformParameters(transformParameters, resourceParameters);
|
|
98
101
|
|
|
99
102
|
// Refresh resource parameters. This refreshes the parameters that configure the resource itself
|
|
@@ -101,7 +104,12 @@ export abstract class Resource<T extends StringIndexedObject> {
|
|
|
101
104
|
|
|
102
105
|
// Short circuit here. If the resource is non-existent, there's no point checking stateful parameters
|
|
103
106
|
if (currentParameters == null) {
|
|
104
|
-
return Plan.create(
|
|
107
|
+
return Plan.create(
|
|
108
|
+
{ ...resourceParameters, ...statefulParameters },
|
|
109
|
+
null,
|
|
110
|
+
resourceMetadata,
|
|
111
|
+
planOptions,
|
|
112
|
+
);
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
// Refresh stateful parameters. These parameters have state external to the resource
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Plan } from './plan.js';
|
|
2
2
|
import { StringIndexedObject } from 'codify-schemas';
|
|
3
3
|
|
|
4
|
-
export interface StatefulParameterOptions<
|
|
5
|
-
name: keyof T;
|
|
4
|
+
export interface StatefulParameterOptions<V> {
|
|
6
5
|
isEqual?: (desired: any, current: any) => boolean;
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -15,20 +14,19 @@ export interface StatefulParameterOptions<T> {
|
|
|
15
14
|
* Set this flag to true to disable this behaviour
|
|
16
15
|
*/
|
|
17
16
|
disableStatelessModeArrayFiltering?: boolean;
|
|
17
|
+
default?: V;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export interface ArrayStatefulParameterOptions<
|
|
20
|
+
export interface ArrayStatefulParameterOptions<V> extends StatefulParameterOptions<V> {
|
|
21
21
|
isEqual?: (desired: any[], current: any[]) => boolean;
|
|
22
22
|
isElementEqual?: (desired: any, current: any) => boolean;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
export abstract class StatefulParameter<T extends StringIndexedObject, V extends T[keyof T]> {
|
|
27
|
-
readonly
|
|
28
|
-
readonly options: StatefulParameterOptions<T>;
|
|
27
|
+
readonly options: StatefulParameterOptions<V>;
|
|
29
28
|
|
|
30
|
-
protected constructor(options: StatefulParameterOptions<
|
|
31
|
-
this.name = options.name;
|
|
29
|
+
protected constructor(options: StatefulParameterOptions<V>) {
|
|
32
30
|
this.options = options
|
|
33
31
|
}
|
|
34
32
|
|
|
@@ -41,9 +39,9 @@ export abstract class StatefulParameter<T extends StringIndexedObject, V extends
|
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
export abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> extends StatefulParameter<T, any>{
|
|
44
|
-
options: ArrayStatefulParameterOptions<
|
|
42
|
+
options: ArrayStatefulParameterOptions<V>;
|
|
45
43
|
|
|
46
|
-
constructor(options: ArrayStatefulParameterOptions<
|
|
44
|
+
constructor(options: ArrayStatefulParameterOptions<V>) {
|
|
47
45
|
super(options);
|
|
48
46
|
this.options = options;
|
|
49
47
|
}
|
|
@@ -55,7 +53,7 @@ export abstract class ArrayStatefulParameter<T extends StringIndexedObject, V> e
|
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
async applyModify(newValues: V[], previousValues: V[], allowDeletes: boolean, plan: Plan<T>): Promise<void> {
|
|
58
|
-
const options = this.options as ArrayStatefulParameterOptions<
|
|
56
|
+
const options = this.options as ArrayStatefulParameterOptions<V>;
|
|
59
57
|
|
|
60
58
|
const valuesToAdd = newValues.filter((n) => !previousValues.some((p) => {
|
|
61
59
|
if (options.isElementEqual) {
|