codify-plugin-lib 1.0.128 → 1.0.130
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/plan/plan.d.ts +14 -14
- package/dist/plan/plan.js +60 -66
- package/dist/plugin/plugin.d.ts +2 -2
- package/dist/plugin/plugin.js +17 -14
- package/dist/resource/config-parser.d.ts +2 -5
- package/dist/resource/config-parser.js +1 -28
- package/dist/resource/resource-controller.d.ts +4 -4
- package/dist/resource/resource-controller.js +47 -49
- package/package.json +2 -2
- package/src/common/errors.test.ts +1 -1
- package/src/messages/handlers.test.ts +9 -3
- package/src/plan/plan.test.ts +21 -20
- package/src/plan/plan.ts +99 -105
- package/src/plugin/plugin.test.ts +8 -9
- package/src/plugin/plugin.ts +24 -16
- package/src/resource/config-parser.ts +6 -41
- package/src/resource/resource-controller-stateful-mode.test.ts +4 -4
- package/src/resource/resource-controller.test.ts +47 -32
- package/src/resource/resource-controller.ts +58 -58
- package/src/resource/resource-settings.test.ts +113 -83
- package/src/stateful-parameter/stateful-parameter-controller.test.ts +19 -10
- package/src/utils/test-utils.test.ts +6 -6
|
@@ -25,9 +25,11 @@ describe('Message handler tests', () => {
|
|
|
25
25
|
await handler.onMessage({
|
|
26
26
|
cmd: 'plan',
|
|
27
27
|
data: {
|
|
28
|
-
|
|
28
|
+
core: {
|
|
29
29
|
type: 'resourceType',
|
|
30
30
|
name: 'name',
|
|
31
|
+
},
|
|
32
|
+
desired: {
|
|
31
33
|
prop1: 'A',
|
|
32
34
|
prop2: 'B',
|
|
33
35
|
},
|
|
@@ -45,7 +47,6 @@ describe('Message handler tests', () => {
|
|
|
45
47
|
const handler = new MessageHandler(plugin);
|
|
46
48
|
|
|
47
49
|
process.send = (message) => {
|
|
48
|
-
console.log(message);
|
|
49
50
|
expect(message).toMatchObject({
|
|
50
51
|
cmd: 'plan_Response',
|
|
51
52
|
status: MessageStatus.ERROR,
|
|
@@ -168,6 +169,9 @@ describe('Message handler tests', () => {
|
|
|
168
169
|
expect(async () => await handler.onMessage({
|
|
169
170
|
cmd: 'plan',
|
|
170
171
|
data: {
|
|
172
|
+
core: {
|
|
173
|
+
type: 'resourceA',
|
|
174
|
+
},
|
|
171
175
|
desired: {
|
|
172
176
|
type: 'resourceA'
|
|
173
177
|
},
|
|
@@ -250,9 +254,11 @@ describe('Message handler tests', () => {
|
|
|
250
254
|
cmd: 'plan',
|
|
251
255
|
requestId: 'abcdef',
|
|
252
256
|
data: {
|
|
253
|
-
|
|
257
|
+
core: {
|
|
254
258
|
type: 'type',
|
|
255
259
|
name: 'name',
|
|
260
|
+
},
|
|
261
|
+
desired: {
|
|
256
262
|
prop1: 'A',
|
|
257
263
|
prop2: 'B',
|
|
258
264
|
},
|
package/src/plan/plan.test.ts
CHANGED
|
@@ -20,13 +20,12 @@ describe('Plan entity tests', () => {
|
|
|
20
20
|
previousValue: null,
|
|
21
21
|
newValue: 'propBValue'
|
|
22
22
|
}],
|
|
23
|
-
|
|
23
|
+
isStateful: false,
|
|
24
24
|
}, controller.parsedSettings.defaultValues);
|
|
25
25
|
|
|
26
26
|
expect(plan.currentConfig).to.be.null;
|
|
27
27
|
|
|
28
28
|
expect(plan.desiredConfig).toMatchObject({
|
|
29
|
-
type: 'type',
|
|
30
29
|
propA: 'defaultA',
|
|
31
30
|
propB: 'propBValue',
|
|
32
31
|
})
|
|
@@ -49,11 +48,10 @@ describe('Plan entity tests', () => {
|
|
|
49
48
|
previousValue: 'propBValue',
|
|
50
49
|
newValue: null,
|
|
51
50
|
}],
|
|
52
|
-
|
|
51
|
+
isStateful: false,
|
|
53
52
|
}, controller.parsedSettings.defaultValues);
|
|
54
53
|
|
|
55
54
|
expect(plan.currentConfig).toMatchObject({
|
|
56
|
-
type: 'type',
|
|
57
55
|
propA: 'defaultA',
|
|
58
56
|
propB: 'propBValue',
|
|
59
57
|
})
|
|
@@ -78,17 +76,15 @@ describe('Plan entity tests', () => {
|
|
|
78
76
|
previousValue: 'propBValue',
|
|
79
77
|
newValue: 'propBValue',
|
|
80
78
|
}],
|
|
81
|
-
|
|
79
|
+
isStateful: false,
|
|
82
80
|
}, controller.parsedSettings.defaultValues);
|
|
83
81
|
|
|
84
82
|
expect(plan.currentConfig).toMatchObject({
|
|
85
|
-
type: 'type',
|
|
86
83
|
propA: 'defaultA',
|
|
87
84
|
propB: 'propBValue',
|
|
88
85
|
})
|
|
89
86
|
|
|
90
87
|
expect(plan.desiredConfig).toMatchObject({
|
|
91
|
-
type: 'type',
|
|
92
88
|
propA: 'defaultA',
|
|
93
89
|
propB: 'propBValue',
|
|
94
90
|
})
|
|
@@ -116,13 +112,12 @@ describe('Plan entity tests', () => {
|
|
|
116
112
|
previousValue: null,
|
|
117
113
|
newValue: 'propAValue',
|
|
118
114
|
}],
|
|
119
|
-
|
|
115
|
+
isStateful: false,
|
|
120
116
|
}, controller.parsedSettings.defaultValues);
|
|
121
117
|
|
|
122
118
|
expect(plan.currentConfig).to.be.null
|
|
123
119
|
|
|
124
120
|
expect(plan.desiredConfig).toMatchObject({
|
|
125
|
-
type: 'type',
|
|
126
121
|
propA: 'propAValue',
|
|
127
122
|
propB: 'propBValue',
|
|
128
123
|
})
|
|
@@ -134,15 +129,15 @@ describe('Plan entity tests', () => {
|
|
|
134
129
|
|
|
135
130
|
it('Returns the original resource names', () => {
|
|
136
131
|
const plan = Plan.calculate<TestConfig>({
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
132
|
+
desired: { propA: 'propA' },
|
|
133
|
+
currentArray: [{ propA: 'propA2' }],
|
|
134
|
+
state: null,
|
|
135
|
+
core: {
|
|
141
136
|
type: 'type',
|
|
142
137
|
name: 'name1'
|
|
143
138
|
},
|
|
144
139
|
settings: new ParsedResourceSettings<TestConfig>({ id: 'type' }),
|
|
145
|
-
|
|
140
|
+
isStateful: false,
|
|
146
141
|
});
|
|
147
142
|
|
|
148
143
|
expect(plan.toResponse()).toMatchObject({
|
|
@@ -174,9 +169,12 @@ describe('Plan entity tests', () => {
|
|
|
174
169
|
}
|
|
175
170
|
|
|
176
171
|
const controller = new ResourceController(resource);
|
|
177
|
-
const plan = await controller.plan(
|
|
178
|
-
|
|
179
|
-
|
|
172
|
+
const plan = await controller.plan(
|
|
173
|
+
{ type: 'type' },
|
|
174
|
+
{ propZ: ['20.15'], } as any,
|
|
175
|
+
null,
|
|
176
|
+
false
|
|
177
|
+
)
|
|
180
178
|
|
|
181
179
|
expect(plan.changeSet.operation).to.eq(ResourceOperation.NOOP);
|
|
182
180
|
})
|
|
@@ -208,9 +206,12 @@ describe('Plan entity tests', () => {
|
|
|
208
206
|
}
|
|
209
207
|
|
|
210
208
|
const controller = new ResourceController(resource);
|
|
211
|
-
const plan = await controller.plan(
|
|
212
|
-
|
|
213
|
-
|
|
209
|
+
const plan = await controller.plan(
|
|
210
|
+
{ type: 'type' },
|
|
211
|
+
{ propZ: ['20.15'], } as any,
|
|
212
|
+
null,
|
|
213
|
+
false
|
|
214
|
+
)
|
|
214
215
|
|
|
215
216
|
expect(plan.changeSet).toMatchObject({
|
|
216
217
|
operation: ResourceOperation.MODIFY,
|
package/src/plan/plan.ts
CHANGED
|
@@ -34,13 +34,13 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
34
34
|
*/
|
|
35
35
|
coreParameters: ResourceConfig;
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
isStateful: boolean;
|
|
38
38
|
|
|
39
|
-
constructor(id: string, changeSet: ChangeSet<T>,
|
|
39
|
+
constructor(id: string, changeSet: ChangeSet<T>, coreParameters: ResourceConfig, isStateful: boolean) {
|
|
40
40
|
this.id = id;
|
|
41
41
|
this.changeSet = changeSet;
|
|
42
|
-
this.coreParameters =
|
|
43
|
-
this.
|
|
42
|
+
this.coreParameters = coreParameters;
|
|
43
|
+
this.isStateful = isStateful;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -51,10 +51,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
return
|
|
55
|
-
...this.coreParameters,
|
|
56
|
-
...this.changeSet.desiredParameters,
|
|
57
|
-
}
|
|
54
|
+
return this.changeSet.desiredParameters;
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
/**
|
|
@@ -65,10 +62,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
65
62
|
return null;
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
return
|
|
69
|
-
...this.coreParameters,
|
|
70
|
-
...this.changeSet.currentParameters,
|
|
71
|
-
}
|
|
65
|
+
return this.changeSet.currentParameters;
|
|
72
66
|
}
|
|
73
67
|
|
|
74
68
|
get resourceId(): string {
|
|
@@ -78,71 +72,71 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
static calculate<T extends StringIndexedObject>(params: {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
desired: Partial<T> | null,
|
|
76
|
+
currentArray: Partial<T>[] | null,
|
|
77
|
+
state: Partial<T> | null,
|
|
78
|
+
core: ResourceConfig,
|
|
85
79
|
settings: ParsedResourceSettings<T>,
|
|
86
|
-
|
|
80
|
+
isStateful: boolean,
|
|
87
81
|
}): Plan<T> {
|
|
88
82
|
const {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
desired,
|
|
84
|
+
currentArray,
|
|
85
|
+
state,
|
|
86
|
+
core,
|
|
93
87
|
settings,
|
|
94
|
-
|
|
88
|
+
isStateful
|
|
95
89
|
} = params
|
|
96
90
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
const current = Plan.matchCurrentParameters<T>({
|
|
92
|
+
desired,
|
|
93
|
+
currentArray,
|
|
94
|
+
state,
|
|
101
95
|
settings,
|
|
102
|
-
|
|
96
|
+
isStateful
|
|
103
97
|
});
|
|
104
98
|
|
|
105
99
|
const filteredCurrentParameters = Plan.filterCurrentParams<T>({
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
desired,
|
|
101
|
+
current,
|
|
102
|
+
state,
|
|
109
103
|
settings,
|
|
110
|
-
|
|
104
|
+
isStateful
|
|
111
105
|
});
|
|
112
106
|
|
|
113
107
|
// Empty
|
|
114
|
-
if (!filteredCurrentParameters && !
|
|
108
|
+
if (!filteredCurrentParameters && !desired) {
|
|
115
109
|
return new Plan(
|
|
116
110
|
uuidV4(),
|
|
117
111
|
ChangeSet.empty<T>(),
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
core,
|
|
113
|
+
isStateful,
|
|
120
114
|
)
|
|
121
115
|
}
|
|
122
116
|
|
|
123
117
|
// CREATE
|
|
124
|
-
if (!filteredCurrentParameters &&
|
|
118
|
+
if (!filteredCurrentParameters && desired) {
|
|
125
119
|
return new Plan(
|
|
126
120
|
uuidV4(),
|
|
127
|
-
ChangeSet.create(
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
ChangeSet.create(desired),
|
|
122
|
+
core,
|
|
123
|
+
isStateful,
|
|
130
124
|
)
|
|
131
125
|
}
|
|
132
126
|
|
|
133
127
|
// DESTROY
|
|
134
|
-
if (filteredCurrentParameters && !
|
|
128
|
+
if (filteredCurrentParameters && !desired) {
|
|
135
129
|
return new Plan(
|
|
136
130
|
uuidV4(),
|
|
137
131
|
ChangeSet.destroy(filteredCurrentParameters),
|
|
138
|
-
|
|
139
|
-
|
|
132
|
+
core,
|
|
133
|
+
isStateful,
|
|
140
134
|
)
|
|
141
135
|
}
|
|
142
136
|
|
|
143
137
|
// NO-OP, MODIFY or RE-CREATE
|
|
144
138
|
const changeSet = ChangeSet.calculateModification(
|
|
145
|
-
|
|
139
|
+
desired!,
|
|
146
140
|
filteredCurrentParameters!,
|
|
147
141
|
settings.parameterSettings,
|
|
148
142
|
);
|
|
@@ -150,60 +144,11 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
150
144
|
return new Plan(
|
|
151
145
|
uuidV4(),
|
|
152
146
|
changeSet,
|
|
153
|
-
|
|
154
|
-
|
|
147
|
+
core,
|
|
148
|
+
isStateful,
|
|
155
149
|
);
|
|
156
150
|
}
|
|
157
151
|
|
|
158
|
-
/**
|
|
159
|
-
* When multiples of the same resource are allowed, this matching function will match a given config with one of the
|
|
160
|
-
* existing configs on the system. For example if there are multiple versions of Android Studios installed, we can use
|
|
161
|
-
* the application name and location to match it to our desired configs name and location.
|
|
162
|
-
*
|
|
163
|
-
* @param params
|
|
164
|
-
* @private
|
|
165
|
-
*/
|
|
166
|
-
private static matchCurrentParameters<T extends StringIndexedObject>(params: {
|
|
167
|
-
desiredParameters: Partial<T> | null,
|
|
168
|
-
currentParametersArray: Partial<T>[] | null,
|
|
169
|
-
stateParameters: Partial<T> | null,
|
|
170
|
-
settings: ResourceSettings<T>,
|
|
171
|
-
statefulMode: boolean,
|
|
172
|
-
}): Partial<T> | null {
|
|
173
|
-
const {
|
|
174
|
-
desiredParameters,
|
|
175
|
-
currentParametersArray,
|
|
176
|
-
stateParameters,
|
|
177
|
-
settings,
|
|
178
|
-
statefulMode
|
|
179
|
-
} = params;
|
|
180
|
-
|
|
181
|
-
if (!settings.allowMultiple) {
|
|
182
|
-
return currentParametersArray?.[0] ?? null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (!currentParametersArray) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (statefulMode) {
|
|
190
|
-
return stateParameters
|
|
191
|
-
? settings.allowMultiple.matcher(stateParameters, currentParametersArray)
|
|
192
|
-
: null
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return settings.allowMultiple.matcher(desiredParameters!, currentParametersArray);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* The type (id) of the resource
|
|
200
|
-
*
|
|
201
|
-
* @return string
|
|
202
|
-
*/
|
|
203
|
-
getResourceType(): string {
|
|
204
|
-
return this.coreParameters.type
|
|
205
|
-
}
|
|
206
|
-
|
|
207
152
|
// 2. Even if there was (maybe for testing reasons), the plan values should not be adjusted
|
|
208
153
|
static fromResponse<T extends ResourceConfig>(data: ApplyRequestData['plan'], defaultValues?: Partial<Record<keyof T, unknown>>): Plan<T> {
|
|
209
154
|
if (!data) {
|
|
@@ -222,7 +167,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
222
167
|
type: data.resourceType,
|
|
223
168
|
name: data.resourceName,
|
|
224
169
|
},
|
|
225
|
-
data.
|
|
170
|
+
data.isStateful
|
|
226
171
|
);
|
|
227
172
|
|
|
228
173
|
function addDefaultValues(): void {
|
|
@@ -275,6 +220,55 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
275
220
|
|
|
276
221
|
}
|
|
277
222
|
|
|
223
|
+
/**
|
|
224
|
+
* The type (id) of the resource
|
|
225
|
+
*
|
|
226
|
+
* @return string
|
|
227
|
+
*/
|
|
228
|
+
getResourceType(): string {
|
|
229
|
+
return this.coreParameters.type
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* When multiples of the same resource are allowed, this matching function will match a given config with one of the
|
|
234
|
+
* existing configs on the system. For example if there are multiple versions of Android Studios installed, we can use
|
|
235
|
+
* the application name and location to match it to our desired configs name and location.
|
|
236
|
+
*
|
|
237
|
+
* @param params
|
|
238
|
+
* @private
|
|
239
|
+
*/
|
|
240
|
+
private static matchCurrentParameters<T extends StringIndexedObject>(params: {
|
|
241
|
+
desired: Partial<T> | null,
|
|
242
|
+
currentArray: Partial<T>[] | null,
|
|
243
|
+
state: Partial<T> | null,
|
|
244
|
+
settings: ResourceSettings<T>,
|
|
245
|
+
isStateful: boolean,
|
|
246
|
+
}): Partial<T> | null {
|
|
247
|
+
const {
|
|
248
|
+
desired,
|
|
249
|
+
currentArray,
|
|
250
|
+
state,
|
|
251
|
+
settings,
|
|
252
|
+
isStateful
|
|
253
|
+
} = params;
|
|
254
|
+
|
|
255
|
+
if (!settings.allowMultiple) {
|
|
256
|
+
return currentArray?.[0] ?? null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!currentArray) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (isStateful) {
|
|
264
|
+
return state
|
|
265
|
+
? settings.allowMultiple.matcher(state, currentArray)
|
|
266
|
+
: null
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return settings.allowMultiple.matcher(desired!, currentArray);
|
|
270
|
+
}
|
|
271
|
+
|
|
278
272
|
/**
|
|
279
273
|
* Only keep relevant params for the plan. We don't want to change settings that were not already
|
|
280
274
|
* defined.
|
|
@@ -284,18 +278,18 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
284
278
|
* or wants to set. If a parameter is not specified then it's not managed by Codify.
|
|
285
279
|
*/
|
|
286
280
|
private static filterCurrentParams<T extends StringIndexedObject>(params: {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
281
|
+
desired: Partial<T> | null,
|
|
282
|
+
current: Partial<T> | null,
|
|
283
|
+
state: Partial<T> | null,
|
|
290
284
|
settings: ResourceSettings<T>,
|
|
291
|
-
|
|
285
|
+
isStateful: boolean,
|
|
292
286
|
}): Partial<T> | null {
|
|
293
287
|
const {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
288
|
+
desired,
|
|
289
|
+
current,
|
|
290
|
+
state,
|
|
297
291
|
settings,
|
|
298
|
-
|
|
292
|
+
isStateful
|
|
299
293
|
} = params;
|
|
300
294
|
|
|
301
295
|
if (!current) {
|
|
@@ -309,7 +303,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
309
303
|
|
|
310
304
|
// For stateful mode, we're done after filtering by the keys of desired + state. Stateless mode
|
|
311
305
|
// requires additional filtering for stateful parameter arrays and objects.
|
|
312
|
-
if (
|
|
306
|
+
if (isStateful) {
|
|
313
307
|
return filteredCurrent;
|
|
314
308
|
}
|
|
315
309
|
|
|
@@ -327,7 +321,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
327
321
|
return null;
|
|
328
322
|
}
|
|
329
323
|
|
|
330
|
-
if (
|
|
324
|
+
if (isStateful) {
|
|
331
325
|
const keys = new Set([...Object.keys(state ?? {}), ...Object.keys(desired ?? {})]);
|
|
332
326
|
return Object.fromEntries(
|
|
333
327
|
Object.entries(current)
|
|
@@ -426,7 +420,7 @@ export class Plan<T extends StringIndexedObject> {
|
|
|
426
420
|
return {
|
|
427
421
|
planId: this.id,
|
|
428
422
|
operation: this.changeSet.operation,
|
|
429
|
-
|
|
423
|
+
isStateful: this.isStateful,
|
|
430
424
|
resourceName: this.coreParameters.name,
|
|
431
425
|
resourceType: this.coreParameters.type,
|
|
432
426
|
parameters: this.changeSet.parameterChanges,
|
|
@@ -56,7 +56,7 @@ describe('Plugin tests', () => {
|
|
|
56
56
|
parameters: [
|
|
57
57
|
{ name: 'propA', operation: ParameterOperation.ADD, newValue: 'abc', previousValue: null },
|
|
58
58
|
],
|
|
59
|
-
|
|
59
|
+
isStateful: false,
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
await plugin.apply({ plan });
|
|
@@ -77,7 +77,7 @@ describe('Plugin tests', () => {
|
|
|
77
77
|
parameters: [
|
|
78
78
|
{ name: 'propA', operation: ParameterOperation.REMOVE, newValue: null, previousValue: 'abc' },
|
|
79
79
|
],
|
|
80
|
-
|
|
80
|
+
isStateful: true,
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
await testPlugin.apply({ plan })
|
|
@@ -100,7 +100,7 @@ describe('Plugin tests', () => {
|
|
|
100
100
|
parameters: [
|
|
101
101
|
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
102
102
|
],
|
|
103
|
-
|
|
103
|
+
isStateful: false,
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
await testPlugin.apply({ plan })
|
|
@@ -124,7 +124,7 @@ describe('Plugin tests', () => {
|
|
|
124
124
|
parameters: [
|
|
125
125
|
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
126
126
|
],
|
|
127
|
-
|
|
127
|
+
isStateful: false,
|
|
128
128
|
};
|
|
129
129
|
|
|
130
130
|
await testPlugin.apply({ plan })
|
|
@@ -224,7 +224,7 @@ describe('Plugin tests', () => {
|
|
|
224
224
|
parameters: [
|
|
225
225
|
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
226
226
|
],
|
|
227
|
-
|
|
227
|
+
isStateful: false,
|
|
228
228
|
};
|
|
229
229
|
|
|
230
230
|
await expect(() => testPlugin.apply({ plan }))
|
|
@@ -245,9 +245,8 @@ describe('Plugin tests', () => {
|
|
|
245
245
|
|
|
246
246
|
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
247
247
|
await testPlugin.plan({
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
},
|
|
248
|
+
core: { type: 'testResource' },
|
|
249
|
+
desired: {},
|
|
251
250
|
state: undefined,
|
|
252
251
|
isStateful: false,
|
|
253
252
|
})
|
|
@@ -275,7 +274,7 @@ describe('Plugin tests', () => {
|
|
|
275
274
|
parameters: [
|
|
276
275
|
{ name: 'propA', operation: ParameterOperation.ADD, newValue: 'abc', previousValue: null },
|
|
277
276
|
],
|
|
278
|
-
|
|
277
|
+
isStateful: false,
|
|
279
278
|
};
|
|
280
279
|
|
|
281
280
|
await testPlugin.apply({ plan })
|
package/src/plugin/plugin.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
PlanRequestData,
|
|
10
10
|
PlanResponseData,
|
|
11
11
|
ResourceConfig,
|
|
12
|
+
ResourceJson,
|
|
12
13
|
ValidateRequestData,
|
|
13
14
|
ValidateResponseData
|
|
14
15
|
} from 'codify-schemas';
|
|
@@ -83,18 +84,20 @@ export class Plugin {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
async import(data: ImportRequestData): Promise<ImportResponseData> {
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
const { core, parameters } = data;
|
|
88
|
+
|
|
89
|
+
if (!this.resourceControllers.has(core.type)) {
|
|
90
|
+
throw new Error(`Cannot get info for resource ${core.type}, resource doesn't exist`);
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
const result = await ptyLocalStorage.run(this.planPty, () =>
|
|
91
94
|
this.resourceControllers
|
|
92
|
-
.get(
|
|
93
|
-
?.import(
|
|
95
|
+
.get(core.type!)
|
|
96
|
+
?.import(core, parameters)
|
|
94
97
|
)
|
|
95
98
|
|
|
96
99
|
return {
|
|
97
|
-
request: data
|
|
100
|
+
request: data,
|
|
98
101
|
result: result ?? [],
|
|
99
102
|
}
|
|
100
103
|
}
|
|
@@ -102,13 +105,15 @@ export class Plugin {
|
|
|
102
105
|
async validate(data: ValidateRequestData): Promise<ValidateResponseData> {
|
|
103
106
|
const validationResults = [];
|
|
104
107
|
for (const config of data.configs) {
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
const { core, parameters } = config;
|
|
109
|
+
|
|
110
|
+
if (!this.resourceControllers.has(core.type)) {
|
|
111
|
+
throw new Error(`Resource type not found: ${core.type}`);
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
const validation = await this.resourceControllers
|
|
110
|
-
.get(
|
|
111
|
-
.validate(
|
|
115
|
+
.get(core.type)!
|
|
116
|
+
.validate(core, parameters);
|
|
112
117
|
|
|
113
118
|
validationResults.push(validation);
|
|
114
119
|
}
|
|
@@ -120,16 +125,17 @@ export class Plugin {
|
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
async plan(data: PlanRequestData): Promise<PlanResponseData> {
|
|
123
|
-
const type = data.
|
|
128
|
+
const { type } = data.core
|
|
124
129
|
|
|
125
|
-
if (!
|
|
130
|
+
if (!this.resourceControllers.has(type)) {
|
|
126
131
|
throw new Error(`Resource type not found: ${type}`);
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
const plan = await ptyLocalStorage.run(this.planPty, async () => this.resourceControllers.get(type)!.plan(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
data.core,
|
|
136
|
+
data.desired ?? null,
|
|
137
|
+
data.state ?? null,
|
|
138
|
+
data.isStateful
|
|
133
139
|
))
|
|
134
140
|
|
|
135
141
|
this.planStorage.set(plan.id, plan);
|
|
@@ -155,9 +161,10 @@ export class Plugin {
|
|
|
155
161
|
// Default back desired back to current if it is not defined (for destroys only)
|
|
156
162
|
const validationPlan = await ptyLocalStorage.run(new BackgroundPty(), async () => {
|
|
157
163
|
const result = await resource.plan(
|
|
164
|
+
plan.coreParameters,
|
|
158
165
|
plan.desiredConfig,
|
|
159
166
|
plan.desiredConfig ?? plan.currentConfig,
|
|
160
|
-
plan.
|
|
167
|
+
plan.isStateful
|
|
161
168
|
);
|
|
162
169
|
|
|
163
170
|
await getPty().kill();
|
|
@@ -192,5 +199,6 @@ export class Plugin {
|
|
|
192
199
|
return Plan.fromResponse(planRequest, resource.parsedSettings.defaultValues);
|
|
193
200
|
}
|
|
194
201
|
|
|
195
|
-
protected async crossValidateResources(
|
|
202
|
+
protected async crossValidateResources(resources: ResourceJson[]): Promise<void> {
|
|
203
|
+
}
|
|
196
204
|
}
|