Skip to content

Commit 1aa7d7c

Browse files
authored
Merge pull request #1 from kirankumar15/development
initial commit
2 parents 3f2fb43 + 30c8c5f commit 1aa7d7c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1287
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store

README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
## My Project
1+
## Build Efficient CI/CD Pipelines for Connected Microservices in Under an Hour using AWS Copilot
22

3-
TODO: Fill this README out!
4-
5-
Be sure to:
6-
7-
* Change the title in this README
8-
* Edit your repository description on GitHub
3+
Sample code repo to Build Efficient CI/CD Pipelines for Connected Microservices in Under an Hour using AWS Copilot. It forms the base of the following tutorials:
4+
* [Build CI/CD Pipelines For Connected Microservices using Copilot](https://buildon.aws/tutorials/Build-ci-cd-pipelines-for-connected-microservices-using-copilot)
95

106
## Security
117

code/backend/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM public.ecr.aws/bitnami/python:3.9
2+
WORKDIR /app
3+
COPY requirements.txt requirements.txt
4+
RUN pip3 install -r requirements.txt
5+
COPY app.py app.py
6+
EXPOSE 10000
7+
CMD ["python3", "app.py"]

code/backend/app.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from flask import Flask, jsonify, request
2+
import json
3+
from flask_expects_json import expects_json
4+
import boto3
5+
import os
6+
7+
table_name = os.getenv('TODOTABLE_NAME')
8+
dynamodb = boto3.resource('dynamodb')
9+
table = dynamodb.Table(table_name)
10+
11+
app = Flask(__name__)
12+
13+
schema = {
14+
'type': 'object',
15+
'properties': {
16+
'id': {'type': 'number'},
17+
'title': {'type': 'string'},
18+
'done': {'type': 'string'}
19+
},
20+
'required': ['id', 'title', 'done']
21+
}
22+
23+
24+
@app.route('/')
25+
def hello_world():
26+
return jsonify({'message': 'Hello, again'})
27+
28+
29+
@app.route('/ishealthy')
30+
def receive_health_check():
31+
return "Health check succeed\n"
32+
33+
34+
@app.route('/createtodo', methods=["POST", "OPTIONS"])
35+
@expects_json(schema, force=False)
36+
def create_todo():
37+
if request.method == 'OPTIONS':
38+
return "Endpoint Hit: createTodo method = OPTIONS\n"
39+
elif request.method == 'POST':
40+
params = request.get_json()
41+
item = {
42+
'TodoId': params['id'],
43+
'title': params['title'],
44+
'done': params['done']
45+
}
46+
table.put_item(Item=item)
47+
return "Endpoint Hit: createTodo and POST method and parameters is valid\n"
48+
49+
50+
def convert_from_response(item):
51+
todo = {
52+
'id': int(item['TodoId']),
53+
'title': item['title'],
54+
'done': item['done']
55+
}
56+
return todo
57+
58+
59+
@app.route('/alltodo')
60+
def get_alltodo():
61+
response = table.scan()
62+
items = response['Items']
63+
items = list(map(convert_from_response, items))
64+
items = json.dumps(items)
65+
return items
66+
67+
68+
@app.route('/updatetodo/<path:todoid>', methods=['POST', 'OPTIONS'])
69+
def update_todo(todoid):
70+
if request.method == 'OPTIONS':
71+
return "Endpoint Hit: createTodo method = OPTIONS\n"
72+
elif request.method == 'POST':
73+
params = request.get_json()
74+
table.update_item(
75+
Key={'TodoId': todoid},
76+
UpdateExpression="SET title=:title, done=:done",
77+
ExpressionAttributeValues={
78+
":title": params['title'],
79+
":done": params['done']
80+
}
81+
)
82+
return "Updated todo\n"
83+
84+
85+
@app.route('/deletetodo/<path:todoid>')
86+
def delete_todo(todoid):
87+
table.delete_item(
88+
Key={'TodoId': int(todoid)}
89+
)
90+
return "Deleted todo\n"
91+
92+
93+
@app.route('/createtable')
94+
def create_table():
95+
return "createtable called (nothing to do)\n"
96+
97+
98+
@app.route('/deletetable')
99+
def delete_table():
100+
return "deletetable called (nothing to do)\n"
101+
102+
103+
if __name__ == '__main__':
104+
app.run(debug=False, host='0.0.0.0', port=10000)

code/backend/manifests/.workspace

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
application: todo
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
Parameters:
2+
App:
3+
Type: String
4+
Description: Your application's name.
5+
Env:
6+
Type: String
7+
Description: The environment name your service, job, or workflow is being deployed to.
8+
Name:
9+
Type: String
10+
Description: The name of the service, job, or workflow being deployed.
11+
Resources:
12+
todotable:
13+
Metadata:
14+
'aws:copilot:description': 'An Amazon DynamoDB table for todotable'
15+
Type: AWS::DynamoDB::Table
16+
Properties:
17+
TableName: !Sub ${App}-${Env}-${Name}-todotable
18+
AttributeDefinitions:
19+
- AttributeName: TodoId
20+
AttributeType: "N"
21+
BillingMode: PAY_PER_REQUEST
22+
KeySchema:
23+
- AttributeName: TodoId
24+
KeyType: HASH
25+
26+
todotableAccessPolicy:
27+
Metadata:
28+
'aws:copilot:description': 'An IAM ManagedPolicy for your service to access the todotable db'
29+
Type: AWS::IAM::ManagedPolicy
30+
Properties:
31+
Description: !Sub
32+
- Grants CRUD access to the Dynamo DB table ${Table}
33+
- { Table: !Ref todotable }
34+
PolicyDocument:
35+
Version: '2012-10-17'
36+
Statement:
37+
- Sid: DDBActions
38+
Effect: Allow
39+
Action:
40+
- dynamodb:BatchGet*
41+
- dynamodb:DescribeStream
42+
- dynamodb:DescribeTable
43+
- dynamodb:Get*
44+
- dynamodb:Query
45+
- dynamodb:Scan
46+
- dynamodb:BatchWrite*
47+
- dynamodb:Create*
48+
- dynamodb:Delete*
49+
- dynamodb:Update*
50+
- dynamodb:PutItem
51+
Resource: !Sub ${ todotable.Arn}
52+
- Sid: DDBLSIActions
53+
Action:
54+
- dynamodb:Query
55+
- dynamodb:Scan
56+
Effect: Allow
57+
Resource: !Sub ${ todotable.Arn}/index/*
58+
59+
Outputs:
60+
todotableName:
61+
Description: "The name of this DynamoDB."
62+
Value: !Ref todotable
63+
todotableAccessPolicy:
64+
Description: "The IAM::ManagedPolicy to attach to the task role."
65+
Value: !Ref todotableAccessPolicy
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# The manifest for the "backend" service.
2+
# Read the full specification for the "Backend Service" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/backend-service/
4+
5+
# Your service name will be used in naming your resources like log groups, ECS services, etc.
6+
name: backend
7+
type: Backend Service
8+
9+
# Your service is reachable at "http://backend.${COPILOT_SERVICE_DISCOVERY_ENDPOINT}:10000" but is not public.
10+
11+
# Configuration for your containers and service.
12+
image:
13+
# Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/backend-service/#image-build
14+
build: Dockerfile
15+
# Port exposed through your container to route traffic to it.
16+
port: 10000
17+
healthcheck:
18+
command: ["CMD-SHELL", "curl -f http://localhost:10000/ishealthy || exit 1"]
19+
interval: 10s
20+
retries: 2
21+
timeout: 6s
22+
start_period: 10s
23+
24+
cpu: 256 # Number of CPU units for the task.
25+
memory: 512 # Amount of memory in MiB used by the task.
26+
count: 1 # Number of tasks that should be running in your service.
27+
exec: true # Enable running commands in your container.
28+
network:
29+
connect: true # Enable Service Connect for intra-environment traffic between services.
30+
31+
# storage:
32+
# readonly_fs: true # Limit to read-only access to mounted root filesystems.
33+
34+
# Optional fields for more advanced use-cases.
35+
#
36+
#variables: # Pass environment variables as key value pairs.
37+
# LOG_LEVEL: info
38+
39+
#secrets: # Pass secrets from AWS Systems Manager (SSM) Parameter Store.
40+
# GITHUB_TOKEN: GITHUB_TOKEN # The key is the name of the environment variable, the value is the name of the SSM parameter.
41+
42+
# You can override any of the values defined above by environment.
43+
#environments:
44+
# test:
45+
# count: 2 # Number of tasks to run for the "test" environment.
46+
# deployment: # The deployment strategy for the "test" environment.
47+
# rolling: 'recreate' # Stops existing tasks before new ones are started for faster deployments.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# The manifest for the "development" environment.
2+
# Read the full specification for the "Environment" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/environment/
4+
5+
# Your environment name will be used in naming your resources like VPC, cluster, etc.
6+
name: development
7+
type: Environment
8+
9+
# Import your own VPC and subnets or configure how they should be created.
10+
# network:
11+
# vpc:
12+
# id:
13+
14+
# Configure the load balancers in your environment, once created.
15+
# http:
16+
# public:
17+
# private:
18+
19+
# Configure observability for your environment resources.
20+
observability:
21+
container_insights: false
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Buildspec runs in the build stage of your pipeline.
2+
version: 0.2
3+
phases:
4+
install:
5+
runtime-versions:
6+
docker: 20
7+
ruby: 3.1
8+
nodejs: 16
9+
commands:
10+
- echo "cd into $CODEBUILD_SRC_DIR"
11+
- cd $CODEBUILD_SRC_DIR
12+
# Download the copilot linux binary.
13+
- wget -q https://ecs-cli-v2-release.s3.amazonaws.com/copilot-linux-v1.27.0
14+
- mv ./copilot-linux-v1.27.0 ./copilot-linux
15+
- chmod +x ./copilot-linux
16+
build:
17+
commands:
18+
- echo "Run your tests"
19+
# - make test
20+
post_build:
21+
commands:
22+
- ls -l
23+
- export COLOR="false"
24+
- pipeline=$(cat $CODEBUILD_SRC_DIR/copilot/pipelines/todobackend-main/manifest.yml | ruby -ryaml -rjson -e 'puts JSON.pretty_generate(YAML.load(ARGF))')
25+
- pl_envs=$(echo $pipeline | jq -r '.stages[].name')
26+
# Find all the local services in the workspace.
27+
- svc_ls_result=$(./copilot-linux svc ls --local --json)
28+
- svc_list=$(echo $svc_ls_result | jq '.services')
29+
- >
30+
if [ ! "$svc_list" = null ]; then
31+
svcs=$(echo $svc_ls_result | jq -r '.services[].name');
32+
fi
33+
# Find all the local jobs in the workspace.
34+
- job_ls_result=$(./copilot-linux job ls --local --json)
35+
- job_list=$(echo $job_ls_result | jq '.jobs')
36+
- >
37+
if [ ! "$job_list" = null ]; then
38+
jobs=$(echo $job_ls_result | jq -r '.jobs[].name');
39+
fi
40+
# Raise error if no services or jobs are found.
41+
- >
42+
if [ "$svc_list" = null ] && [ "$job_list" = null ]; then
43+
echo "No services or jobs found for the pipeline to deploy. Please create at least one service or job and push the manifest to the remote." 1>&2;
44+
exit 1;
45+
fi
46+
# Generate the cloudformation templates.
47+
# The tag is the build ID but we replaced the colon ':' with a dash '-'.
48+
# We truncate the tag (from the front) to 128 characters, the limit for Docker tags
49+
# (https://docs.docker.com/engine/reference/commandline/tag/)
50+
# Check if the `svc package` commanded exited with a non-zero status. If so, echo error msg and exit.
51+
- >
52+
for env in $pl_envs; do
53+
tag=$(echo ${CODEBUILD_BUILD_ID##*:}-$env | sed 's/:/-/g' | rev | cut -c 1-128 | rev)
54+
for svc in $svcs; do
55+
./copilot-linux svc package -n $svc -e $env --output-dir './infrastructure' --tag $tag --upload-assets;
56+
if [ $? -ne 0 ]; then
57+
echo "Cloudformation stack and config files were not generated. Please check build logs to see if there was a manifest validation error." 1>&2;
58+
exit 1;
59+
fi
60+
done;
61+
for job in $jobs; do
62+
./copilot-linux job package -n $job -e $env --output-dir './infrastructure' --tag $tag --upload-assets;
63+
if [ $? -ne 0 ]; then
64+
echo "Cloudformation stack and config files were not generated. Please check build logs to see if there was a manifest validation error." 1>&2;
65+
exit 1;
66+
fi
67+
done;
68+
done;
69+
- ls -lah ./infrastructure
70+
artifacts:
71+
files:
72+
- "infrastructure/*"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# The manifest for the "todobackend-main" pipeline.
2+
# This YAML file defines your pipeline: the source repository it tracks and the order of the environments to deploy to.
3+
# For more info: https://aws.github.io/copilot-cli/docs/manifest/pipeline/
4+
5+
# The name of the pipeline.
6+
name: todobackend-main
7+
8+
# The version of the schema used in this template.
9+
version: 1
10+
11+
# This section defines your source, changes to which trigger your pipeline.
12+
source:
13+
# The name of the provider that is used to store the source artifacts.
14+
# (i.e. GitHub, Bitbucket, CodeCommit)
15+
provider: CodeCommit
16+
# Additional properties that further specify the location of the artifacts.
17+
properties:
18+
branch: main
19+
repository: https://us-east-1.console.aws.amazon.com/codesuite/codecommit/repositories/todobackend/browse
20+
21+
# This section defines the order of the environments your pipeline will deploy to.
22+
stages:
23+
- # The name of the environment.
24+
name: development
25+
# Optional: flag for manual approval action before deployment.
26+
# requires_approval: true
27+
# Optional: use test commands to validate this stage of your build.
28+
# test_commands: [echo 'running tests', make test]
29+

0 commit comments

Comments
 (0)