Skip to content

feat: add existing VPC import support + fix Route53 hosted zone lookup#138

Open
jmino wants to merge 10 commits intoBoise-State-Development:mainfrom
UniversityOfSaintThomas:feature/existing-vpc-support
Open

feat: add existing VPC import support + fix Route53 hosted zone lookup#138
jmino wants to merge 10 commits intoBoise-State-Development:mainfrom
UniversityOfSaintThomas:feature/existing-vpc-support

Conversation

@jmino
Copy link
Copy Markdown

@jmino jmino commented Apr 10, 2026

Summary

Add optional existing VPC import support for InfrastructureStack. Organizations with hub-and-spoke network topologies or shared VPCs can now deploy into a pre-existing VPC instead of always creating a new one.

What changed

  • Config: Added ExistingVpcConfig interface, parseExistingVpcConfig(), and validateExistingVpcConfig() in config.ts
  • Stack: Changed this.vpc from ec2.Vpc to ec2.IVpc, added fromVpcAttributes() branch in infrastructure-stack.ts
  • SSM exports: Adjusted to use config values directly for imported VPCs
  • CI/CD: Added CDK_EXISTING_VPC_* env vars to load-env.sh, synth.sh, deploy.sh, and infrastructure.yml
  • Tests: 8 property-based tests (fast-check) covering config round-trip, validation, precedence, and stack synthesis
  • Docs: Updated ACTIONS-REFERENCE.md and deploy guide with new variables

How it works

When CDK_EXISTING_VPC_ID is set (via env var or CDK context), the stack imports the VPC via Vpc.fromVpcAttributes() and skips VPC/Subnet/NAT creation. When absent, behavior is identical to today. Downstream stacks require zero changes — they consume network resources via SSM parameters regardless of VPC origin.

Testing

  • 311 tests passing (14 suites)
  • 8 new property-based tests with 50-100 iterations each
  • Covers: config round-trip, env var precedence, field validation, subnet/AZ count matching, VPC CIDR bypass, stack synthesis, SSM parameter completeness
  • Verified with a full stack deployment against an existing VPC in an AWS Account

Additional fix

  • Frontend stack: Fixed Route53 hosted zone lookup to extract parent zone from subdomain (e.g., app.example.comexample.com). Previously failed when domainName was not the zone apex.

Julian Mino and others added 5 commits April 9, 2026 22:51
Fix to extract the parent domain for the zone lookup.

Signed-off-by: Julian Mino <5713710+jmino@users.noreply.github.com>
Allow importing a pre-existing VPC via Vpc.fromVpcAttributes() instead
of always creating a new one. When the optional existingVpc config block
is present, the stack skips VPC/Subnet/NAT creation and uses the
provided VPC ID, subnet IDs, and availability zones. Downstream stacks
require zero changes since they consume network resources via SSM.
@jmino jmino requested a review from a team April 10, 2026 17:03
@philmerrell
Copy link
Copy Markdown
Contributor

Hi @jmino!

Wow, thank you for this PR. This is fantastic. We will take a look on Monday and most likely merge early next week. Have a great weekend! :)

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optional “import existing VPC” support to the CDK InfrastructureStack so deployments can target a pre-provisioned VPC (hub-and-spoke/shared VPC topologies), and updates Route53 hosted zone lookup behavior for subdomain-based domainName values.

Changes:

  • Introduces ExistingVpcConfig parsing + validation in infrastructure/lib/config.ts and switches InfrastructureStack VPC handling to ec2.IVpc with an import branch.
  • Updates CI/CD + shell scripts to accept/pass new CDK_EXISTING_VPC_* inputs; adds fast-check property-based tests for config + stack synthesis behavior.
  • Adjusts frontend Route53 hosted zone lookup logic to derive a parent zone from subdomains.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/stack-infrastructure/synth.sh Adds passing existing VPC context to synth command.
