Jenkins shared library and CDK constructs for AWS infrastructure. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
6.0 KiB
Groovy
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
|
|
|