From adc3eb01e6c7c96ac5cee4544accdc5c75d6900e Mon Sep 17 00:00:00 2001 From: "Wais,Erhard (IT INF) BIG-AT-V" Date: Mon, 4 Sep 2023 12:46:55 +0200 Subject: [PATCH] initial commit of the AWS CDK Python Quickstarter --- inf-cdk-python-aws/Jenkinsfile | 30 ++++ inf-cdk-python-aws/Jenkinsfile.template | 150 ++++++++++++++++++ inf-cdk-python-aws/README.md | 5 + .../.devcontainer/devcontainer.json.template | 3 + inf-cdk-python-aws/files/.editorconfig | 19 +++ inf-cdk-python-aws/files/.gitignore | 5 + inf-cdk-python-aws/files/README.md | 62 ++++++++ inf-cdk-python-aws/files/metadata.yml | 7 + inf-cdk-python-aws/files/release-manager.yml | 2 + .../files/reports/install/.gitkeep | 1 + .../files/src/requirements-dev.txt | 1 + 11 files changed, 285 insertions(+) create mode 100644 inf-cdk-python-aws/Jenkinsfile create mode 100644 inf-cdk-python-aws/Jenkinsfile.template create mode 100644 inf-cdk-python-aws/README.md create mode 100644 inf-cdk-python-aws/files/.devcontainer/devcontainer.json.template create mode 100644 inf-cdk-python-aws/files/.editorconfig create mode 100644 inf-cdk-python-aws/files/.gitignore create mode 100644 inf-cdk-python-aws/files/README.md create mode 100644 inf-cdk-python-aws/files/metadata.yml create mode 100644 inf-cdk-python-aws/files/release-manager.yml create mode 100644 inf-cdk-python-aws/files/reports/install/.gitkeep create mode 100644 inf-cdk-python-aws/files/src/requirements-dev.txt diff --git a/inf-cdk-python-aws/Jenkinsfile b/inf-cdk-python-aws/Jenkinsfile new file mode 100644 index 000000000..23a9523ee --- /dev/null +++ b/inf-cdk-python-aws/Jenkinsfile @@ -0,0 +1,30 @@ +def odsNamespace = '' +def odsGitRef = '' +def odsImageTag = '' +def sharedLibraryRef = '' +def agentImageTag = '' + +node { + odsNamespace = env.ODS_NAMESPACE ?: 'ods' + odsGitRef = env.ODS_GIT_REF ?: 'master' + odsImageTag = env.ODS_IMAGE_TAG ?: 'latest' + sharedLibraryRef = env.SHARED_LIBRARY_REF ?: odsImageTag + agentImageTag = env.AGENT_IMAGE_TAG ?: odsImageTag +} + +library("ods-jenkins-shared-library@${sharedLibraryRef}") + +odsQuickstarterPipeline( + imageStreamTag: "${odsNamespace}/jenkins-agent-terraform2:${agentImageTag}", +) { context -> + + // Create a new AWS CDK project by invoking cdk init. + sh(""" + mkdir ${context.componentId}/src && cd ${context.componentId}/src + cdk init app --language python + """) + + odsQuickstarterStageCopyFiles(context) + + odsQuickstarterStageRenderJenkinsfile(context) +} diff --git a/inf-cdk-python-aws/Jenkinsfile.template b/inf-cdk-python-aws/Jenkinsfile.template new file mode 100644 index 000000000..4ae7af8f9 --- /dev/null +++ b/inf-cdk-python-aws/Jenkinsfile.template @@ -0,0 +1,150 @@ +/* generated jenkins file used for building and deploying AWS-infrastructure in projects */ + +@Library('ods-jenkins-shared-library@@shared_library_ref@') _ + +odsComponentPipeline( + imageStreamTag: '@ods_namespace@/jenkins-agent-terraform-2306:@agent_image_tag@', + branchToEnvironmentMapping: [ + 'master': 'dev', + 'feature/': 'dev' + ] +) { context -> + + /* Account credentials are provided via OpenShift, see AWS Terraform Quickstarter also */ + awsAccountIds = [ + 'dev': '', + 'test': '', + 'prod': '' + ] + awsRegions = [ + 'dev': 'eu-west-1', + 'test': 'eu-west-1', + 'prod': 'eu-west-1' + ] + + withEnv([ + "CDK_DEFAULT_REGION=${awsRegions[context.environment]}", + "AWS_DEFAULT_REGION=${awsRegions[context.environment]}", + ]){ + dir('src/') { // directory where your CDK stack is located + stagePrepareVirtualEnv(context) + stageAwsAccountInformation(context, awsAccountIds[context.environment], awsRegions[context.environment]) + + stageBootstrap(context, awsAccountIds[context.environment], awsRegions[context.environment]) + stageUnitTest(context) + stageDiff(context) + stageDeploy(context) + } + } +} + +def stagePrepareVirtualEnv(def context){ + stage('Prepare Python Virtual Environment') { + sh "python --version" + sh "python -mvenv .venv" + sh "source .venv/bin/activate && pip install -r requirements.txt -r requirements-dev.txt" + } +} + +def stageAwsAccountInformation(context, String awsAccountId, String awsRegion) { + stage('AWS account information') { + echo "awsAccountId: ${awsAccountId}" + echo "awsRegion: ${awsRegion}" + echo "Reading credentialsId: ${context.projectId}-cd-aws-access-key-id-${context.environment}" + echo "Reading credentialsId: ${context.projectId}-cd-aws-secret-access-key-${context.environment}" + withCredentials([ + string( + credentialsId: "${context.projectId}-cd-aws-access-key-id-${context.environment}", + variable: 'AWS_ACCESS_KEY_ID'), + string( + credentialsId: "${context.projectId}-cd-aws-secret-access-key-${context.environment}", + variable: 'AWS_SECRET_ACCESS_KEY'), + ]) { + sh 'env | sort' + sh "aws sts get-caller-identity" + } + } +} + +def stageBootstrap(def context, String awsAccountId, String awsRegion) { + stage('Bootstrap') { + withCredentials([ + string( + credentialsId: "${context.projectId}-cd-aws-access-key-id-${context.environment}", + variable: 'AWS_ACCESS_KEY_ID'), + string( + credentialsId: "${context.projectId}-cd-aws-secret-access-key-${context.environment}", + variable: 'AWS_SECRET_ACCESS_KEY'), + ]) { + def success = sh(script: """ + #!/bin/bash -e + source .venv/bin/activate && \ + cdk bootstrap aws://${awsAccountId}/${awsRegion} + """, returnStatus: true) + if (success!=0){ + error("CDK bootstrap failed") + } + } + } +} + +def stageUnitTest(def context) { + stage('Unit Test') { + withCredentials([ + string( + credentialsId: "${context.projectId}-cd-aws-access-key-id-${context.environment}", + variable: 'AWS_ACCESS_KEY_ID'), + string( + credentialsId: "${context.projectId}-cd-aws-secret-access-key-${context.environment}", + variable: 'AWS_SECRET_ACCESS_KEY'), + ]) { + sh """ + #!/bin/bash -e + source .venv/bin/activate + pytest --verbose --junitxml=../build/test-results/test/junit.xml + + """ + } + } +} + +def stageDiff(def context) { + stage('Diff') { + withCredentials([ + string( + credentialsId: "${context.projectId}-cd-aws-access-key-id-${context.environment}", + variable: 'AWS_ACCESS_KEY_ID'), + string( + credentialsId: "${context.projectId}-cd-aws-secret-access-key-${context.environment}", + variable: 'AWS_SECRET_ACCESS_KEY'), + ]) { + sh """ + #!/bin/bash -e + source .venv/bin/activate + cdk diff + """ + } + } +} + +def stageDeploy(def context) { + stage('Deploy') { + withCredentials([ + string( + credentialsId: "${context.projectId}-cd-aws-access-key-id-${context.environment}", + variable: 'AWS_ACCESS_KEY_ID'), + string( + credentialsId: "${context.projectId}-cd-aws-secret-access-key-${context.environment}", + variable: 'AWS_SECRET_ACCESS_KEY'), + ]) { + sh """ + #!/bin/bash -e + source .venv/bin/activate + cdk deploy --ci --require-approval never \\ + --context env=${context.environment} \\ + --context project=${context.projectId} \\ + --context anotherContextKey=anotherContextValue + """ + } + } +} diff --git a/inf-cdk-python-aws/README.md b/inf-cdk-python-aws/README.md new file mode 100644 index 000000000..d7f7a1c9c --- /dev/null +++ b/inf-cdk-python-aws/README.md @@ -0,0 +1,5 @@ +# CDK Python Quickstarter (inf-cdk-python-aws) + +Documentation is located in our [official documentation](https://www.opendevstack.org/ods-documentation/ods-quickstarters/latest/index.html) + +Please update documentation in the [antora page directory](https://github.com/opendevstack/ods-quickstarters/tree/master/docs/modules/quickstarters/pages) diff --git a/inf-cdk-python-aws/files/.devcontainer/devcontainer.json.template b/inf-cdk-python-aws/files/.devcontainer/devcontainer.json.template new file mode 100644 index 000000000..f0810403b --- /dev/null +++ b/inf-cdk-python-aws/files/.devcontainer/devcontainer.json.template @@ -0,0 +1,3 @@ +{ + "image": "ghcr.io/nichtraunzer/terrarium:latest" +} diff --git a/inf-cdk-python-aws/files/.editorconfig b/inf-cdk-python-aws/files/.editorconfig new file mode 100644 index 000000000..147abfb08 --- /dev/null +++ b/inf-cdk-python-aws/files/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false ; trimming trailing whitespace may break Markdown + +[Makefile] +tab_width = 2 +indent_style = tab diff --git a/inf-cdk-python-aws/files/.gitignore b/inf-cdk-python-aws/files/.gitignore new file mode 100644 index 000000000..91ebb2cd2 --- /dev/null +++ b/inf-cdk-python-aws/files/.gitignore @@ -0,0 +1,5 @@ +reports/install/* +!reports/install/.gitkeep +.devcontainer +.venv +build diff --git a/inf-cdk-python-aws/files/README.md b/inf-cdk-python-aws/files/README.md new file mode 100644 index 000000000..6394c45e1 --- /dev/null +++ b/inf-cdk-python-aws/files/README.md @@ -0,0 +1,62 @@ +# ODS AWS CDK Python Quickstarter + +This Quickstarter can be used to deploy AWS resources. Its primary usage is to build solutions based on AWS CDK Python. + +## What is the AWS CDK? + +The AWS Cloud Development Kit (CDK) is an open-source software development framework that allows you to define cloud infrastructure in code. It provides a high-level object-oriented abstraction to define AWS resources imperatively using programming languages like TypeScript, JavaScript, Python, Java, and C#. + +## AWS CDK with Python + +AWS CDK supports Python as one of the programming languages to define and manage cloud infrastructure. You can use Python to write your infrastructure code, which will be compiled into AWS CloudFormation templates. This allows you to leverage Python's features and libraries to create, modify, and manage your AWS resources. + +## How to get started? + +The Quickstarter will automatically create a new AWS CDK Python project in your component repository. +In order to develop, the Python package installer, pip, and virtual environment manager, virtualenv, are required. The provided ODS agent comes already installed with these tools. + +If you want to develop locally, make sure those tools are available in your environment, too. To run your code locally execute the following commands: + +``` +$ python -mvenv .venv +$ cd src +$ source ../.venv/bin/activate && pip install -r requirements.txt -r requirements-dev.txt +``` +You may want to to verify you code by running ... +``` +$ pytest +``` + +Note that your code will interact with *AWS*. It is up to you to provide sufficient configuration to enable these interactions. Here is an example for *AWS* that uses environment variables (via [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)): + +``` +$ export AWS_ACCESS_KEY_ID=... +$ export AWS_SECRET_ACCESS_KEY=... +$ export AWS_DEFAULT_REGION=us-east-1 +``` + +## Brief Example + +Here's a simple example of using AWS CDK with Python to create an Amazon S3 bucket: +``` +from aws_cdk import core +from aws_cdk.aws_s3 import Bucket + +class MyS3BucketStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon S3 bucket + Bucket(self, "MyBucket", versioned=True) + +app = core.App() +MyS3BucketStack(app, "MyS3BucketStack") +app.synth() +``` +In this example, we import the necessary modules, define a stack class, create an S3 bucket with versioning enabled, and then synthesize the stack to generate the CloudFormation template. + +## Problems? Questions? Suggestions? + +In case of problems, questions or suggestions, feel free to file an issue with the respective project's repository. Thanks! + diff --git a/inf-cdk-python-aws/files/metadata.yml b/inf-cdk-python-aws/files/metadata.yml new file mode 100644 index 000000000..b4c66dd89 --- /dev/null +++ b/inf-cdk-python-aws/files/metadata.yml @@ -0,0 +1,7 @@ +--- +name: AWS CDK (Python) +# yamllint disable-line rule:line-length +description: "The AWS CDK lets you build reliable, scalable, cost-effective applications in the cloud with the considerable expressive power of a programming language." +supplier: https://docs.aws.amazon.com/cdk/v2/guide/home.html +version: 4.x +type: ods-infra diff --git a/inf-cdk-python-aws/files/release-manager.yml b/inf-cdk-python-aws/files/release-manager.yml new file mode 100644 index 000000000..23d65c7ef --- /dev/null +++ b/inf-cdk-python-aws/files/release-manager.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/inf-cdk-python-aws/files/reports/install/.gitkeep b/inf-cdk-python-aws/files/reports/install/.gitkeep new file mode 100644 index 000000000..9074a39d4 --- /dev/null +++ b/inf-cdk-python-aws/files/reports/install/.gitkeep @@ -0,0 +1 @@ +/report.* diff --git a/inf-cdk-python-aws/files/src/requirements-dev.txt b/inf-cdk-python-aws/files/src/requirements-dev.txt new file mode 100644 index 000000000..9299a7a8b --- /dev/null +++ b/inf-cdk-python-aws/files/src/requirements-dev.txt @@ -0,0 +1 @@ +pytest==6.2.5 \ No newline at end of file