scripts/stack-infrastructure/deploy.sh Adds passing existing VPC context to deploy command.
scripts/common/load-env.sh Exports/parses CDK_EXISTING_VPC_* and adds them to built context params.
infrastructure/test/infrastructure-stack-property.test.ts Property tests for imported-VPC synth resource counts + SSM parameters.
infrastructure/test/helpers/mock-config.ts Adds existingVpc default to mock config.
infrastructure/test/existing-vpc-config.property.test.ts Property tests for config precedence/validation/round-trip.
infrastructure/package.json Adds fast-check dev dependency.
infrastructure/package-lock.json Locks fast-check dependency.
infrastructure/lib/infrastructure-stack.ts Imports VPC via fromVpcAttributes when configured; adjusts SSM exports.
infrastructure/lib/frontend-stack.ts Changes hosted zone lookup to use derived parent zone name.
infrastructure/lib/config.ts Adds ExistingVpcConfig, parsing, validation, and CIDR-validation bypass logic.
infrastructure/cdk.context.json Updates cached availability-zone lookup data.
.kiro/specs/existing-vpc-support/tasks.md Implementation plan documentation for the feature.
.kiro/specs/existing-vpc-support/requirements.md Requirements documentation for existing VPC support.
.kiro/specs/existing-vpc-support/design.md Design documentation for existing VPC support.
.kiro/specs/existing-vpc-support/.config.kiro Kiro spec metadata for the new feature.
.github/workflows/infrastructure.yml Adds CDK_EXISTING_VPC_* vars to workflow env.
.github/docs/deploy/step-03-github-config.md Documents new CDK_EXISTING_VPC_* variables.
.github/ACTIONS-REFERENCE.md Documents new CDK_EXISTING_VPC_* variables.
Files not reviewed (1)
  • infrastructure/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

infrastructure/package-lock.json:26

  • package.json pins fast-check to 4.6.0, but package-lock.json records it as ^4.6.0 under packages[""]. This mismatch can cause npm ci to fail due to an out-of-sync lockfile. Regenerate the lockfile (or align the spec) so the lock reflects the exact version constraint from package.json.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/stack-infrastructure/synth.sh
Comment thread scripts/stack-infrastructure/deploy.sh
Comment thread scripts/common/load-env.sh
Comment thread infrastructure/lib/frontend-stack.ts
Comment thread infrastructure/lib/infrastructure-stack.ts
Julian Mino added 5 commits April 15, 2026 14:17
…zone lookup

Use config.infrastructureHostedZoneDomain (CDK_HOSTED_ZONE_DOMAIN) for
the Route53 fromLookup() call instead of deriving the zone name from
config.domainName. Falls back to domainName when the hosted zone config
is not set, preserving existing behavior for apex domain deployments.
The frontend workflow was missing CDK_HOSTED_ZONE_DOMAIN in its env
sections, causing Route53 hosted zone lookups to fail when domainName
differs from the hosted zone domain (e.g., app.example.com vs example.com).

- Add CDK_HOSTED_ZONE_DOMAIN to synth-cdk and deploy-infrastructure jobs
CDK_HOSTED_ZONE_DOMAIN is a required variable per documentation, so
the fallback to domainName is unnecessary.
FrontendStack requires this variable for Route53 hosted zone lookup
when synthesizing all stacks.
@jmino jmino force-pushed the feature/existing-vpc-support branch from 1b8f1f4 to a35d0e7 Compare April 16, 2026 00:54
@DerrickF
Copy link
Copy Markdown
Contributor

Testing: Existing VPC Import

Notes:

I ran a manual integration test for the changes in this pull request, here are the results.

Environment

  • Fresh AWS account with no prior CDK deployments
  • Region: us-east-1
  • Pre-created VPC with CIDR 10.0.0.0/16, 2 public and 2 private subnets across us-east-1a and us-east-1b
  • All stacks disabled except InfrastructureStack to isolate the VPC import behavior

Configuration

Added existingVpc block to cdk.context.json:

"existingVpc": {
  "vpcId": "vpc-xxxxx",
  "availabilityZones": ["us-east-1a", "us-east-1b"],
  "publicSubnetIds": ["subnet-pub1", "subnet-pub2"],
  "privateSubnetIds": ["subnet-priv1", "subnet-priv2"],
  "vpcCidrBlock": "10.0.0.0/16"
}

Deployment Steps

  1. npm install + npm run build — clean TypeScript compilation, no errors
  2. npx cdk synth InfrastructureStack — template generated successfully. Expected CDK warnings about missing routeTableId on imported subnets (harmless — no stack resources read route table IDs)
  3. npx cdk bootstrap + npx cdk deploy InfrastructureStack — deployed in ~180s after resolving a Cognito domain prefix collision (global uniqueness constraint, unrelated to VPC feature)

Verification

Check Command Expected Actual Result
SSM VPC ID aws ssm get-parameter --name "/<prefix>/network/vpc-id" Matches input VPC ID Matches
No new VPC created aws ec2 describe-vpcs Only pre-existing VPC + default VPC 2 VPCs: input VPC + default
ALB in correct subnets aws elbv2 describe-load-balancers Public subnets from config Both public subnets matched
ALB reachable curl http://<alb-dns> HTTP 404 (default listener response) 404

Summary

The InfrastructureStack correctly imports an existing VPC via Vpc.fromVpcAttributes() instead of creating a new one. ALB, ECS cluster, security groups, DynamoDB tables, Cognito, and all SSM cross-stack parameters were created successfully using the imported VPC. The stack output confirmed the VPC ID matched the input configuration.

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.

5 participants