Skip to content

Commit

Permalink
feat: added a CodePipeline Python example building a Docker image (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
josjaf authored and skinny85 committed Oct 21, 2019
1 parent 103c296 commit ffda295
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 0 deletions.
75 changes: 75 additions & 0 deletions python/codepipeline-docker-build/Base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from aws_cdk import (
aws_s3 as aws_s3,
aws_ecr,
aws_codebuild,
aws_ssm,
core,
)

class Base(core.Stack):
def __init__(self, app: core.App, id: str, props, **kwargs) -> None:
super().__init__(app, id, **kwargs)

# pipeline requires versioned bucket
bucket = aws_s3.Bucket(
self, "SourceBucket",
bucket_name=f"{props['namespace'].lower()}-{core.Aws.ACCOUNT_ID}",
versioned=True,
removal_policy=core.RemovalPolicy.DESTROY)
# ssm parameter to get bucket name later
bucket_param = aws_ssm.StringParameter(
self, "ParameterB",
parameter_name=f"{props['namespace']}-bucket",
string_value=bucket.bucket_name,
description='cdk pipeline bucket'
)
# ecr repo to push docker container into
ecr = aws_ecr.Repository(
self, "ECR",
repository_name=f"{props['namespace']}",
removal_policy=core.RemovalPolicy.DESTROY
)
# codebuild project meant to run in pipeline
cb_docker_build = aws_codebuild.PipelineProject(
self, "DockerBuild",
project_name=f"{props['namespace']}-Docker-Build",
build_spec=aws_codebuild.BuildSpec.from_source_filename(
filename='pipeline_delivery/docker_build_buildspec.yml'),
environment=aws_codebuild.BuildEnvironment(
privileged=True,
),
# pass the ecr repo uri into the codebuild project so codebuild knows where to push
environment_variables={
'ecr': aws_codebuild.BuildEnvironmentVariable(
value=ecr.repository_uri),
'tag': aws_codebuild.BuildEnvironmentVariable(
value='cdk')
},
description='Pipeline for CodeBuild',
timeout=core.Duration.minutes(60),
)
# codebuild iam permissions to read write s3
bucket.grant_read_write(cb_docker_build)

# codebuild permissions to interact with ecr
ecr.grant_pull_push(cb_docker_build)

core.CfnOutput(
self, "ECRURI",
description="ECR URI",
value=ecr.repository_uri,
)
core.CfnOutput(
self, "S3Bucket",
description="S3 Bucket",
value=bucket.bucket_name
)

self.output_props = props.copy()
self.output_props['bucket']= bucket
self.output_props['cb_docker_build'] = cb_docker_build

# pass objects to another stack
@property
def outputs(self):
return self.output_props
62 changes: 62 additions & 0 deletions python/codepipeline-docker-build/Pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from aws_cdk import (
aws_codepipeline,
aws_codepipeline_actions,
aws_ssm,
core,
)


class Pipeline(core.Stack):
def __init__(self, app: core.App, id: str, props, **kwargs) -> None:
super().__init__(app, id, **kwargs)
# define the s3 artifact
source_output = aws_codepipeline.Artifact(artifact_name='source')
# define the pipeline
pipeline = aws_codepipeline.Pipeline(
self, "Pipeline",
pipeline_name=f"{props['namespace']}",
artifact_bucket=props['bucket'],
stages=[
aws_codepipeline.StageProps(
stage_name='Source',
actions=[
aws_codepipeline_actions.S3SourceAction(
bucket=props['bucket'],
bucket_key='source.zip',
action_name='S3Source',
run_order=1,
output=source_output,
trigger=aws_codepipeline_actions.S3Trigger.POLL
),
]
),
aws_codepipeline.StageProps(
stage_name='Build',
actions=[
aws_codepipeline_actions.CodeBuildAction(
action_name='DockerBuildImages',
input=source_output,
project=props['cb_docker_build'],
run_order=1,
)
]
)
]

)
# give pipelinerole read write to the bucket
props['bucket'].grant_read_write(pipeline.role)

#pipeline param to get the
pipeline_param = aws_ssm.StringParameter(
self, "PPipeline",
parameter_name=f"{props['namespace']}-pipeline",
string_value=pipeline.pipeline_name,
description='cdk pipeline bucket'
)
# cfn output
core.CfnOutput(
self, "PipelineOut",
description="Pipeline",
value=pipeline.pipeline_name
)
6 changes: 6 additions & 0 deletions python/codepipeline-docker-build/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# CDK Python CodePipeline Example
* This is an example of a CodePipeline project that uses CodeBuild to Build a Docker Image and push to ECR.
* This example uses multiple stacks for the purpose of demonstrating ways of passing in objects from different stacks
* push.sh will trigger the pipeline via an S3 Upload.
* Parameter Store is used to store the value of the Pipeline and S3 Bucket so it can be retrieved later in push.sh.
* Parameter Store can be replaced with CloudFormation Outputs or Exports
17 changes: 17 additions & 0 deletions python/codepipeline-docker-build/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from aws_cdk import (
core,
)

from Base import Base
from Pipeline import Pipeline

props = {'namespace': 'cdk-example-pipeline'}
app = core.App()

# stack for ecr, bucket, codebuild
base = Base(app, f"{props['namespace']}-base", props)

# pipeline stack
pipeline = Pipeline(app, f"{props['namespace']}-pipeline", base.outputs)
pipeline.add_dependency(base)
app.synth()
3 changes: 3 additions & 0 deletions python/codepipeline-docker-build/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "python3 app.py"
}
2 changes: 2 additions & 0 deletions python/codepipeline-docker-build/pipeline_delivery/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM python:3.7.2-alpine
RUN pip install awscli
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 0.2

phases:
pre_build:
commands:
- echo logging into docker
- $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
build:
commands:
- echo Entered the post_build phase...
- echo Build completed on `date`
- docker build -t ${tag}:latest pipeline_delivery/
- docker tag $tag:latest $ecr:$tag
- docker push $ecr

11 changes: 11 additions & 0 deletions python/codepipeline-docker-build/push.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash


export account_id=$(aws sts get-caller-identity | jq -r .Account)
export source_bucket=$(aws ssm get-parameter --name 'cdk-example-pipeline-bucket' | jq -r .Parameter.Value)
export pipeline_name=$(aws ssm get-parameter --name 'cdk-example-pipeline-pipeline' | jq -r .Parameter.Value)
export REGION='us-east-1'

zip -r source.zip .
aws s3 cp source.zip s3://${source_bucket}/source.zip
#aws codepipeline start-pipeline-execution --name ${pipeline_name}
15 changes: 15 additions & 0 deletions python/codepipeline-docker-build/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
aws-cdk.aws-cloudformation
aws-cdk.aws-codepipeline
aws-cdk.aws-codepipeline-actions
aws-cdk.aws-ecr
aws-cdk.aws-ecr-assets
aws-cdk.aws-s3
aws-cdk.aws-s3-assets

aws-cdk.aws-sqs
aws-cdk.aws-ssm

aws-cdk.core
aws-cdk.cx-api
aws-cdk.region-info

0 comments on commit ffda295

Please sign in to comment.