Skip to content

Commit 7027c5a

Browse files
committed
Fixed bug with resources not being destroyed
1 parent f7035c5 commit 7027c5a

4 files changed

Lines changed: 118 additions & 4 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codify-plugin-test",
3-
"version": "0.0.25",
3+
"version": "0.0.26",
44
"description": "",
55
"main": "dist/index.js",
66
"typings": "dist/index.d.ts",

src/plugin-tester.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,13 @@ ${JSON.stringify(modifyPlans, null, 2)}`)
177177
}
178178

179179
if (!skipUninstall) {
180-
const id = (config: ResourceConfig) => config.type + config.name ? `.${config.name}` : '';
180+
// We need to add unique names to multiple configs with the same type or else it breaks the unionBy below.
181+
const configsWithNames = this.addNamesToConfigs(configs);
182+
const modifiedConfigs = this.addNamesToConfigs(options?.testModify?.modifiedConfigs ?? [])
181183

182-
const configsToDestroy = unionBy(options?.testModify?.modifiedConfigs ?? [], configs, id);
184+
const id = (config: ResourceConfig) => config.type + (config.name ? `.${config.name}` : '')
185+
186+
const configsToDestroy = unionBy(modifiedConfigs, configsWithNames, id);
183187
await this.uninstall(configsToDestroy.toReversed(), options);
184188
}
185189
}
@@ -291,6 +295,22 @@ ${JSON.stringify(validationPlan, null, 2)}
291295
}
292296
})
293297
}
298+
299+
private addNamesToConfigs(configs: ResourceConfig[]): ResourceConfig[] {
300+
const configsWithNames = new Array<ResourceConfig>();
301+
302+
const typeSet = new Set(configs.map((c) => c.type));
303+
for (const type of typeSet) {
304+
const sameTypeConfigs = configs.filter((c) => c.type === type);
305+
if (sameTypeConfigs.length > 1) {
306+
sameTypeConfigs.forEach((c, idx) => { c.name = c.name ?? idx.toString() });
307+
}
308+
309+
configsWithNames.push(...sameTypeConfigs);
310+
}
311+
312+
return configsWithNames;
313+
}
294314
}
295315

296316

test/plugin-tester.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,56 @@ describe('Plugin tester integration tests', () => {
277277
)
278278
})
279279

280+
it('Works when uninstalling two resources', async () => {
281+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
282+
283+
await plugin.fullTest([{
284+
type: 'test-destroy',
285+
propA: 'a',
286+
propB: 10,
287+
}, {
288+
type: 'test-destroy-2',
289+
propA: 'a',
290+
propB: 20,
291+
}], {
292+
validateDestroy(plan) {
293+
expect(plan.length).to.eq(2);
294+
expect(plan[0]).toMatchObject({
295+
operation: 'destroy',
296+
resourceType: 'test-destroy-2',
297+
})
298+
expect(plan[1]).toMatchObject({
299+
operation: 'destroy',
300+
resourceType: 'test-destroy',
301+
})
302+
}
303+
});
304+
})
305+
306+
it('Can uninstall two resources with the same type', async () => {
307+
const plugin = new PluginTester(path.join(__dirname, './test-plugin.ts'));
308+
309+
await plugin.fullTest([{
310+
type: 'test-destroy',
311+
propA: 'a',
312+
propB: 10,
313+
}, {
314+
type: 'test-destroy',
315+
propA: 'a',
316+
propB: 20,
317+
}], {
318+
validateDestroy(plan) {
319+
expect(plan.length).to.eq(2);
320+
expect(plan[0]).toMatchObject({
321+
operation: 'destroy',
322+
resourceType: 'test-destroy',
323+
})
324+
expect(plan[1]).toMatchObject({
325+
operation: 'destroy',
326+
resourceType: 'test-destroy',
327+
})
328+
}
329+
});
330+
})
331+
280332
})

test/test-plugin.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,54 @@ export class TestModifyResource extends Resource<TestConfig> {
132132
async destroy(plan: DestroyPlan<TestConfig>): Promise<void> {}
133133
}
134134

135+
export class TestDestroyResource extends Resource<TestConfig> {
136+
private isCreated: boolean;
137+
private isDestroyed: boolean;
138+
139+
getSettings(): ResourceSettings<TestConfig> {
140+
return {
141+
id: 'test-destroy',
142+
}
143+
}
144+
145+
async refresh(parameters: Partial<TestConfig>): Promise<Array<Partial<TestConfig>> | Partial<TestConfig> | null> {
146+
if (this.isCreated && !this.isDestroyed) {
147+
return parameters;
148+
}
149+
150+
return null;
151+
}
152+
153+
async modify(pc: ParameterChange<TestConfig>, plan: ModifyPlan<TestConfig>): Promise<void> {
154+
return super.modify(pc, plan);
155+
}
156+
157+
async create(plan: CreatePlan<TestConfig>): Promise<void> {
158+
this.isCreated = true;
159+
}
160+
161+
async destroy(plan: DestroyPlan<TestConfig>): Promise<void> {
162+
this.isDestroyed = true;
163+
console.log('destroy');
164+
}
165+
}
166+
167+
export class TestDestroyResource2 extends TestDestroyResource {
168+
getSettings(): ResourceSettings<TestConfig> {
169+
return {
170+
id: 'test-destroy-2',
171+
}
172+
}
173+
}
174+
135175
runPlugin(Plugin.create(
136176
'default',
137177
[
138178
new TestResource(),
139179
new TestResource2(),
140180
new TestUninstallResource(),
141-
new TestModifyResource()
181+
new TestModifyResource(),
182+
new TestDestroyResource(),
183+
new TestDestroyResource2()
142184
]
143185
));

0 commit comments

Comments
 (0)