Skip to content

feat(aws): storage.backup — aws-backup port (plan/vault/selection) - #154

Open
so0k wants to merge 2 commits into
convert-aws-redshiftfrom
convert-aws-backup
Open

feat(aws): storage.backup — aws-backup port (plan/vault/selection)#154
so0k wants to merge 2 commits into
convert-aws-redshiftfrom
convert-aws-backup

Conversation

@so0k

@so0k so0k commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Storage slice PR 11 — storage.backup: the aws-backup port (v2.263.0)

Stacked on #153. The database-backup-management slice: BackupPlan (+ all four static retention factories), BackupPlanRule, BackupResource, BackupSelection, BackupVault, backupable-resources-collector — 59 unit tests across the three upstream suites. Stable aws-cdk-lib module (not alpha), so no churn tracker.

Mapping notes

  • The 4th block-typed-Lazy footgun instance: aws_backup_plan.rule is block-typed and addRule() accumulates rules after construction. The port feeds rule a Lazy.anyValue that maps the accumulator through the provider's own backupPlanRuleToTerraform renderer at synth (the table.ts GSI idiom), so nested tokens resolve. A dedicated regression test proves a rule added post-construction (with a Lazy-wrapped deleteAfter) lands in the synthesized JSON — and the live integ proves it against AWS.
  • Vault split-offs: provider 6.x moved accessPolicy → standalone aws_backup_vault_policy, notifications → aws_backup_vault_notifications, lockConfigurationaws_backup_vault_lock_configuration. All three documented deviations; blockRecoveryPointDeletion() statement fidelity preserved. encryptionKeykms_key_arn (id-vs-ARN audit pre-applied). removalPolicy → Terraform-native forceDestroy.
  • Collector adapted from CFN resource types to TerraformResource types via Aspects (cdktn Aspects.add() has no priority arg — documented); every upstream type is mapped or TODO-omitted with a permalink, none silently dropped. EFS (fromEfsFileSystem + collector match) TODO-omitted — EFS is not ported yet.
  • events.Schedule → this repo's notify.Schedule; upstream's full validation set (cold-storage/retention/continuousBackup constraints) verbatim; Durations → provider day/minute numbers per upstream conversion rules.
  • fromRdsDatabaseCluster/fromRdsServerlessCluster use clusterArn directly (renders byte-identical to upstream's hand-built formatArn — documented).

Live integ (make backup.plan) — receipts in thread

Real BackupVault + BackupPlan + BackupSelection over a DynamoDB table: GetBackupPlan reads back both rules — Daily (35d, constructor path) and Weekly (90d, added via addRule() after construction — the Lazy rule-block design live-proven), per-rule retention asserted; selection carries the table ARN + stage=prod tag condition + IAM role; drift oracle; clean destroy.

so0k added 2 commits August 7, 2026 09:40
Full file-for-file port of aws-cdk-lib/aws-backup into the storage.backup
sub-namespace: BackupPlan (+ static retention factories), BackupPlanRule,
BackupResource, BackupSelection, BackupVault, backupable-resources-collector.

- plan.ts: rule blocks fed via Lazy.anyValue mapping the addRule() accumulator
  through backupPlanRuleToTerraform at synth (4th block-typed-Lazy footgun
  instance — table.ts GSI idiom; regression test proves post-construction
  addRule() lands in synthesized JSON), omitEmptyArray per house idiom
- vault.ts: accessPolicy/notifications/lockConfiguration split onto standalone
  aws_backup_vault_policy / _notifications / _lock_configuration resources
  (provider 6.x shape — documented deviations); encryptionKey → kms_key_arn
- rule.ts: events.Schedule → notify.Schedule; upstream validation set verbatim
- resource.ts: fromDynamoDbTable/fromRdsDatabaseInstance/fromRdsDatabaseCluster/
  fromRdsServerlessCluster/fromEc2Instance/fromTag/fromArn/fromConstruct;
  fromEfsFileSystem TODO-omitted (EFS not ported)
- collector adapted from Cfn resource types to TerraformResource types via
  Aspects; unported types TODO-omitted, none silently dropped
- 59 unit tests across plan/vault/selection suites
…oDB table

Real BackupVault (force_destroy) + BackupPlan with the daily static-factory
rule AND a weekly rule added after construction (live proof of the
Lazy.anyValue rule-block design) + BackupSelection over the table ARN and a
stage=prod tag condition. Read-backs: GetBackupPlan rules with per-rule
retention (Daily 35d / Weekly 90d), DescribeBackupVault, GetBackupSelection
resources/tags/role, post-apply drift oracle.

Adds aws-sdk-go-v2/service/backup v1.60.0.
@so0k

so0k commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Live integ receipts — make backup.plan (aws-vault → tcons-vincent, us-east-1) — first-attempt PASS, 46.95s (fastest live test of the slice)

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
backup-plan: c242ac33-f13a-4b27-8335-ab84e13f2de6 has rules Daily(35d)+Weekly(90d) targeting vault backupplanVaultFDE1BD54
backup-plan: vault backupplanVaultFDE1BD54 exists (arn:aws:backup:us-east-1:694710432912:backup-vault:backupplanVaultFDE1BD54)
backup-plan: selection bcb2090a-310a-499e-9095-e37793f8e4e7 covers table arn:aws:dynamodb:us-east-1:694710432912:table/backupplanTable5A02F3C3 + tag stage=prod via role arn:aws:iam::694710432912:role/gdddddddd-dddd-backanPlanSelectionRole061f11fdf36ecc9faf6200d31e
No changes. Your infrastructure matches the configuration.   <-- post-apply drift oracle (tofu plan -detailed-exitcode == 0)
Destroy complete! Resources: 6 destroyed.
--- PASS: TestBackupPlan (46.95s)

Highlights:

  • The Weekly(90d) rule was added via addRule() AFTER construction and read back from GetBackupPlan — live proof of the Lazy.anyValue rule-block design (block-typed L1 args never resolve Lazy tokens; this is the 4th instance of that footgun in the repo and the first one proven live).
  • Per-rule retention asserted exactly (Daily 35d / Weekly 90d), both targeting the fixture vault.
  • Selection carries the DynamoDB table ARN (fromDynamoDbTable), the stage=prod tag condition (fromTag), and the grid-scoped IAM role.
  • Zero-drift re-plan; clean destroy (vault force_destroy — the Terraform-native removalPolicy replacement).
  • Third consecutive first-attempt pass of the slice.

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