Jenkins shared library and CDK constructs for AWS infrastructure. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
198 lines
5.7 KiB
Groovy
198 lines
5.7 KiB
Groovy
/**
|
|
* CDK Utilities for Spicy CDK pipelines
|
|
*
|
|
* Provides functions to run AWS CDK commands from Jenkins pipelines.
|
|
* CDK runs directly on the Jenkins worker (no Docker needed for CDK itself).
|
|
*/
|
|
|
|
/**
|
|
* Run a CDK command
|
|
*
|
|
* @param args.account Account configuration with region and jenkinsAwsCredentialsId
|
|
* @param args.command The CDK command to run (e.g., "deploy", "diff", "synth")
|
|
* @param args.stackName Name of the stack to deploy
|
|
* @param args.context Map of context values to pass to CDK (-c key=value)
|
|
* @param args.workDir Working directory (default: current directory)
|
|
* @param args.requireApproval CDK approval level (default: "never" for CI/CD)
|
|
*/
|
|
def runCdk(Map args) {
|
|
def account = args.account
|
|
def command = args.command ?: "deploy"
|
|
def stackName = args.stackName
|
|
def context = args.context ?: [:]
|
|
def workDir = args.workDir ?: "cdk-source"
|
|
def requireApproval = args.requireApproval ?: "never"
|
|
|
|
// Build context arguments
|
|
def contextArgs = context.collect { k, v ->
|
|
if (v != null && v != '') {
|
|
"-c ${k}='${v}'"
|
|
}
|
|
}.findAll { it != null }.join(' ')
|
|
|
|
// Build the full CDK command
|
|
def cdkCommand = "npx cdk ${command}"
|
|
|
|
if (stackName) {
|
|
cdkCommand += " ${stackName}"
|
|
}
|
|
|
|
if (contextArgs) {
|
|
cdkCommand += " ${contextArgs}"
|
|
}
|
|
|
|
if (command == "deploy") {
|
|
cdkCommand += " --require-approval ${requireApproval}"
|
|
}
|
|
|
|
if (command == "destroy") {
|
|
cdkCommand += " --force"
|
|
}
|
|
|
|
// Run with AWS credentials
|
|
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding',
|
|
credentialsId: account.jenkinsAwsCredentialsId]]) {
|
|
dir(workDir) {
|
|
sh """
|
|
export AWS_DEFAULT_REGION=${account.region}
|
|
export CDK_DEFAULT_ACCOUNT=${account.accountId ?: ''}
|
|
export CDK_DEFAULT_REGION=${account.region}
|
|
${cdkCommand}
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deploy a CDK stack
|
|
*
|
|
* @param args.account Account configuration
|
|
* @param args.stackName Name of the stack
|
|
* @param args.stackType Type of stack (vpc, ecs-cluster, ecs-service)
|
|
* @param args.context Additional context values
|
|
*/
|
|
def deploy(Map args) {
|
|
def context = args.context ?: [:]
|
|
|
|
// Add stackType and stackName to context
|
|
context.stackType = args.stackType ?: "vpc"
|
|
context.stackName = args.stackName
|
|
context.region = args.account.region
|
|
|
|
runCdk(
|
|
account: args.account,
|
|
command: "deploy",
|
|
stackName: args.stackName,
|
|
context: context,
|
|
workDir: args.workDir ?: "cdk-source"
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Show diff for a CDK stack
|
|
*/
|
|
def diff(Map args) {
|
|
def context = args.context ?: [:]
|
|
context.stackType = args.stackType ?: "vpc"
|
|
context.stackName = args.stackName
|
|
context.region = args.account.region
|
|
|
|
runCdk(
|
|
account: args.account,
|
|
command: "diff",
|
|
stackName: args.stackName,
|
|
context: context,
|
|
workDir: args.workDir ?: "cdk-source"
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Synthesize CloudFormation template for a CDK stack
|
|
*/
|
|
def synth(Map args) {
|
|
def context = args.context ?: [:]
|
|
context.stackType = args.stackType ?: "vpc"
|
|
context.stackName = args.stackName
|
|
context.region = args.account.region
|
|
|
|
runCdk(
|
|
account: args.account,
|
|
command: "synth",
|
|
stackName: args.stackName,
|
|
context: context,
|
|
workDir: args.workDir ?: "cdk-source"
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Destroy a CDK stack
|
|
*/
|
|
def destroy(Map args) {
|
|
def context = args.context ?: [:]
|
|
context.stackType = args.stackType ?: "vpc"
|
|
context.stackName = args.stackName
|
|
context.region = args.account.region
|
|
|
|
runCdk(
|
|
account: args.account,
|
|
command: "destroy",
|
|
stackName: args.stackName,
|
|
context: context,
|
|
workDir: args.workDir ?: "cdk-source"
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Install CDK workspace files from library resources.
|
|
* Assumes CDK/TypeScript toolchain is available globally on the agent.
|
|
*/
|
|
def install(Map args = [:]) {
|
|
def workDir = args.workDir ?: "cdk-source"
|
|
dir(workDir) {
|
|
// Ensure expected directory layout exists before copying files from resources
|
|
sh "mkdir -pv bin lib lib/constructs lib/stacks"
|
|
|
|
// Copy CDK project files from shared library resources into the workspace
|
|
[
|
|
[source: "package.json", destination: "package.json"],
|
|
[source: "pnpm-lock.yaml", destination: "pnpm-lock.yaml"],
|
|
[source: "tsconfig.json", destination: "tsconfig.json"],
|
|
[source: "cdk.json", destination: "cdk.json"],
|
|
[source: "cdk.context.json", destination: "cdk.context.json"],
|
|
[source: "bin/spicy-cdk.ts", destination: "bin/spicy-cdk.ts"],
|
|
[source: "lib/index.ts", destination: "lib/index.ts"],
|
|
[source: "lib/constructs/index.ts", destination: "lib/constructs/index.ts"],
|
|
[source: "lib/constructs/spicy-alb.ts", destination: "lib/constructs/spicy-alb.ts"],
|
|
[source: "lib/constructs/spicy-ecs-cluster.ts", destination: "lib/constructs/spicy-ecs-cluster.ts"],
|
|
[source: "lib/constructs/spicy-ecs-service.ts", destination: "lib/constructs/spicy-ecs-service.ts"],
|
|
[source: "lib/constructs/spicy-vpc.ts", destination: "lib/constructs/spicy-vpc.ts"],
|
|
[source: "lib/stacks/index.ts", destination: "lib/stacks/index.ts"],
|
|
[source: "lib/stacks/spicy-alb-stack.ts", destination: "lib/stacks/spicy-alb-stack.ts"],
|
|
[source: "lib/stacks/spicy-ecs-cluster-stack.ts", destination: "lib/stacks/spicy-ecs-cluster-stack.ts"],
|
|
[source: "lib/stacks/spicy-ecs-service-stack.ts", destination: "lib/stacks/spicy-ecs-service-stack.ts"],
|
|
[source: "lib/stacks/spicy-vpc-stack.ts", destination: "lib/stacks/spicy-vpc-stack.ts"],
|
|
].each { entry ->
|
|
resources.copyResourceFile(
|
|
source: entry.source,
|
|
destination: entry.destination,
|
|
overwrite: true
|
|
)
|
|
}
|
|
|
|
sh "pnpm install --frozen-lockfile"
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run CDK tests
|
|
*/
|
|
def test(Map args = [:]) {
|
|
def workDir = args.workDir ?: "."
|
|
dir(workDir) {
|
|
sh "pnpm run test"
|
|
}
|
|
}
|
|
|
|
return this
|
|
|