/amplify2terraform

Proof-of-concept for replacing Amplify CLI with Terraform & Serverless

Primary LanguageHCLMIT LicenseMIT

amplify2terraform

This repo is a proof-of-concept for using Amplify client libraries with Terraform (and serverless for Lambda functions) rather than Amplify CLI and Console.

See my blog for an explanation of why: https://tommygroshong.com/posts/appsync-cognito-cloudfront/

Prereqs

Install the following tools:

Setup AWS API credentials: aws configure

Build

The build workflow is as follows:

  • Terraform infrastructure:
    • cd terraform
    • terraform init (only needed the first time)
    • terraform apply
  • Deploy serverless function:
    • cd serverless
    • serverless deploy -v
  • Build and push react app:
    • terraform output -state=terraform/terraform.tfstate aws-exports-file > src/aws-exports.js
    • yarn build
    • aws s3 sync build s3://<YOURBUCKET> --cache-control max-age=300

Overview

Infrastructure

My terraform scripts are in terraform/ and the resources are organized thusly:

  1. main.tf: Variables, Outputs, and Data resources
  2. api.tf: DynamoDB; AppSync API, Data Sources, and Resolvers; IAM perms
  3. auth.tf: Cognito Identity Pool, User Pool, User Groups, Clients, and IAM roles
  4. website.tf: S3 website bucket, CloudFront distribution, Route 53 Record

Serverless functions are in services/. The code is just a dummy example. The serverless.yml however shows a few useful examples:

  1. Giving access to DynamoDB tables
  2. Outputting your function ARNs so you can plug them into terraform as variables

When using these scripts in a non-toy app, I create multiple terraform workspaces and separate <stage>.tfvars files for use with each. Not beautiful, but works.

Client

The client app was bootstrapped with Create React App.

It uses the AppSyncClientSDK which is an Apollo compatible client; just pass it to your provider: <ApolloProvider client={client} />.

The pattern that Amplify and AppSync give you for configuring the Clients is having a src/aws-exports.js file that is ignored from git and contains all your configuration details for AppSync, Cognito, etc. My code does the same pattern except uses terraform to generate that file:

terraform output aws-exports-file > ../src/aws-exports.js

That was a trick I picked up for generating Kubeconfig files after setting up Kubernetes. So after creating your infrastructure with terraform, you should generate the latest aws-exports.js file.

NOTE: Generate the latest aws-exports.js file for your target stage before bundling code!

Your bundled code will essentially be hardcoded to point at whatever stage/environment was referenced by aws-exports.js at the time of bundling. Notice in the instructions above on how to build and push react app it has you write the src/aws-exports.js first. Those few lines are should go in a deploy script.