Initial commit: Spicy CDK automation framework

Jenkins shared library and CDK constructs for AWS infrastructure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-11-18 22:21:00 -08:00
commit 68684df471
51 changed files with 15587 additions and 0 deletions

317
docs/VPC.md Normal file
View File

@@ -0,0 +1,317 @@
# VPC Deployment Guide
Deploy production-ready VPCs with `spicyVPC`.
## Minimal Setup
```groovy
@Library(["spicy-automation@main"]) _
spicyVPC(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "my-vpc",
ownerTag: "MyTeam",
productTag: "myproduct",
componentTag: "vpc",
)
```
This creates a VPC with all defaults - see [What Gets Created](#what-gets-created).
## Full Configuration
```groovy
@Library(["spicy-automation@main"]) _
spicyVPC(
// Required
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "production-vpc",
ownerTag: "Platform",
productTag: "myapp",
componentTag: "network",
// Optional - VPC Configuration
vpcCidr: "10.0.0.0/16", // Default: 172.1.0.0/16
vpcTenancy: "default", // default | dedicated
numberOfAzs: 4, // 2, 3, or 4
availabilityZones: "ca-central-1a,ca-central-1b,ca-central-1c,ca-central-1d",
// Optional - Subnet Creation
createPrivateSubnets: true, // Default: true
createAdditionalPrivateSubnets: true, // Default: true (creates NACL-protected subnets)
// Optional - Subnet Tags
publicSubnetTag: "Network=Public",
privateSubnetATag: "Network=Private",
privateSubnetBTag: "Network=Private",
// Optional - Custom CIDRs (see Custom CIDR Configuration below)
// Optional - Pipeline Behavior
showDiff: true, // Show diff before deploy (default: true)
showDiffOnPR: true, // Show diff on non-main branches (default: true)
// Optional - Hooks
onPreDeploy: { args, ctx -> }, // Called before deployment
onPostDeploy: { args, ctx -> }, // Called after deployment
)
```
## Parameters Reference
### Required Parameters
| Parameter | Type | Description |
| ------------------------- | ------ | ------------------------------------------------------------- |
| `jenkinsAwsCredentialsId` | string | Jenkins credential ID for AWS access |
| `region` | string | AWS region (e.g., `ca-central-1`) |
| `stackName` | string | CloudFormation stack name (must be unique per account/region) |
| `ownerTag` | string | Owner tag applied to all resources |
| `productTag` | string | Product tag applied to all resources |
| `componentTag` | string | Component tag applied to all resources |
### VPC Configuration
| Parameter | Type | Default | Description |
| ------------------- | ------ | -------------- | ------------------------------------------- |
| `vpcCidr` | string | `172.1.0.0/16` | VPC CIDR block |
| `vpcTenancy` | string | `default` | Instance tenancy (`default` or `dedicated`) |
| `numberOfAzs` | number | `4` | Number of availability zones (2, 3, or 4) |
| `availabilityZones` | string | auto | Comma-separated AZ list |
### Subnet Configuration
| Parameter | Type | Default | Description |
| -------------------------------- | ------- | ------- | ------------------------------------------- |
| `createPrivateSubnets` | boolean | `true` | Create private subnets with NAT Gateways |
| `createAdditionalPrivateSubnets` | boolean | `true` | Create secondary private subnets with NACLs |
### Subnet Tags
| Parameter | Type | Default | Description |
| ------------------- | ------ | ----------------- | --------------------------------- |
| `publicSubnetTag` | string | `Network=Public` | Tag for public subnets |
| `privateSubnetATag` | string | `Network=Private` | Tag for primary private subnets |
| `privateSubnetBTag` | string | `Network=Private` | Tag for secondary private subnets |
## What Gets Created
With default settings, `spicyVPC` creates:
### Network Resources
- **1 VPC** with DNS hostnames and DNS support enabled
- **1 Internet Gateway** attached to the VPC
- **DHCP Options** configured for the region
### Public Subnets (4 AZs)
- 4 public subnets (one per AZ)
- 1 shared public route table with route to Internet Gateway
- Auto-assign public IP enabled
### Private Subnets Type 1 (4 AZs)
- 4 private subnets (one per AZ)
- 4 NAT Gateways (one per AZ) with Elastic IPs
- 4 route tables with routes to NAT Gateways
### Private Subnets Type 2 (4 AZs)
- 4 additional private subnets (one per AZ)
- 4 Network ACLs (allow all by default, customizable)
- 4 route tables with routes to NAT Gateways
### VPC Endpoints
- S3 Gateway Endpoint (free, attached to all private route tables)
## Default CIDR Blocks
| Subnet | AZ A | AZ B | AZ C | AZ D |
| --------- | -------------- | -------------- | -------------- | -------------- |
| Public | 172.1.128.0/20 | 172.1.144.0/20 | 172.1.160.0/20 | 172.1.176.0/20 |
| Private 1 | 172.1.0.0/19 | 172.1.32.0/19 | 172.1.64.0/19 | 172.1.96.0/19 |
| Private 2 | 172.1.192.0/21 | 172.1.200.0/21 | 172.1.208.0/21 | 172.1.216.0/21 |
## Custom CIDR Configuration
Override individual subnet CIDRs:
```groovy
spicyVPC(
// ... required params ...
// Public subnets
publicSubnetACidr: "10.0.0.0/20",
publicSubnetBCidr: "10.0.16.0/20",
publicSubnetCCidr: "10.0.32.0/20",
publicSubnetDCidr: "10.0.48.0/20",
// Private subnets (type 1)
privateSubnetA1Cidr: "10.0.64.0/19",
privateSubnetB1Cidr: "10.0.96.0/19",
privateSubnetC1Cidr: "10.0.128.0/19",
privateSubnetD1Cidr: "10.0.160.0/19",
// Private subnets (type 2, with NACLs)
privateSubnetA2Cidr: "10.0.192.0/21",
privateSubnetB2Cidr: "10.0.200.0/21",
privateSubnetC2Cidr: "10.0.208.0/21",
privateSubnetD2Cidr: "10.0.216.0/21",
)
```
## CloudFormation Outputs
The stack exports these values for cross-stack references:
| Export Name | Description |
| --------------------------------------- | ------------------------- |
| `{stackName}-VPCID` | VPC ID |
| `{stackName}-VPCCIDR` | VPC CIDR block |
| `{stackName}-PublicSubnetAID` | Public Subnet A ID |
| `{stackName}-PublicSubnetBID` | Public Subnet B ID |
| `{stackName}-PublicSubnetCID` | Public Subnet C ID |
| `{stackName}-PublicSubnetDID` | Public Subnet D ID |
| `{stackName}-PrivateSubnetA1ID` | Private Subnet A1 ID |
| `{stackName}-PrivateSubnetB1ID` | Private Subnet B1 ID |
| `{stackName}-PrivateSubnetC1ID` | Private Subnet C1 ID |
| `{stackName}-PrivateSubnetD1ID` | Private Subnet D1 ID |
| `{stackName}-PrivateSubnetA2ID` | Private Subnet A2 ID |
| `{stackName}-PrivateSubnetB2ID` | Private Subnet B2 ID |
| `{stackName}-PrivateSubnetC2ID` | Private Subnet C2 ID |
| `{stackName}-PrivateSubnetD2ID` | Private Subnet D2 ID |
| `{stackName}-NATZoneAEIP` | NAT Gateway A Elastic IP |
| `{stackName}-NATZoneBEIP` | NAT Gateway B Elastic IP |
| `{stackName}-NATZoneCEIP` | NAT Gateway C Elastic IP |
| `{stackName}-NATZoneDEIP` | NAT Gateway D Elastic IP |
| `{stackName}-PublicSubnetRouteTable` | Public Route Table ID |
| `{stackName}-PrivateSubnetA1RouteTable` | Private A1 Route Table ID |
| `{stackName}-PrivateSubnetB1RouteTable` | Private B1 Route Table ID |
| `{stackName}-PrivateSubnetC1RouteTable` | Private C1 Route Table ID |
| `{stackName}-PrivateSubnetD1RouteTable` | Private D1 Route Table ID |
## Using Account Configurations
For multi-environment deployments:
```groovy
@Library(["spicy-automation@main"]) _
def account = accounts.get().SPICY_CA_CENRAL_1_PROD
spicyVPC(
jenkinsAwsCredentialsId: account.jenkinsAwsCredentialsId,
region: account.region,
accountId: account.accountId,
stackName: "production-vpc",
ownerTag: "Platform",
productTag: "spicy",
componentTag: "vpc",
)
```
## Pipeline Hooks
### Pre-Deploy Hook
```groovy
spicyVPC(
// ... params ...
onPreDeploy: { args, ctx ->
echo "About to deploy ${args.stackName}"
// Run custom validation, notifications, etc.
}
)
```
### Post-Deploy Hook
```groovy
spicyVPC(
// ... params ...
onPostDeploy: { args, ctx ->
echo "Deployed stack: ${ctx.stackName}"
// Update DNS, notify Slack, etc.
}
)
```
## Examples
### Development VPC (2 AZs, No NACL Subnets)
```groovy
spicyVPC(
jenkinsAwsCredentialsId: "aws-dev",
region: "ca-central-1",
stackName: "dev-vpc",
ownerTag: "Dev",
productTag: "myapp",
componentTag: "vpc",
numberOfAzs: 2,
createAdditionalPrivateSubnets: false,
)
```
### Production VPC (Full HA)
```groovy
spicyVPC(
jenkinsAwsCredentialsId: "aws-prod",
region: "ca-central-1",
stackName: "prod-vpc",
ownerTag: "Platform",
productTag: "myapp",
componentTag: "vpc",
vpcCidr: "10.0.0.0/16",
numberOfAzs: 4,
createPrivateSubnets: true,
createAdditionalPrivateSubnets: true,
)
```
### Public-Only VPC (No NAT Gateways)
```groovy
spicyVPC(
jenkinsAwsCredentialsId: "aws-credentials",
region: "ca-central-1",
stackName: "public-vpc",
ownerTag: "Dev",
productTag: "myapp",
componentTag: "vpc",
createPrivateSubnets: false,
)
```
## Local Testing
Test VPC synthesis locally:
```bash
cd spicy-automation
# Synthesize with minimal config
npx cdk synth \
-c stackType=vpc \
-c stackName=test-vpc \
-c ownerTag=Test \
-c productTag=test \
-c componentTag=vpc
# With custom options
npx cdk synth \
-c stackType=vpc \
-c stackName=test-vpc \
-c ownerTag=Test \
-c productTag=test \
-c componentTag=vpc \
-c vpcCidr=10.0.0.0/16 \
-c numberOfAzs=2 \
-c createAdditionalPrivateSubnets=false
```