Commit 2ff886bf authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

doc: add serverless example

parent 8f41f29c
Loading
Loading
Loading
Loading
+114 −9
Original line number Diff line number Diff line
@@ -272,42 +272,46 @@ stages:
  - production
```

#### hook scripts
#### AWS scripts

##### `aws-deploy.sh`

This script is executed by the template to perform the application(s) deployment based on `aws` CLI, and uses dynamic variables provided by the template.
This script is executed by the template to perform the application(s) deployment based on `aws` CLI, and uses [dynamic variables](#dynamic-variables) provided by the template (`${appname}` is used as the CloudFormation stack name).

It implements [dynamic environment URLs](#static-vs-dynamic-environment-urls), by generating the `environment_url.txt` file, containing
the dynamically generated url at the end of the deployment script.

```bash
#!/usr/bin/env bash
set -e # fail on error

echo "[aws-deploy] Deploying $appname..."

# disable AWS CLI pager
export AWS_PAGER=""

template_file=file://MyStack.template
# retrieve environment type ($env) from template
# retrieve $AWS_KEYPAIR_NAME from project secret variables
params_opts="--parameters ParameterKey=EnvType,ParameterValue=$env ParameterKey=KeyName,ParameterValue=$AWS_KEYPAIR_NAME"

if aws cloudformation describe-stacks --output text --no-cli-pager --stack-name "$appname" > /dev/null
if aws cloudformation describe-stacks --output text --stack-name "$appname" > /dev/null
then
  echo -e "Stack exists: update..."
  aws cloudformation update-stack --output text --no-cli-pager --stack-name "$appname" --template-body $template_file $parameters
  aws cloudformation update-stack --output text --stack-name "$appname" --template-body $template_file $parameters

  echo "Waiting for stack to be updated..."
  aws cloudformation wait stack-update-complete --stack-name "$appname"
else
  echo -e "Stack doesn't exist: create..."
  aws cloudformation create-stack --output text --no-cli-pager --stack-name "$appname" --template-body $template_file $parameters
  aws cloudformation create-stack --output text --stack-name "$appname" --template-body $template_file $parameters
  
  echo "Waiting for stack to be created..."
  aws cloudformation wait stack-create-complete --stack-name "$appname"
fi

# Retrieve outputs (use a Python script as jq is not installed in the AWS CLI Docker image)
desc_json=$(aws cloudformation describe-stacks --output json --no-cli-pager --stack-name "$appname")
webserver_url=$(echo "$desc_json" | python -c 'import json,sys;desc=json.load(sys.stdin);outputs=desc["Stacks"][0]["Outputs"];print filter(lambda o: o["OutputKey"] == "WebServerUrl", outputs)[0]["OutputValue"]')
# Retrieve outputs (use cloudformation query)
webserver_url=$(aws cloudformation describe-stacks --output text --stack-name "$appname" --query 'Stacks[0].Outputs[?OutputKey==`WebServerUrl`].OutputValue')

echo "Stack created/updated:"
echo " - WebServerUrl: $webserver_url"
@@ -322,7 +326,108 @@ This script is executed by the template to perform the application(s) cleanup ba

```bash
#!/usr/bin/env bash
set -e # fail on error

echo "[aws-cleanup] Cleanup $appname..."

# disable AWS CLI pager
export AWS_PAGER=""

aws cloudformation delete-stack --stack-name "$appname"
```


### AWS Serverless

This chapter gives some implementation hints to implement continuous deployment of a Serverless application based on [Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/).

It enables review, staging and production environments.

#### `.gitlab-ci.yml`

```yaml
include:
  # Include AWS template
  - project: 'to-be-continuous/aws'
    ref: '1.0.1'
    file: '/templates/gitlab-ci-aws.yml'
  ...

# Global variables
variables:
  # AWS
  # use an image with both aws and sam CLI
  AWS_CLI_IMAGE: "pahud/aws-sam-cli:latest"
  # AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY defined as secret CI/CD variable
  AWS_REVIEW_ENABLED: "true" # enable review env
  AWS_STAGING_ENABLED: "true" # enable staging env
  AWS_PROD_ENABLED: "true" # enable production env
  ...

# Pipeline steps
stages:
  - build
  - test
  - deploy
  - acceptance
  - publish
  - production
```

#### AWS scripts

##### `aws-deploy.sh`

This script is executed by the template to perform the application(s) deployment based on `sam`and `aws` CLI, and uses [dynamic variables](#dynamic-variables) provided by the template (`${appname}` is used as the SAM/CloudFormation stack name).

It implements [dynamic environment URLs](#static-vs-dynamic-environment-urls), by generating the `environment_url.txt` file, containing
the dynamically generated url at the end of the deployment script.

```bash
#!/usr/bin/env bash
set -e # fail on error

echo "[aws-deploy] Deploy $appname..."

# disable AWS CLI pager
export AWS_PAGER=""

# 1: build
sam build ${TRACE+--debug}

# 2: deploy (each environment is a separate stack)
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY defined as secret CI/CD variable
# AWS_DEFAULT_REGION and AWS_SAM_BUCKET defined as project CI/CD variable
sam deploy ${TRACE+--debug} \
  --stack-name "$appname" \
  --region "$AWS_DEFAULT_REGION" \
  --s3-bucket "$AWS_SAM_BUCKET" \
  --no-fail-on-empty-changeset \
  --no-confirm-changeset \
  --tags "ci-job-url=$CI_JOB_URL environment=$env"

# Retrieve outputs (use cloudformation query)
api_url=$(aws cloudformation describe-stacks --stack-name "$appname" --output text --query 'Stacks[0].Outputs[?OutputKey==`MyProjectApiUrl`].OutputValue')

echo "Stack created/updated:"
echo " - Api URL: $api_url"

# Finally set the dynamically generated WebServer Url
echo "$api_url" > environment_url.txt
```

##### `aws-cleanup.sh`

This script is executed by the template to perform the application(s) cleanup based on `aws` CLI (review env only).

```bash
#!/usr/bin/env bash
set -e # fail on error

echo "[aws-cleanup] Cleanup $appname..."

aws cloudformation delete-stack --stack-name "$appname" || echo "delete stack failed"
# disable AWS CLI pager
export AWS_PAGER=""

aws cloudformation delete-stack --stack-name "$appname"
```