Skip to content

feat: assumed_count caveat for counts that rest on a data source placeholder - #105

Merged
andreacappelletti97 merged 1 commit into
mainfrom
feat/assumed-count-caveat
Sep 29, 2026
Merged

andreacappelletti97 merged 1 commit into
mainfrom
feat/assumed-count-caveat

Conversation

@andreacappelletti97

Copy link
Copy Markdown
Contributor

What

A new caveat code, assumed_count. When a resource's count / for_each, or that of the module it sits in, is computed from a data source c3x gives a placeholder (data.aws_availability_zones is three zones in the provider's region, aws_region, aws_caller_identity, google_client_config), every priced instance now says so:

  aws_nat_gateway.main[0]
    ⚠ instance count assumes data.aws_availability_zones.available.names = [us-east-1a, us-east-1b, us-east-1c]; price a plan JSON for exact counts

How

  • Parser: expandInstances already stripped placeholder marks from count/for_each; it now renders them (describePlaceholders) into instance.assumed. moduleEnv.assumedCount carries a module instance's assumption down, so every resource under a placeholder-counted module inherits it (joined with the resource's own, deduplicated). The result lands in the new domain.Resource.AssumedCount.
  • Calculator: assumedCountCaveat turns it into a resource-level caveat, only when the resource's subtotal is non-zero: a free subnet's count can't move the total.
  • Output: no renderer changes needed; resource caveats already render in text, markdown, the PR comment, JSON (code: assumed_count), count toward caveat_count, and fail --strict (exit 3). The --strict help text mentions the new case.
  • Logging: the stderr WARN for a resource or module count/for_each is now DEBUG. The caveat says the same thing next to the number, in every format; the warning just printed four raw slog lines above the report (one per resource, free ones included). A dynamic block's for_each over a placeholder has no caveat, so it still warns.
  • README caveat table and CHANGELOG [Unreleased] updated.

Tests

  • Parser: count and for_each over the zones record AssumedCount on every instance; a literal count and no count record nothing; module count over the zones propagates to the module's resources, a literal module count doesn't. Existing placeholder tests now assert on AssumedCount instead of the log.
  • Calculator: caveat with the exact detail on a priced resource; none on a free one; none without an assumption.
  • CLI (flat-price test server): JSON carries assumed_count on the per-AZ instances only (not the literal-count instances, not the free VPCs), text and markdown show it for the three priced instances, --strict returns the caveat error and lists assumed_count.
  • Golden files unchanged: they run --offline, where every price is $0, so no resource gets the caveat.

Demo (c3x-demo/aws, live pricing)

$ c3x estimate --path . --format json | jq '.caveat_count'
6        # aws_eip.nat[0..2], aws_nat_gateway.main[0..2]; the free subnets get none
$ c3x estimate --path . --strict; echo $?
c3x: --strict: the estimate has 6 caveat(s):
  assumed_count          6
3

…eholder

A resource whose count or for_each (its own, or its module's) is computed
from a data source placeholder, such as one NAT gateway per
data.aws_availability_zones zone, now carries an assumed_count caveat on
each priced instance naming the value assumed. The parser records it as
domain.Resource.AssumedCount; the calculator reports it only on resources
with a non-zero cost. It renders in every format, counts toward
caveat_count and fails --strict.

The stderr warning for a resource or module count / for_each is now a
debug line, since the caveat says the same thing next to the number. A
dynamic block's for_each, which has no caveat, still warns.
@andreacappelletti97
andreacappelletti97 merged commit b63f1dc into main Sep 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant