Files
spicy-automation/vars/spicyVPC.groovy
Ryan Wilson 68684df471 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>
2025-11-18 22:21:00 -08:00

190 lines
6.0 KiB
Groovy

/**
* Spicy VPC Pipeline
*
* Deploys a VPC using AWS CDK.
*
* Usage in Jenkinsfile:
* ```groovy
* @Library(["spicy-automation@main"]) _
*
* spicyVPC(
* jenkinsAwsCredentialsId: "aws-credentials",
* region: "ca-central-1",
* stackName: "spicy-vpc",
* ownerTag: "SpicyTeam",
* productTag: "spicy",
* componentTag: "spicy-VPC",
* availabilityZones: "ca-central-1a,ca-central-1b,ca-central-1c,ca-central-1d",
* createPrivateSubnets: true,
* createAdditionalPrivateSubnets: true,
* )
* ```
*/
def call(Map args) {
args = spicyDefaults(args)
timeout(time: 1, unit: "DAYS") {
timestamps {
node("docker") {
properties(args.pipelineProperties)
ansiColor("xterm") {
stage("Checkout") {
checkout scm
giteaUtils.setSuccess("checkout")
}
stage("Setup") {
cdkUtils.install()
giteaUtils.setSuccess("setup")
}
if (args.onPreDeploy) {
spicyUtils.stageWithFailure("PreDeploy") {
args.onPreDeploy.call(args, [:])
}
}
stage("Deploy VPC") {
if (gitUtils.isMain()) {
try {
// Build context from args
def context = buildVpcContext(args)
// Create account object for cdkUtils
def account = awsUtils.buildAccountConfig(args)
// Show diff first (optional, for visibility)
if (args.showDiff != false) {
echo "Showing CDK diff..."
cdkUtils.diff(
account: account,
stackName: args.stackName,
stackType: "vpc",
context: context
)
}
// Deploy the stack
echo "Deploying VPC stack: ${args.stackName}"
cdkUtils.deploy(
account: account,
stackName: args.stackName,
stackType: "vpc",
context: context
)
giteaUtils.setSuccess("deploy")
if (args.onPostDeploy) {
spicyUtils.stageWithFailure("PostDeploy") {
args.onPostDeploy.call(args, [
stackName: args.stackName
])
}
}
} catch (err) {
giteaUtils.setFailed("deploy")
throw err
}
} else {
echo "Skipping deployment - not on main branch"
// Still show diff on non-main branches for PR review
if (args.showDiffOnPR != false) {
def context = buildVpcContext(args)
def account = [
region: args.region,
jenkinsAwsCredentialsId: args.jenkinsAwsCredentialsId,
accountId: args.accountId ?: ''
]
echo "Showing CDK diff for PR review..."
try {
cdkUtils.diff(
account: account,
stackName: args.stackName,
stackType: "vpc",
context: context
)
} catch (err) {
echo "Diff failed (stack may not exist yet): ${err.message}"
}
}
}
}
giteaUtils.setSuccess("pipeline")
}
}
}
}
}
/**
* Build CDK context map from pipeline arguments
*/
def buildVpcContext(Map args) {
def context = [:]
// Required tags
context.ownerTag = args.ownerTag
context.productTag = args.productTag
context.componentTag = args.componentTag
// Optional build tag
context.build = args.build ?: gitUtils.getShortSHA()
// VPC configuration
if (args.vpcCidr) context.vpcCidr = args.vpcCidr
if (args.vpcTenancy) context.vpcTenancy = args.vpcTenancy
// Availability zones
if (args.availabilityZones) {
context.availabilityZones = args.availabilityZones
// Calculate numberOfAzs from the AZ list if not explicitly provided
if (!args.numberOfAzs) {
context.numberOfAzs = args.availabilityZones.split(",").length.toString()
}
}
if (args.numberOfAzs) context.numberOfAzs = args.numberOfAzs.toString()
// Subnet creation flags
if (args.createPrivateSubnets != null) {
context.createPrivateSubnets = args.createPrivateSubnets.toString()
}
if (args.createAdditionalPrivateSubnets != null) {
context.createAdditionalPrivateSubnets = args.createAdditionalPrivateSubnets.toString()
}
// Subnet tags
if (args.publicSubnetTag) context.publicSubnetTag = args.publicSubnetTag
if (args.privateSubnetATag) context.privateSubnetATag = args.privateSubnetATag
if (args.privateSubnetBTag) context.privateSubnetBTag = args.privateSubnetBTag
// Public subnet CIDRs
if (args.publicSubnetACidr) context.publicSubnetACidr = args.publicSubnetACidr
if (args.publicSubnetBCidr) context.publicSubnetBCidr = args.publicSubnetBCidr
if (args.publicSubnetCCidr) context.publicSubnetCCidr = args.publicSubnetCCidr
if (args.publicSubnetDCidr) context.publicSubnetDCidr = args.publicSubnetDCidr
// Private subnet 1 CIDRs
if (args.privateSubnetA1Cidr) context.privateSubnetA1Cidr = args.privateSubnetA1Cidr
if (args.privateSubnetB1Cidr) context.privateSubnetB1Cidr = args.privateSubnetB1Cidr
if (args.privateSubnetC1Cidr) context.privateSubnetC1Cidr = args.privateSubnetC1Cidr
if (args.privateSubnetD1Cidr) context.privateSubnetD1Cidr = args.privateSubnetD1Cidr
// Private subnet 2 CIDRs (with NACLs)
if (args.privateSubnetA2Cidr) context.privateSubnetA2Cidr = args.privateSubnetA2Cidr
if (args.privateSubnetB2Cidr) context.privateSubnetB2Cidr = args.privateSubnetB2Cidr
if (args.privateSubnetC2Cidr) context.privateSubnetC2Cidr = args.privateSubnetC2Cidr
if (args.privateSubnetD2Cidr) context.privateSubnetD2Cidr = args.privateSubnetD2Cidr
return context
}
return this