@intentius/chant-lexicon-terraform 0.59.0 → 0.61.0
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/describe-resources.d.ts +59 -0
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/hcl/edges.d.ts +124 -0
- package/dist/hcl/edges.d.ts.map +1 -0
- package/dist/hcl/parse.d.ts +42 -0
- package/dist/hcl/parse.d.ts.map +1 -1
- package/dist/hcl/roots.d.ts +6 -0
- package/dist/hcl/roots.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/op/activities/terraform.d.ts +44 -8
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/adoption.d.ts +110 -35
- package/dist/op/adoption.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__fixtures__/ACCEPTANCE.md +92 -58
- package/src/__fixtures__/graph-roots/README.md +21 -0
- package/src/__fixtures__/graph-roots/app/main.tf +41 -0
- package/src/__fixtures__/graph-roots/app/modules/cdn/main.tf +7 -0
- package/src/__fixtures__/graph-roots/network/main.tf +16 -0
- package/src/__fixtures__/live-estate/README.md +65 -19
- package/src/__fixtures__/live-estate/adoptable.tf +13 -0
- package/src/__fixtures__/live-ls.json +5 -5
- package/src/__fixtures__/live-plan.json +67 -35
- package/src/composites/terraform-adopt-op.acceptance.test.ts +36 -50
- package/src/composites/terraform-apply-op.acceptance.test.ts +4 -2
- package/src/describe-resources.live.test.ts +76 -4
- package/src/describe-resources.test.ts +35 -0
- package/src/describe-resources.ts +110 -3
- package/src/hcl/edges.test.ts +207 -0
- package/src/hcl/edges.ts +316 -0
- package/src/hcl/parse.ts +53 -0
- package/src/hcl/roots.ts +14 -0
- package/src/index.ts +1 -0
- package/src/op/activities/choudoufu.test.ts +3 -3
- package/src/op/activities/terraform.ts +70 -21
- package/src/op/adoption.test.ts +129 -11
- package/src/op/adoption.ts +181 -49
|
@@ -277,10 +277,10 @@ describe("isOlderVersion / parseChoudoufuVersion (#2103)", () => {
|
|
|
277
277
|
// ── The version check, wired into every activity via resolveRoot ───────────
|
|
278
278
|
|
|
279
279
|
describe("choudoufu version check (#2103)", () => {
|
|
280
|
-
test("refuses a binary older than the floor, which the
|
|
280
|
+
test("refuses a binary older than the floor, which the adoptable section moved to v0.15.0", async () => {
|
|
281
281
|
const dir = liveProject();
|
|
282
|
-
replies.push({ match: "version", reply: { stdout: "choudoufu v0.
|
|
283
|
-
await expect(choudoufuLiveCheck({ root: "estate", cwd: dir })).rejects.toThrow(/older than.*v0\.
|
|
282
|
+
replies.push({ match: "version", reply: { stdout: "choudoufu v0.14.0 (based on OpenTofu v1.13.0)\n", stderr: "" } });
|
|
283
|
+
await expect(choudoufuLiveCheck({ root: "estate", cwd: dir })).rejects.toThrow(/older than.*v0\.15\.0/);
|
|
284
284
|
});
|
|
285
285
|
|
|
286
286
|
test("passes at exactly the minimum version", async () => {
|
|
@@ -81,11 +81,20 @@ export const DEFAULT_LIVE_PLAN_DOCUMENT_FILE = "chant.live-plan.json";
|
|
|
81
81
|
* estate ([choudoufu #894](https://github.com/INTENTIUS/choudoufu/issues/894),
|
|
82
82
|
* PR 915), which is the shape every chant live root has: before it,
|
|
83
83
|
* {@link choudoufuLivePlan} could not produce the document for a real root at
|
|
84
|
-
* all.
|
|
85
|
-
*
|
|
86
|
-
*
|
|
84
|
+
* all. v0.15.0 brought the document's `adoptable` section and the `swept`
|
|
85
|
+
* list beside it
|
|
86
|
+
* ([choudoufu #962](https://github.com/INTENTIUS/choudoufu/issues/962), PR
|
|
87
|
+
* 963), which is the only place a content match reaches a machine: before it,
|
|
88
|
+
* a declared resource whose identity the provider assigns could never be
|
|
89
|
+
* adopted through the document at all, and `TerraformAdoptOp`'s own
|
|
90
|
+
* acceptance suite had never passed on any binary (#2241).
|
|
91
|
+
*
|
|
92
|
+
* {@link terraformApply} depends on the exit-3 refusal, `describeResources()`
|
|
93
|
+
* and both document-reading Ops depend on the document, and the adopt path
|
|
94
|
+
* depends on the `adoptable` section, so the floor is the release that
|
|
95
|
+
* shipped the last of the three.
|
|
87
96
|
*/
|
|
88
|
-
export const MIN_CHOUDOUFU_VERSION = "0.
|
|
97
|
+
export const MIN_CHOUDOUFU_VERSION = "0.15.0";
|
|
89
98
|
|
|
90
99
|
/**
|
|
91
100
|
* choudoufu's own refusal summary for `-out` on the `live-plan -estate`
|
|
@@ -185,6 +194,12 @@ export interface ChoudoufuLivePlanArgs extends TerraformRootArgs {
|
|
|
185
194
|
* cost is that the second read asks the estate-wide sweep the account-bounded
|
|
186
195
|
* question ("which live resources carry no ownership marker at all"), so it
|
|
187
196
|
* is slower than the ordinary render, not faster.
|
|
197
|
+
*
|
|
198
|
+
* Since #2241 the flag also puts `TOFU_LIVE_COLLECT_UNCLAIMED=1` on the
|
|
199
|
+
* `-json` run, so the document carries the same sweep's answer as its
|
|
200
|
+
* `adoptable` and `swept` sections rather than only the render carrying it.
|
|
201
|
+
* That is what an adoption reads: the render's rows are prose, and the
|
|
202
|
+
* document's are addresses, marker values and a tagging command.
|
|
188
203
|
*/
|
|
189
204
|
adoptionOnly?: boolean;
|
|
190
205
|
}
|
|
@@ -276,11 +291,22 @@ export interface TerraformApplyResult {
|
|
|
276
291
|
refusal?: string;
|
|
277
292
|
}
|
|
278
293
|
|
|
279
|
-
/** Counts projected out of `live-plan -json`'s `unowned`
|
|
294
|
+
/** Counts projected out of `live-plan -json`'s `unowned` and `adoptable` sections. */
|
|
280
295
|
export interface LivePlanUnownedCounts {
|
|
281
|
-
/**
|
|
296
|
+
/**
|
|
297
|
+
* `unowned[]`'s length: live resources sitting at an identity this
|
|
298
|
+
* configuration declares, carrying no ownership marker for this estate.
|
|
299
|
+
*/
|
|
282
300
|
unowned: number;
|
|
283
|
-
/**
|
|
301
|
+
/**
|
|
302
|
+
* Every live resource this run could claim with a tag write, from both
|
|
303
|
+
* sections: the `unowned[]` rows choudoufu offered marker values for, plus
|
|
304
|
+
* the `adoptable[]` rows the estate-wide sweep content-matched to a
|
|
305
|
+
* declaration that carries no identity of its own (choudoufu #962). Those
|
|
306
|
+
* two sections are disjoint, so this is a sum and never a double count.
|
|
307
|
+
* `adoptable[]` is populated only on an adoption run (#2241), so an
|
|
308
|
+
* observation read's document contributes nothing to it.
|
|
309
|
+
*/
|
|
284
310
|
adoptable: number;
|
|
285
311
|
}
|
|
286
312
|
|
|
@@ -306,7 +332,10 @@ export interface LivePlanUnownedCounts {
|
|
|
306
332
|
export interface ChoudoufuLivePlanResult extends LivePlanUnownedCounts, PlanChangeCounts {
|
|
307
333
|
/** `true` when `-detailed-exitcode` reported exit 2: the live plan proposes changes. */
|
|
308
334
|
drift: boolean;
|
|
309
|
-
/**
|
|
335
|
+
/**
|
|
336
|
+
* GitHub issue #788's JSON document (`bound`, `omissions`, `unowned`, and
|
|
337
|
+
* since choudoufu v0.15.0 `adoptable` and `swept`), captured whole.
|
|
338
|
+
*/
|
|
310
339
|
json: unknown;
|
|
311
340
|
/**
|
|
312
341
|
* The human-readable plan, from a second `live-plan` run without `-json`
|
|
@@ -334,6 +363,13 @@ export interface ChoudoufuLivePlanResult extends LivePlanUnownedCounts, PlanChan
|
|
|
334
363
|
contested: AdoptionCandidate[];
|
|
335
364
|
/** How many declared addresses are contested — the count `contested` above spells out. */
|
|
336
365
|
ambiguous: number;
|
|
366
|
+
/**
|
|
367
|
+
* `swept[]`: the resource types the estate-wide sweep listed in full on this
|
|
368
|
+
* run. Empty on any run that did not ask for the sweep, which is every run
|
|
369
|
+
* without {@link ChoudoufuLivePlanArgs.adoptionOnly}, so an empty
|
|
370
|
+
* `adoptions` beside an empty `swept` means the question was never put.
|
|
371
|
+
*/
|
|
372
|
+
swept: string[];
|
|
337
373
|
/** Absolute path of the root module directory. */
|
|
338
374
|
dir: string;
|
|
339
375
|
/** Where the JSON document was written, relative to `dir`; {@link DEFAULT_LIVE_PLAN_DOCUMENT_FILE} unless overridden. */
|
|
@@ -549,14 +585,14 @@ export function choudoufuLiveCheckCommand(opts: { binary: string }): string {
|
|
|
549
585
|
* (`adopt_tofu_estate`/`adopt_tofu_address` present).
|
|
550
586
|
*/
|
|
551
587
|
export function countLivePlanUnowned(document: unknown): LivePlanUnownedCounts {
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
for (const entry of unowned) {
|
|
588
|
+
const doc = (document ?? {}) as { unowned?: unknown; adoptable?: unknown };
|
|
589
|
+
const unowned = Array.isArray(doc.unowned) ? doc.unowned : [];
|
|
590
|
+
const claimable = (entry: unknown): boolean => {
|
|
556
591
|
const e = entry as { adopt_tofu_estate?: unknown; adopt_tofu_address?: unknown } | null | undefined;
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
|
|
592
|
+
return Boolean(e?.adopt_tofu_estate || e?.adopt_tofu_address);
|
|
593
|
+
};
|
|
594
|
+
const matched = Array.isArray(doc.adoptable) ? doc.adoptable.filter(claimable).length : 0;
|
|
595
|
+
return { unowned: unowned.length, adoptable: unowned.filter(claimable).length + matched };
|
|
560
596
|
}
|
|
561
597
|
|
|
562
598
|
/**
|
|
@@ -665,8 +701,8 @@ async function ensureChoudoufuVersion(binary: string, signal?: AbortSignal): Pro
|
|
|
665
701
|
if (isOlderVersion(version, MIN_CHOUDOUFU_VERSION)) {
|
|
666
702
|
throw new Error(
|
|
667
703
|
`choudoufu ${version} is older than the minimum supported version v${MIN_CHOUDOUFU_VERSION} ` +
|
|
668
|
-
"(needed for live-plan -json, live-ls, live-check -json,
|
|
669
|
-
"`apply <planfile>` pair). Upgrade choudoufu.",
|
|
704
|
+
"(needed for live-plan -json, live-ls, live-check -json, the approval artifact `plan -out` / " +
|
|
705
|
+
"`apply <planfile>` pair, and the document's adoptable section). Upgrade choudoufu.",
|
|
670
706
|
);
|
|
671
707
|
}
|
|
672
708
|
})();
|
|
@@ -1011,8 +1047,17 @@ export async function choudoufuLivePlan(
|
|
|
1011
1047
|
let drift: boolean;
|
|
1012
1048
|
let jsonStdout: string;
|
|
1013
1049
|
const planCmd = choudoufuLivePlanCommand({ binary, ...estateFlag, json: true });
|
|
1050
|
+
// The document's `adoptable` and `swept` sections are populated only on a
|
|
1051
|
+
// run that asked the estate-wide sweep the account-bounded question, which
|
|
1052
|
+
// `-adoption-only` implies and a `-json` run does not
|
|
1053
|
+
// (`internal/command/live_collect_unclaimed.go`). `-adoption-only` cannot
|
|
1054
|
+
// ride the `-json` invocation, so the env var is how a document-producing
|
|
1055
|
+
// run asks for the same thing. Set only under `adoptionOnly`: the sweep is
|
|
1056
|
+
// an account-wide list per admitted type, and an observation read has no use
|
|
1057
|
+
// for it.
|
|
1058
|
+
const planEnv = args.adoptionOnly ? { ...env, TOFU_LIVE_COLLECT_UNCLAIMED: "1" } : env;
|
|
1014
1059
|
try {
|
|
1015
|
-
const { stdout, stderr } = await run(planCmd, dir,
|
|
1060
|
+
const { stdout, stderr } = await run(planCmd, dir, planEnv, signal);
|
|
1016
1061
|
report(stdout, stderr);
|
|
1017
1062
|
drift = false;
|
|
1018
1063
|
jsonStdout = stdout;
|
|
@@ -1069,9 +1114,12 @@ export async function choudoufuLivePlan(
|
|
|
1069
1114
|
|
|
1070
1115
|
writeFileSync(join(dir, documentPath), document);
|
|
1071
1116
|
|
|
1072
|
-
//
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1117
|
+
// An `adoptable[]` row carries its own tagging command in the document
|
|
1118
|
+
// (choudoufu #962). An `unowned[]` row does not, and the render is the only
|
|
1119
|
+
// place one is printed for it, so the parse still runs on an adoption run
|
|
1120
|
+
// and the map still feeds that half. A candidate off an ordinary run carries
|
|
1121
|
+
// the two marker values and no command, which is the whole ownership
|
|
1122
|
+
// contract either way.
|
|
1075
1123
|
const ledger = readAdoptionLedger(json, args.adoptionOnly ? parseAdoptionCommands(text) : undefined);
|
|
1076
1124
|
const ledgerText = renderAdoptionLedger(ledger, estate);
|
|
1077
1125
|
|
|
@@ -1084,6 +1132,7 @@ export async function choudoufuLivePlan(
|
|
|
1084
1132
|
adoptions: ledger.adoptions,
|
|
1085
1133
|
contested: ledger.contested,
|
|
1086
1134
|
ambiguous: ledger.ambiguous,
|
|
1135
|
+
swept: ledger.swept,
|
|
1087
1136
|
dir,
|
|
1088
1137
|
documentPath,
|
|
1089
1138
|
estate,
|
package/src/op/adoption.test.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The adoption ledger (#2105): reading `live-plan -json`'s `unowned`
|
|
3
|
-
* pairing
|
|
2
|
+
* The adoption ledger (#2105, #2241): reading `live-plan -json`'s `unowned`
|
|
3
|
+
* and `adoptable` sections, pairing the first with the commands
|
|
4
|
+
* `-adoption-only` printed, and rendering both.
|
|
4
5
|
*
|
|
5
6
|
* The document fragments below are the shape choudoufu actually emits, taken
|
|
6
|
-
* from `views.StatelessUnowned`'s json tags
|
|
7
|
-
* and checked against the recorded document
|
|
8
|
-
* an adoptable row carries
|
|
9
|
-
*
|
|
7
|
+
* from `views.StatelessUnowned` and `views.LivePlanAdoptable`'s json tags
|
|
8
|
+
* (`internal/command/live_plan.go`) and checked against the recorded document
|
|
9
|
+
* next door: an adoptable row carries
|
|
10
|
+
* `adopt_tofu_estate`/`adopt_tofu_address`, and a row held by somebody else
|
|
11
|
+
* carries `tofu_estate` and neither of the other two.
|
|
12
|
+
*
|
|
13
|
+
* The last block reads `../__fixtures__/live-plan.json` itself, so the
|
|
14
|
+
* `adoptable` half is proved against a real v0.15.0 document rather than
|
|
15
|
+
* against a literal a test author typed.
|
|
10
16
|
*/
|
|
11
17
|
|
|
18
|
+
import { readFileSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
12
20
|
import { describe, test, expect } from "vitest";
|
|
13
21
|
import { parseAdoptionCommands, readAdoptionLedger, renderAdoptionLedger } from "./adoption";
|
|
14
22
|
|
|
@@ -79,10 +87,110 @@ describe("readAdoptionLedger (#2105)", () => {
|
|
|
79
87
|
expect(ledger.adoptions.find((c) => c.addr === "aws_subnet.app")?.command).toBeUndefined();
|
|
80
88
|
});
|
|
81
89
|
|
|
82
|
-
test("a document with
|
|
83
|
-
|
|
84
|
-
expect(readAdoptionLedger(
|
|
85
|
-
expect(readAdoptionLedger(
|
|
90
|
+
test("a document with neither section, or none at all, is an empty ledger", () => {
|
|
91
|
+
const empty = { adoptions: [], contested: [], ambiguous: 0, swept: [] };
|
|
92
|
+
expect(readAdoptionLedger({ bound: [] })).toEqual(empty);
|
|
93
|
+
expect(readAdoptionLedger(undefined)).toEqual(empty);
|
|
94
|
+
expect(readAdoptionLedger({ unowned: "not a list", adoptable: 7, swept: "aws_vpc" })).toEqual(empty);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("readAdoptionLedger over the adoptable section (choudoufu #962, #2241)", () => {
|
|
99
|
+
const matched = (addr: string, identity: string) => ({
|
|
100
|
+
addr,
|
|
101
|
+
type: "aws_vpc",
|
|
102
|
+
identity,
|
|
103
|
+
matched: [{ attribute: "cidr_block", value: "10.77.0.0/16" }],
|
|
104
|
+
adopt_tofu_estate: "prod-networking",
|
|
105
|
+
adopt_tofu_address: addr,
|
|
106
|
+
adopt_command: `aws ec2 create-tags --resources '${identity}'`,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("a content match is a candidate carrying its own command and what it matched on", () => {
|
|
110
|
+
const ledger = readAdoptionLedger({ unowned: [], adoptable: [matched("aws_vpc.main", "vpc-0abc")] });
|
|
111
|
+
expect(ledger.adoptions).toEqual([
|
|
112
|
+
{
|
|
113
|
+
addr: "aws_vpc.main",
|
|
114
|
+
type: "aws_vpc",
|
|
115
|
+
identity: "vpc-0abc",
|
|
116
|
+
markerEstate: "prod-networking",
|
|
117
|
+
markerAddress: "aws_vpc.main",
|
|
118
|
+
command: "aws ec2 create-tags --resources 'vpc-0abc'",
|
|
119
|
+
matched: [{ attribute: "cidr_block", value: "10.77.0.0/16" }],
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("the document's own command wins: no render is parsed for this half", () => {
|
|
125
|
+
const ledger = readAdoptionLedger(
|
|
126
|
+
{ adoptable: [matched("aws_vpc.main", "vpc-0abc")] },
|
|
127
|
+
new Map([["aws_vpc.main", "a command scraped off the render"]]),
|
|
128
|
+
);
|
|
129
|
+
expect(ledger.adoptions[0].command).toBe("aws ec2 create-tags --resources 'vpc-0abc'");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("both sections feed one ledger, and one address in both is contested", () => {
|
|
133
|
+
const ledger = readAdoptionLedger({
|
|
134
|
+
unowned: [adoptable("aws_cloudwatch_log_group.app", "/estate/app", "aws_cloudwatch_log_group")],
|
|
135
|
+
adoptable: [matched("aws_vpc.main", "vpc-0abc"), matched("aws_cloudwatch_log_group.app", "/estate/app")],
|
|
136
|
+
});
|
|
137
|
+
expect(ledger.adoptions.map((c) => c.addr)).toEqual(["aws_vpc.main"]);
|
|
138
|
+
expect(ledger.contested.map((c) => c.addr)).toEqual([
|
|
139
|
+
"aws_cloudwatch_log_group.app",
|
|
140
|
+
"aws_cloudwatch_log_group.app",
|
|
141
|
+
]);
|
|
142
|
+
expect(ledger.ambiguous).toBe(1);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("swept comes back so an empty ledger can say which empty it is", () => {
|
|
146
|
+
expect(readAdoptionLedger({ swept: ["aws_vpc", 7, "aws_subnet"] }).swept).toEqual(["aws_vpc", "aws_subnet"]);
|
|
147
|
+
expect(readAdoptionLedger({ unowned: [] }).swept).toEqual([]);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe("readAdoptionLedger over the recorded v0.15.0 document (#2241)", () => {
|
|
152
|
+
const document: unknown = JSON.parse(
|
|
153
|
+
readFileSync(join(import.meta.dirname, "..", "__fixtures__", "live-plan.json"), "utf-8"),
|
|
154
|
+
);
|
|
155
|
+
const ledger = readAdoptionLedger(document);
|
|
156
|
+
|
|
157
|
+
test("both halves of the real document reach the ledger", () => {
|
|
158
|
+
// The log group's identity is the name in its own block, so choudoufu read
|
|
159
|
+
// it and put it in `unowned[]`. The VPC's is assigned by EC2, so the sweep
|
|
160
|
+
// content-matched it and put it in `adoptable[]`. One ledger, both rows.
|
|
161
|
+
expect(ledger.adoptions.map((c) => c.addr).sort()).toEqual([
|
|
162
|
+
"aws_cloudwatch_log_group.adoptable",
|
|
163
|
+
"aws_vpc.adoptable",
|
|
164
|
+
]);
|
|
165
|
+
expect(ledger.contested).toEqual([]);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("the content match carries the cidr it rested on and choudoufu's own tagging command", () => {
|
|
169
|
+
const vpc = ledger.adoptions.find((c) => c.addr === "aws_vpc.adoptable")!;
|
|
170
|
+
expect(vpc.type).toBe("aws_vpc");
|
|
171
|
+
expect(vpc.identity).toMatch(/^vpc-/);
|
|
172
|
+
expect(vpc.markerEstate).toBe("stateless-e2e-block");
|
|
173
|
+
expect(vpc.markerAddress).toBe("aws_vpc.adoptable");
|
|
174
|
+
expect(vpc.matched).toEqual([{ attribute: "cidr_block", value: "10.88.0.0/16" }]);
|
|
175
|
+
expect(vpc.command).toContain("aws ec2 create-tags");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("the declared-identity row carries no match and no command of its own", () => {
|
|
179
|
+
// `views.StatelessUnowned` has no command field, which is why
|
|
180
|
+
// `parseAdoptionCommands` still exists for this half alone.
|
|
181
|
+
const log = ledger.adoptions.find((c) => c.addr === "aws_cloudwatch_log_group.adoptable")!;
|
|
182
|
+
expect(log.matched).toBeUndefined();
|
|
183
|
+
expect(log.command).toBeUndefined();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("the sweep's type list rides along, so nothing here is silence", () => {
|
|
187
|
+
expect(ledger.swept).toContain("aws_vpc");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("the rendering names the match under its row", () => {
|
|
191
|
+
const text = renderAdoptionLedger(ledger, "stateless-e2e-block");
|
|
192
|
+
expect(text).toContain("Adoptable now: 2 live resources");
|
|
193
|
+
expect(text).toContain(" matched on: cidr_block=10.88.0.0/16");
|
|
86
194
|
});
|
|
87
195
|
});
|
|
88
196
|
|
|
@@ -139,6 +247,16 @@ describe("renderAdoptionLedger (#2105)", () => {
|
|
|
139
247
|
expect(text).toContain("Adoptable now: nothing");
|
|
140
248
|
});
|
|
141
249
|
|
|
250
|
+
test("an empty ledger off a run that swept nothing says it did not look", () => {
|
|
251
|
+
// The difference choudoufu's own view draws, and the reason `swept` is
|
|
252
|
+
// carried at all: no sweep means no answer, which is not the same answer
|
|
253
|
+
// as "nothing to adopt".
|
|
254
|
+
expect(renderAdoptionLedger(readAdoptionLedger({ unowned: [] }))).toContain("No estate-wide sweep ran");
|
|
255
|
+
expect(renderAdoptionLedger(readAdoptionLedger({ unowned: [], swept: ["aws_vpc"] }))).toContain(
|
|
256
|
+
"across 1 swept resource type (aws_vpc)",
|
|
257
|
+
);
|
|
258
|
+
});
|
|
259
|
+
|
|
142
260
|
test("contested addresses are listed under their own heading with no marker values offered", () => {
|
|
143
261
|
const text = renderAdoptionLedger(
|
|
144
262
|
readAdoptionLedger({ unowned: [adoptable("aws_vpc.main", "vpc-0abc"), adoptable("aws_vpc.main", "vpc-0def")] }),
|
|
@@ -152,7 +270,7 @@ describe("renderAdoptionLedger (#2105)", () => {
|
|
|
152
270
|
expect(contestedBlock).not.toContain("write: tofu-estate=");
|
|
153
271
|
});
|
|
154
272
|
|
|
155
|
-
test("nothing outside the
|
|
273
|
+
test("nothing outside the two adoption sections reaches the rendering", () => {
|
|
156
274
|
// The document carries every declared instance the plan bound and every
|
|
157
275
|
// one it could not read, with identities and reasons. The ledger is a
|
|
158
276
|
// projection of `unowned` alone, and this is what says so.
|