Introduction
Hello everyone! I want to share my experience of exploring AWS CDK. I want to deploy AWS AppSync and Amazon DynamoDB. Let's learn with me.
Background
I used Terraform for provisioning the resources into Heroku. Heroku announced that they will stop the free plan, so I want to move my resources into AWS. I learned AWS SDK 3 months ago, but got stuck. I hope this post will help you.
Preparation
- Install Node.js
- Install AWS CDK Toolkit. Command:
npm install -g aws-cdk
. More informations. - If you want to generate a new project. You can use
cdk init app --language csharp
. More informations.
Update the Stack
I want simple architecture. You can see my architecture below.
- I have GraphQL schema like this:
type Experience {
id: ID!
title: String!
}
input ExperienceInput {
title: String!
}
input UpdateExperienceInput {
id: ID!
title: String
}
type Query {
getExperienceById(experienceId: String!): Experience
getExperiences: [Experience]
}
type Mutation {
addExperience(input: ExperienceInput!): Experience
updateExperience(input: UpdateExperienceInput!): Experience
deleteExperience(experienceId: String!): String
}
Our schema only has simple CRUD and store experience data. The experience data has id and title only. You can extend more columns on it, but take note you will need to update the CDK code too.
- My CDK stacks look like this:
using Amazon.CDK;
using Amazon.CDK.AWS.AppSync.Alpha;
using Amazon.CDK.AWS.DynamoDB;
using Amazon.CDK.AWS.IAM;
using Constructs;
namespace MyPersonalWebApiInfra
{
public class MyPersonalWebApiInfraStack : Stack
{
internal MyPersonalWebApiInfraStack(Construct scope, string id, IStackProps props = null) : base(scope, id,
props)
{
// AppSync
var api = new GraphqlApi(this, "api", new GraphqlApiProps
{
Name = "berv-api",
Schema = Schema.FromAsset("schema.graphql"),
XrayEnabled = true,
});
// Dynamo DB
var experienceTable = new Table(this, "berv-experiences", new TableProps
{
BillingMode = BillingMode.PAY_PER_REQUEST,
PartitionKey = new Attribute
{
Name = "id",
Type = AttributeType.STRING
},
});
// IAM Role
var role = new Role(this, "Role", new RoleProps
{
AssumedBy = new ServicePrincipal("lambda.amazonaws.com")
});
// AppSync apply IAM to some mutations
api.GrantMutation(role, "addExperience");
api.GrantMutation(role, "updateExperience");
api.GrantMutation(role, "deleteExperience");
// Add Dynamo DB as DataSource of AppSync
var dataSource = api.AddDynamoDbDataSource("experience", experienceTable);
// Add Resolver for Get All Experiences
dataSource.CreateResolver(new BaseResolverProps
{
TypeName = "Query",
FieldName = "getExperiences",
RequestMappingTemplate = MappingTemplate.DynamoDbScanTable(),
ResponseMappingTemplate = MappingTemplate.DynamoDbResultList(),
});
// Add Resolver for Get Experience by Id
dataSource.CreateResolver(new BaseResolverProps
{
TypeName = "Query",
FieldName = "getExperienceById",
RequestMappingTemplate = MappingTemplate.DynamoDbGetItem("id", "experienceId"),
ResponseMappingTemplate = MappingTemplate.DynamoDbResultItem(),
});
// Add Resolver for Create Experience
dataSource.CreateResolver(new BaseResolverProps
{
TypeName = "Mutation",
FieldName = "addExperience",
RequestMappingTemplate =
MappingTemplate.DynamoDbPutItem(PrimaryKey.Partition("id").Auto(), Values.Projecting("input")),
ResponseMappingTemplate = MappingTemplate.DynamoDbResultItem()
});
// Add Resolver for Update an Experience
dataSource.CreateResolver(new BaseResolverProps
{
TypeName = "Mutation",
FieldName = "updateExperience",
RequestMappingTemplate = MappingTemplate.FromString("""
{
"version" : "2017-02-28",
"operation" : "PutItem",
"key": {
"id" : $util.dynamodb.toDynamoDBJson($ctx.args.input.id),
},
"attributeValues" : {
"title" : $util.dynamodb.toDynamoDBJson($ctx.args.input.title)
}
}
"""),
ResponseMappingTemplate = MappingTemplate.DynamoDbResultItem()
});
// Add Resolver for Delete an Experience
dataSource.CreateResolver(new BaseResolverProps
{
TypeName = "Mutation",
FieldName = "deleteExperience",
RequestMappingTemplate = MappingTemplate.DynamoDbDeleteItem("id", "experienceId"),
ResponseMappingTemplate = MappingTemplate.FromString("$util.toJson($ctx.result)")
});
}
}
}
I didn't have enough information on the best way to map the Update Request. Please feel free to give feedback about it. Anyway, visit this repository for the complete project.
bervProject / my-personal-web-api-infra
Infrastructure as Code for My Personal Web API
Welcome to your CDK C# project!
This is a blank project for CDK development with C#.
The cdk.json
file tells the CDK Toolkit how to execute your app.
It uses the .NET Core CLI to compile and execute your project.
Useful commands
-
dotnet build src
compile this app -
cdk deploy
deploy this stack to your default AWS account/region -
cdk diff
compare deployed stack with current state -
cdk synth
emits the synthesized CloudFormation template
Deploying and Testing
- You can deploy the app using
cdk deploy
. Please make sure you've set up the account in your environment. If you're not sure, please check here. - Let's test our AppSync using in-browser tools provided by AppSync. You can click
Run a query
button.
- Test Create
- Test Update
- Test Get Experiences
- Test Get Experience by Id
- Test Delete
Top comments (0)