Skip to content

aws: the provider-default prune entries the claimed-field set now covers #2185

Description

@lex00

#2172 (issue #2160) added the claimed-field set: packages/core/src/claimed-fields.ts derives, from a declaration's own props, every path it ever set. A live value on a path outside that set now reports correctly instead of being read as drift. (#2181 is renaming that #2172 bucket from "held elsewhere" to "unclaimed": DeepDiffResult.unclaimed, heading UNCLAIMED. Using "unclaimed" throughout this issue.)

#2172's PR body names the counterpart-gated provider-default entries in the aws deep-observe hook as the largest shrink candidate for this lexicon, and says pruning and unclaimed report differently: pruned means the field never reaches the tree, unclaimed means it is reported with its live value under the UNCLAIMED heading. This issue is the per-lexicon follow-up its acceptance line asked for; nothing here has been shrunk yet.

What is in the file

awsDeepNormalizationHooks.prune (lexicons/aws/src/deep-observe.ts:379-419) checks, in order:

  • AWS_READ_ONLY_NAMES (deep-observe.ts:239-257): Arn, RoleId, PolicyId, GroupId, OwnerId, AttachmentCount, PermissionsBoundaryUsageCount, DefaultVersionId, IsAttachable, CreateDate, CreationDate, UpdateDate, LastModified, LastModifiedTime, DualStackDomainName, RegionalDomainName, WebsiteURL. Pruned on both sides unconditionally (checked at line 386).
  • schemaReadOnlyPatterns() (deep-observe.ts:334-344): generated at runtime from the CloudFormation schema's own readOnlyProperties, not hand-maintained. Also unconditional, both sides (line 385).
  • AWS_DEEP_BLIND_SPOTS (lexicons/aws/src/deep-topology.ts:223-237, applied at deep-observe.ts:392-398): AWS::EC2::VPC (4 names), AWS::EC2::Subnet (5 names). Declared-side only, and only when the live side cannot see the property at all.
  • isOwnershipTag() (defined deep-observe.ts:530-533, checked at line 410): chant's own ownership tag, counterpart-gated live+absent.
  • AWS_GENERATED_NAMES (deep-observe.ts:300-303, merged with EC2_TOPOLOGY_GENERATED_NAMES from deep-topology.ts:207-210): AWS::EC2::SecurityGroup.GroupName, AWS::EC2::Subnet (AvailabilityZone, AvailabilityZoneId), AWS::EC2::Instance.AvailabilityZone. 4 entries across 3 kinds, counterpart-gated live+absent (checked at line 413).
  • AWS_SERVICE_DEFAULTS (deep-observe.ts:266-289, merged with EC2_TOPOLOGY_SERVICE_DEFAULTS from deep-topology.ts:180-199): AWS::S3::Bucket (VersioningConfiguration.Status, AccelerateConfiguration.AccelerationStatus, ObjectLockEnabled, 3), AWS::IAM::Role (Path, MaxSessionDuration, 2), AWS::IAM::ManagedPolicy (Path, 1), AWS::EC2::SecurityGroup (GroupDescription, SecurityGroupEgress[].CidrIp, SecurityGroupEgress[].IpProtocol, 3), AWS::EC2::VPC (InstanceTenancy, IsDefault, 2), AWS::EC2::Subnet (MapPublicIpOnLaunch, AssignIpv6AddressOnCreation, EnableDns64, Ipv6Native, DefaultForAz, 5), AWS::EC2::Instance (Tenancy, Monitoring, EbsOptimized, SourceDestCheck, DisableApiTermination, 5). 21 entries across 7 kinds, gated the same way (checked at line 403).

Grepped every exported name across the lexicon and packages/core. AWS_READ_ONLY_NAMES and AWS_SERVICE_DEFAULTS are re-exported as public API from lexicons/aws/src/index.ts:61-62, but nothing internal or in examples/ imports them a second time. The aws lexicon has no export-resources.ts, so there is no import/export consumer to protect the way azure and fountain have.

Candidates versus must-stay

Candidates: AWS_SERVICE_DEFAULTS/EC2_TOPOLOGY_SERVICE_DEFAULTS (21 entries) and AWS_GENERATED_NAMES/EC2_TOPOLOGY_GENERATED_NAMES (4 entries). Both only fire when the declaration never set the property, the shape claimedFieldsOfProps now answers directly.

One caveat specific to this lexicon: deep-topology.ts:172-179's own comment ties EC2_TOPOLOGY_SERVICE_DEFAULTS's gating to keeping the topology fold facts (IsDefault, DefaultForAz, a live MapPublicIpOnLaunch) visible in the deep snapshot without them reading as drift on a provider-created resource. lexicons/aws/src/defaults.ts:44-46 reads IsDefault/DefaultForAz for the provider-default classification (providerDefault: true), but from a separate ambient property read, not from this deep-observe tree, so removing these two entries from the prune table looks safe for that consumer on inspection. This is not fully confirmed by reading the code alone; treat it as a required check rather than an assumption. A live value equal to the default (for example a non-default VPC's IsDefault: false) would newly report as UNCLAIMED on every clean read once the entry is gone, which is the exact tradeoff the rest of this table already makes.

Must stay:

Verification before merging

Run chant lifecycle diff --live against a real AWS account covering an AWS::S3::Bucket, an AWS::IAM::Role, an AWS::IAM::ManagedPolicy, an AWS::EC2::SecurityGroup, a AWS::EC2::VPC, an AWS::EC2::Subnet and an AWS::EC2::Instance, each declared with the relevant property left unset, before and after removing an entry. For the topology entries, additionally confirm the default-VPC and default-for-az classification in lexicons/aws/src/defaults.ts still resolves correctly on a real default VPC and a real non-default one.

Ref #2160, #2172, #2181.

Acceptance

  • Each AWS_SERVICE_DEFAULTS/EC2_TOPOLOGY_SERVICE_DEFAULTS and AWS_GENERATED_NAMES/EC2_TOPOLOGY_GENERATED_NAMES entry removed has a test in lexicons/aws/src/deep-observe.test.ts or deep-topology.test.ts asserting the field reports unclaimed with its live value.
  • The default-VPC and default-for-az topology classification in lexicons/aws/src/defaults.ts still passes its existing tests after any topology entry moves, or gains a new test if none covered it.
  • No entry moves without a matching real-estate run named in the PR (account, resource kinds, fields checked).
  • No KNOWN_FAILURES entry added for any lexicon.
  • lexicons/aws/src/deep-observe.test.ts and lexicons/aws/src/deep-topology.test.ts pass in full.
  • AWS_READ_ONLY_NAMES, schemaReadOnlyPatterns(), AWS_DEEP_BLIND_SPOTS and isOwnershipTag() are untouched, or the PR explains why one of them turned out to be coverable after all.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions