2fd7069a09
The code that computed --target deletion dependants was not correct. It used parent/child component relationships, but did not respect actual DAG dependencies. As a result, it could erroneously leave hanging references to resources that no longer exist after performing a `pulumi destroy --target X` operation. This manifested in bugs like https://github.com/pulumi/pulumi/issues/6283, which is fixed by this change. The solution is to compute the (transitive!) dependency graph correctly, factoring in both parent/child, as well as explicit and implicit, dependencies. The existing logic does the correct thing once we do this. I've also added tests for this area, including regression tests that cover transitive dependency relationships, as well as ones that would cause an infinite loop given a naive implementation.
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
// Copyright 2021, Pulumi Corporation. All rights reserved.
|
|
|
|
import * as pulumi from "@pulumi/pulumi";
|
|
|
|
interface MyResourceArgs {
|
|
input?: pulumi.Input<string> | undefined;
|
|
}
|
|
|
|
class MyResource extends pulumi.dynamic.Resource {
|
|
static latestId: number = 0;
|
|
|
|
constructor(name, args?: MyResourceArgs, opts?: pulumi.CustomResourceOptions) {
|
|
super({
|
|
async create(inputs: any) {
|
|
return { id: (MyResource.latestId++).toString() };
|
|
},
|
|
}, name, args || {}, opts);
|
|
}
|
|
}
|
|
|
|
// Create a chain of resources, such that attempting to delete
|
|
// one will fail due to numerous dependency violations. This includes
|
|
// both implicit and explicit, as well as parent/child, dependencies.
|
|
|
|
// A
|
|
// B (impl depends on A)
|
|
// C (expl depends on A)
|
|
// D (impl depends on B)
|
|
// E (expl depends on B)
|
|
// F (child of A)
|
|
// G (child of B)
|
|
// H (expl depends on A, B, impl depends on C, D, child of F)
|
|
|
|
const a = new MyResource("a");
|
|
const b = new MyResource("b", { input: a.urn });
|
|
const c = new MyResource("c", { }, { dependsOn: a });
|
|
const d = new MyResource("d", { input: b.urn });
|
|
const e = new MyResource("e", { }, { dependsOn: b });
|
|
const f = new MyResource("f", { }, { parent: a });
|
|
const g = new MyResource("g", { }, { parent: b });
|
|
const h = new MyResource("h",
|
|
{ input: pulumi.all(([c.urn, d.urn])).apply(([curn, _])=>curn) },
|
|
{
|
|
dependsOn: [a, b],
|
|
parent: f,
|
|
},
|
|
);
|