You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(provisioning): clear an SQS Queue attribute that resolves away on UPDATE (Fn::If -> AWS::NoValue) instead of leaving the stale value
The new conditions-update-2 integ fixture surfaced a real cdkd UPDATE-path
bug: when an SQS Queue property whose value is Fn::If(cond, <value>,
AWS::NoValue) flips from <value> (phase a, condition true) to AWS::NoValue
(phase b, condition false), the resolved desired properties OMIT the
property entirely. cdkd's diff layer correctly classifies that as a change
(compareProperties unions current + desired keys, so a key present in state
but absent from the resolved template is detected), but SQSQueueProvider.update()
only acted on keys PRESENT in the new properties -- so the stale value (e.g.
RedrivePolicy) was never cleared on AWS. The fixture's phase-b assertion
(WorkQueue RedrivePolicy GONE) failed.
This is the "providers only act on keys present in newProperties" gap
(feedback_internal_contract_audit_first). The fix adds a removal branch to
SQSQueueProvider.update(): a CDK-managed attribute present in
previousProperties but absent from the resolved desired properties is reset
to its default via SetQueueAttributes, mirroring CloudFormation's
reset-to-default-on-removal behavior. The new SQS_ATTRIBUTE_REMOVAL_RESET map
clears the JSON policy attributes (RedrivePolicy / RedriveAllowPolicy) and
KmsMasterKeyId to the empty string SQS documents for removal, and resets the
numeric attributes to their documented SetQueueAttributes defaults.
The branch is gated on the attribute being present in previousProperties AND
in the reset map, so it never spuriously clears an attribute that was never
set (a tag-only update issues no SetQueueAttributes), and immutable /
FIFO-discriminated attributes (FifoQueue / DeduplicationScope /
FifoThroughputLimit) are deliberately excluded. The change is confined to the
SQS provider -- no shared / cross-provider code path changed, so other
providers' update semantics are untouched.
Unit tests (tests/unit/provisioning/sqs-queue-provider-update.test.ts):
clear-on-removal (RedrivePolicy -> ""), numeric-reset-on-removal
(VisibilityTimeout -> 30), and the no-over-clear guard (attribute absent on
both sides -> no SetQueueAttributes).
Also adds the conditions-update-2 integ fixture that stresses the harder
CloudFormation-Conditions-on-UPDATE semantics the simple #840 flip does not
cover (moved-condition resources, condition-gated outputs, dangling DependsOn
on a pruned resource, Ref into a pruned resource, and the Fn::If ->
AWS::NoValue property-removal case above).
NOTE: needs /run-integ conditions-update-2 against real AWS before merge.
Copy file name to clipboardExpand all lines: docs/_generated/scenario-coverage.json
+18Lines changed: 18 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -20,6 +20,10 @@
20
20
"tag": "conditions-and-if",
21
21
"description": "CloudFormation Conditions section + resource-level `Condition:` key + `Fn::If` / `Fn::Equals` / `Fn::And` / `Fn::Or` / `Fn::Not` evaluated by cdkd itself. Two deploys flip a CDK-context-driven CfnParameter Default so the SAME stack is asserted in both settings: condition-gated resource creation (PRESENT vs ABSENT on AWS), `Fn::If` property + tag branch values reaching AWS, and `Fn::If` -> `AWS::NoValue` genuinely OMITTING a property."
22
22
},
23
+
{
24
+
"tag": "conditions-update-semantics",
25
+
"description": "Harder CloudFormation-Conditions-on-UPDATE semantics beyond the simple flip in `conditions-and-if` (which surfaced #840). A CDK-context phase flip (-c phase=a|b) redeploys the SAME stack in place and asserts: a resource that MOVES gating conditions (IsPhaseA-gated -> condition-false -> DELETED) and its reverse (IsPhaseB-gated absent -> CREATED); `Fn::If` -> `AWS::NoValue` REMOVING a nested property block (SQS RedrivePolicy) on an in-place UPDATE (same physical id, not a replacement); a condition-gated OUTPUT present vs absent in cdkd state outputs; a `DependsOn` to a condition-EXCLUDED resource being dropped (the depender still deploys); and a `Ref` to a condition-excluded resource living inside another condition-excluded resource (both pruned together, no dangling-ref crash)."
26
+
},
23
27
{
24
28
"tag": "cross-cutting-deploy-destroy",
25
29
"description": "Broad real-AWS regression set (39+ resource VPC+NAT+CF+Lambda+SQS or comparable breadth). Refreshes the integ-broad gate."
@@ -338,6 +342,13 @@
338
342
"conditions-and-if"
339
343
]
340
344
},
345
+
{
346
+
"name": "conditions-update-2",
347
+
"annotated": true,
348
+
"scenarios": [
349
+
"conditions-update-semantics"
350
+
]
351
+
},
341
352
{
342
353
"name": "context-test",
343
354
"annotated": true,
@@ -1100,6 +1111,13 @@
1100
1111
"conditions-and-if"
1101
1112
]
1102
1113
},
1114
+
{
1115
+
"scenario": "conditions-update-semantics",
1116
+
"description": "Harder CloudFormation-Conditions-on-UPDATE semantics beyond the simple flip in `conditions-and-if` (which surfaced #840). A CDK-context phase flip (-c phase=a|b) redeploys the SAME stack in place and asserts: a resource that MOVES gating conditions (IsPhaseA-gated -> condition-false -> DELETED) and its reverse (IsPhaseB-gated absent -> CREATED); `Fn::If` -> `AWS::NoValue` REMOVING a nested property block (SQS RedrivePolicy) on an in-place UPDATE (same physical id, not a replacement); a condition-gated OUTPUT present vs absent in cdkd state outputs; a `DependsOn` to a condition-EXCLUDED resource being dropped (the depender still deploys); and a `Ref` to a condition-excluded resource living inside another condition-excluded resource (both pruned together, no dangling-ref crash).",
1117
+
"fixtures": [
1118
+
"conditions-update-2"
1119
+
]
1120
+
},
1103
1121
{
1104
1122
"scenario": "cross-cutting-deploy-destroy",
1105
1123
"description": "Broad real-AWS regression set (39+ resource VPC+NAT+CF+Lambda+SQS or comparable breadth). Refreshes the integ-broad gate.",
Copy file name to clipboardExpand all lines: docs/scenario-coverage.md
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
5
5
Run `vp run scenario-coverage` to regenerate.
6
6
7
-
**52 / 52 canonical scenarios** have at least one integ fixture exercising them. **119 / 138 integ fixtures** carry a `.scenarios.json` sidecar (with 0+ tags); the rest are un-annotated and contributor-reviewed below.
7
+
**53 / 53 canonical scenarios** have at least one integ fixture exercising them. **120 / 139 integ fixtures** carry a `.scenarios.json` sidecar (with 0+ tags); the rest are un-annotated and contributor-reviewed below.
8
8
9
9
## How this is computed
10
10
@@ -26,7 +26,7 @@ This report is a visibility tool, not a commit-time gate. Many cdkd fixtures leg
26
26
27
27
_None._ Every canonical scenario has at least one integ fixture tagged with it.
28
28
29
-
## Per-scenario coverage (52 scenarios)
29
+
## Per-scenario coverage (53 scenarios)
30
30
31
31
| Scenario | Description | Integ Fixture(s) |
32
32
|---|---|---|
@@ -35,6 +35,7 @@ _None._ Every canonical scenario has at least one integ fixture tagged with it.
35
35
|`cfn-macro-expansion`| CloudFormation macro / `Fn::Transform` expansion via transient CFn changeset round-trip (SAM, AWS::Include, AWS::LanguageExtensions, custom macros). See `docs/design/463-cfn-macros.md`. |[`macro-expansion`](../tests/integration/macro-expansion/)|
36
36
|`cloudfront-oai-attribute-enrichment`| CloudFront OAI `S3CanonicalUserId` attribute enrichment (the attribute is not on `GetCloudFrontOriginAccessIdentity` directly). |[`s3-cloudfront`](../tests/integration/s3-cloudfront/)|
37
37
|`conditions-and-if`| CloudFormation Conditions section + resource-level `Condition:` key + `Fn::If` / `Fn::Equals` / `Fn::And` / `Fn::Or` / `Fn::Not` evaluated by cdkd itself. Two deploys flip a CDK-context-driven CfnParameter Default so the SAME stack is asserted in both settings: condition-gated resource creation (PRESENT vs ABSENT on AWS), `Fn::If` property + tag branch values reaching AWS, and `Fn::If` -> `AWS::NoValue` genuinely OMITTING a property. |[`conditions-and-if`](../tests/integration/conditions-and-if/)|
38
+
|`conditions-update-semantics`| Harder CloudFormation-Conditions-on-UPDATE semantics beyond the simple flip in `conditions-and-if` (which surfaced #840). A CDK-context phase flip (-c phase=a|b) redeploys the SAME stack in place and asserts: a resource that MOVES gating conditions (IsPhaseA-gated -> condition-false -> DELETED) and its reverse (IsPhaseB-gated absent -> CREATED); `Fn::If` -> `AWS::NoValue` REMOVING a nested property block (SQS RedrivePolicy) on an in-place UPDATE (same physical id, not a replacement); a condition-gated OUTPUT present vs absent in cdkd state outputs; a `DependsOn` to a condition-EXCLUDED resource being dropped (the depender still deploys); and a `Ref` to a condition-excluded resource living inside another condition-excluded resource (both pruned together, no dangling-ref crash). |[`conditions-update-2`](../tests/integration/conditions-update-2/)|
38
39
|`cross-cutting-deploy-destroy`| Broad real-AWS regression set (39+ resource VPC+NAT+CF+Lambda+SQS or comparable breadth). Refreshes the integ-broad gate. |[`bench-ccapi`](../tests/integration/bench-ccapi/)<br>[`bench-cdk-sample`](../tests/integration/bench-cdk-sample/)<br>[`bench-sdk`](../tests/integration/bench-sdk/)<br>[`full-stack-demo`](../tests/integration/full-stack-demo/)<br>[`lambda`](../tests/integration/lambda/)<br>[`microservices`](../tests/integration/microservices/)<br>[`multi-resource`](../tests/integration/multi-resource/)|
39
40
|`custom-resource-async-poll`| Custom Resource backed by Lambda + cfn-response via S3 pre-signed URL polling. |[`cloudfront-function-url`](../tests/integration/cloudfront-function-url/)<br>[`custom-resource-provider`](../tests/integration/custom-resource-provider/)<br>[`destroy-interrupt`](../tests/integration/destroy-interrupt/)<br>[`vpc-lambda-cr-race`](../tests/integration/vpc-lambda-cr-race/)|
40
41
|`deletion-policy-retain`| DeletionPolicy: Retain skip on destroy (schema v5 recorded value wins over template). |[`deletion-policy-retain`](../tests/integration/deletion-policy-retain/)|
'CloudFormation Conditions section + resource-level `Condition:` key + `Fn::If` / `Fn::Equals` / `Fn::And` / `Fn::Or` / `Fn::Not` evaluated by cdkd itself. Two deploys flip a CDK-context-driven CfnParameter Default so the SAME stack is asserted in both settings: condition-gated resource creation (PRESENT vs ABSENT on AWS), `Fn::If` property + tag branch values reaching AWS, and `Fn::If` -> `AWS::NoValue` genuinely OMITTING a property.',
140
+
'conditions-update-semantics':
141
+
'Harder CloudFormation-Conditions-on-UPDATE semantics beyond the simple flip in `conditions-and-if` (which surfaced #840). A CDK-context phase flip (-c phase=a|b) redeploys the SAME stack in place and asserts: a resource that MOVES gating conditions (IsPhaseA-gated -> condition-false -> DELETED) and its reverse (IsPhaseB-gated absent -> CREATED); `Fn::If` -> `AWS::NoValue` REMOVING a nested property block (SQS RedrivePolicy) on an in-place UPDATE (same physical id, not a replacement); a condition-gated OUTPUT present vs absent in cdkd state outputs; a `DependsOn` to a condition-EXCLUDED resource being dropped (the depender still deploys); and a `Ref` to a condition-excluded resource living inside another condition-excluded resource (both pruned together, no dangling-ref crash).',
0 commit comments