[CloudFormation] Automating API deployment of API Gateway (Part 2)

[CloudFormation] Automating API deployment of API Gateway (Part 2)

Understanding each component in API Gateway deployment via AWSCLI

ยท

4 min read

Previously...

In my previous article, I wanted to test if I can deploy API Gateway solely through CloudFormation.

While it seems possible, it will become increasingly difficult to maintain. This is due to the constant updating of CloudFormation stacks, by adding news resources differentiated with unique identifiers or timestamps. I share similar sentiments to what is discussed in this Stack Overflow post

Today's Objective

In this article, I will explore the steps required to programmatically provision an API Gateway and create deployments to it via awscli and shell scripting.

TL;DR

  1. This article covers the list of awscli commands required to provision and deploy API to AWS API Gateway.

  2. Note that jq and awscli need to be installed before running the commands below. You can save them into a script file to run them all at once.

#!/bin/bash
# Replace the filepath placeholder accordingly
export INITIAL_FILEPATH="fileb:///path/to/api.json"
export SUBSEQUENT_FILEPATH='fileb:///path/to/api-full.json'
export STAGE_NAME="dev"

# Provision API Gateway
## Store the response from creating REST API Gateway
APIGW=$(aws apigateway create-rest-api --name "My REST API" --description "APIGW created by AWSCLI" --endpoint-configuration types=REGIONAL)

## Parse and filter for the rest-api-id
export REST_API_ID=$(echo $APIGW | jq -r '.id')

## Upload JSON file for initial set of available API
### Required to put 'fileb://' + '/path/to/api.json', 3 slashes in front is as intended
aws apigateway put-rest-api --rest-api-id $REST_API_ID --body "$INITIAL_FILEPATH"

## Create 1st deployment & filter for the deployment id
FIRST_DEPLOYMENT_RESPONSE=$(aws apigateway create-deployment --rest-api-id $REST_API_ID --description 'First deployment to the dev stage')
DEPLOYMENT_ID=$(echo $FIRST_DEPLOYMENT_RESPONSE | jq -r '.id')

## Create new stage and push deployment

DEV_STAGE=$(aws apigateway create-stage --rest-api-id $REST_API_ID --stage-name "$STAGE_NAME" --deployment-id $DEPLOYMENT_ID)

# Subsequent Deployments
## Similar to step 3, upload API
aws apigateway put-rest-api --rest-api-id $REST_API_ID --body "$FILEPATH"

## Create a new deployment and push to existing stages
SECOND_DEPLOYMENT=$(aws apigateway create-deployment --rest-api-id $REST_API_ID --stage-name "$STAGE_NAME" --description "Second deployment to dev stage")

Walkthrough

1. Create API Gateway (APIGW)

A regional API Gateway will be created. A rest-api-id will be generated as the APIGW's identifier.

# Store the response from creating REST API Gateway
APIGW=$(aws apigateway create-rest-api --name "My REST API" --description "APIGW created by AWSCLI" --endpoint-configuration types=REGIONAL)

# Parse and filter for the rest-api-id
export REST_API_ID=$(echo $APIGW | jq -r '.id')

2. Check for existing deployments

The command below is used to check for all deployments for the target API Gateway. As the APIGW is new, there will be no deployments.

aws apigateway get-deployments --rest-api-id $REST_API_ID

# Ouput will be empty since it's a new API Gateway
{
    "items": []
}

3. Provision Initial Resources

If import is used, a new separate API Gateway default to Edge endpoint will be created instead.

By uploading methods in the form of a OpenSwagger API JSON file, it would be the equivalent of manually creating the resources in the APIGW.

# For convenience, the filepath to the API JSON file is stored into a variable
FILEPATH="fileb:///path/to/api.json"

# Required to put 'fileb://' + '/path/to/api.json', 3 slashes in front is as intended
aws apigateway put-rest-api --rest-api-id $REST_API_ID --body "$FILEPATH"

4. Create a new deployment

A JSON response will be returned along with the deployment ID to be deployed into a stage.

# Create the first deployment
FIRST_DEPLOYMENT_RESPONSE=$(aws apigateway create-deployment --rest-api-id $REST_API_ID --description 'First deployment to the dev stage')

# Sample JSON response
{
    "id": "<SAMPLE_DEPLOYMENT_ID>",
    "description": "First deployment to the dev stage",
    "createdDate": "2022-07-31T14:57:16+08:00"
}

# Filter for deployment ID
DEPLOYMENT_ID=$(echo $FIRST_DEPLOYMENT_RESPONSE | jq -r '.id')

5. Create a new stage for the first deployment.

Upon deploying the deployment into the stage, the APIGW will receive the latest changes to the API.

export STAGE_NAME="dev"
DEV_STAGE=$(aws apigateway create-stage --rest-api-id $REST_API_ID --stage-name "$STAGE_NAME" --deployment-id $DEPLOYMENT_ID)

# Sample JSON Response
{
    "deploymentId": "<DEPLOYMENT_ID>",
    "stageName": "dev",
    "cacheClusterEnabled": false,
    "cacheClusterStatus": "NOT_AVAILABLE",
    "methodSettings": {},
    "tracingEnabled": false,
    "createdDate": "2022-07-31T15:07:06+08:00",
    "lastUpdatedDate": "2022-07-31T15:07:06+08:00"
}

6. Subsequent deployment

Upload a subsequent required new OpenSwagger JSON file into a variable for the next deployment

FILEPATH='fileb:///path/to/api-full.json'
# Similar to step 3, upload API
aws apigateway put-rest-api --rest-api-id $REST_API_ID --body "$FILEPATH"

# Create a new deployment
SECOND_DEPLOYMENT=$(aws apigateway create-deployment --rest-api-id $REST_API_ID --stage-name "$STAGE_NAME" --description "Second deployment to dev stage")

Conclusion

By trying out the commands, I believe I will be able to create a Lambda-backed custom resource for automating the API Gateway deployment within CloudFormation stack.

Keep a look out for that! Cheers

Did you find this article valuable?

Support Bernice Choy by becoming a sponsor. Any amount is appreciated!

ย