/** * 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