Last active
March 4, 2021 01:26
-
-
Save tlakomy/f1312ec1fd092ece75a0f72403235fc8 to your computer and use it in GitHub Desktop.
Revisions
-
Tomasz Łakomy revised this gist
Apr 6, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -678,7 +678,7 @@ headers: { ``` new s3Deployment.BucketDeployment(this, "DeployWebsite", { sources: [s3Deployment.Source.asset("../frontend/build")], destinationBucket: websiteBucket }); ``` -
Tomasz Łakomy revised this gist
Apr 6, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -678,7 +678,7 @@ headers: { ``` new s3Deployment.BucketDeployment(this, "DeployWebsite", { sources: [s3Deployment.Source.asset("../../frontend/build")], destinationBucket: websiteBucket }); ``` -
Tomasz Łakomy revised this gist
Apr 5, 2020 . 1 changed file with 17 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -486,6 +486,23 @@ const addTodoItem = async (data: { todo: string; id: string }) => { } return todo; }; const deleteTodoItem = async (data: { id: string }) => { const { id } = data; if (id && id !== "") { await dynamo .delete({ TableName: tableName, Key: { id } }) .promise(); } return id; }; ``` - Go to the lambda directory and run `npm init` to create a `package.json` and install `uuid` package -
Tomasz Łakomy revised this gist
Apr 5, 2020 . 1 changed file with 15 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -328,6 +328,21 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { }; ``` - Implement the `getAllTodos` function: ```js const getAllTodos = async () => { const scanResult = await dynamo .scan({ TableName: tableName }) .promise(); return scanResult; }; ``` - Deploy the `todoHandler.ts` function in the `TodoDatabase` stack ``` -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 47 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -445,16 +445,57 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct - Refactor the `todoHandler` function so it can handle both `GET` and `POST` requests, along with some error handling (notice that currently the id is **HARDCODED**): ``` const getAllTodos = async () => { const scanResult = await dynamo .scan({ TableName: tableName }) .promise(); return scanResult; }; const addTodoItem = async (data: { todo: string; id: string }) => { const { id, todo } = data; if (todo && todo !== "") { await dynamo .put({ TableName: tableName, Item: { id: "123", todo } }) .promise(); } return todo; }; ``` - Go to the lambda directory and run `npm init` to create a `package.json` and install `uuid` package - Modify the `POST` section of the lambda function to use the `uuid` package: ``` const uuid = require("uuid/v4"); ... ... const addTodoItem = async (data: { todo: string; id: string }) => { const { id, todo } = data; if (todo && todo !== "") { await dynamo .put({ TableName: tableName, Item: { id: id || uuid(), todo } }) .promise(); } return todo; }; ``` - At the end, our lambda function should look similar to this: -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 32 additions and 30 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -459,42 +459,42 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct - At the end, our lambda function should look similar to this: ``` /// <reference types="aws-sdk" /> import AWS = require("aws-sdk"); const uuid = require("uuid/v4"); const tableName = process.env.TABLE_NAME || ""; const dynamo = new AWS.DynamoDB.DocumentClient(); const createResponse = ( body: string | AWS.DynamoDB.DocumentClient.ItemList, statusCode = 200 ) => { return { statusCode, body: JSON.stringify(body, null, 2) }; }; const getAllTodos = async () => { const scanResult = await dynamo .scan({ TableName: tableName }) .promise(); return scanResult; }; const addTodoItem = async (data: { todo: string; id: string }) => { const { id, todo } = data; if (todo && todo !== "") { await dynamo .put({ TableName: tableName, Item: { id: id || uuid(), todo } }) .promise(); @@ -504,12 +504,13 @@ const addTodoItem = async (data: { todo: string; id: string }) => { const deleteTodoItem = async (data: { id: string }) => { const { id } = data; if (id && id !== "") { await dynamo .delete({ TableName: tableName, Key: { id } }) .promise(); @@ -523,13 +524,13 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { const { httpMethod, body: requestBody } = event; if (httpMethod === "GET") { const response = await getAllTodos(); return createResponse(response.Items || []); } if (!requestBody) { return createResponse("Missing request body", 500); } const data = JSON.parse(requestBody); @@ -538,7 +539,7 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { const todo = await addTodoItem(data); return todo ? createResponse(`${todo} added to the database`) : createResponse("Todo is missing", 500); } if (httpMethod === "DELETE") { @@ -547,15 +548,16 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { ? createResponse( `Todo item with an id of ${id} deleted from the database` ) : createResponse("ID is missing", 500); } return createResponse( `We only accept GET, POST, OPTIONS and DELETE, not ${httpMethod}`, 500 ); } catch (error) { console.log(error); return createResponse(error, 500); } }; ``` -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -344,7 +344,7 @@ export class TodoDatabase extends cdk.Construct { }); new lambda.Function(this, "TodoHandler", { code: lambda.Code.fromAsset("lesson_07/lambda"), handler: "todoHandler.handler", runtime: lambda.Runtime.NODEJS_12_X, environment: { @@ -373,7 +373,7 @@ export class TodoDatabase extends cdk.Construct { }); this.handler = new lambda.Function(this, "TodoHandler", { code: lambda.Code.fromAsset("lesson_07/lambda"), handler: "todoHandler.handler", runtime: lambda.Runtime.NODEJS_12_X, environment: { -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 20 additions and 16 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -358,25 +358,29 @@ export class TodoDatabase extends cdk.Construct { afterwards we need to make the `todoHandler` available for modules importing this class: ``` import * as cdk from "@aws-cdk/core"; import * as dynamodb from "@aws-cdk/aws-dynamodb"; import * as lambda from "@aws-cdk/aws-lambda"; export class TodoDatabase extends cdk.Construct { public readonly handler: lambda.Function; constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id); const todosTable = new dynamodb.Table(this, "TodoTable", { partitionKey: { name: "id", type: dynamodb.AttributeType.STRING } }); this.handler = new lambda.Function(this, "TodoHandler", { code: lambda.Code.fromAsset("lambda"), handler: "todoHandler.handler", runtime: lambda.Runtime.NODEJS_12_X, environment: { TABLE_NAME: todosTable.tableName } }); } } ``` -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 18 additions and 22 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -331,28 +331,27 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { - Deploy the `todoHandler.ts` function in the `TodoDatabase` stack ``` import * as cdk from "@aws-cdk/core"; import * as dynamodb from "@aws-cdk/aws-dynamodb"; import * as lambda from "@aws-cdk/aws-lambda"; export class TodoDatabase extends cdk.Construct { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id); const todosTable = new dynamodb.Table(this, "TodoTable", { partitionKey: { name: "id", type: dynamodb.AttributeType.STRING } }); new lambda.Function(this, "TodoHandler", { code: lambda.Code.fromAsset("lambda"), handler: "todoHandler.handler", runtime: lambda.Runtime.NODEJS_12_X, environment: { TABLE_NAME: todosTable.tableName } }); } } ``` @@ -377,9 +376,6 @@ export class TodoAdder extends cdk.Construct { TODOS_TABLE_NAME: todosTable.tableName } }); } } ``` -
Tomasz Łakomy revised this gist
Mar 21, 2020 . 1 changed file with 41 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -286,7 +286,47 @@ Resources - Create a `todoHandler.ts` lambda function that for now is going to list all items from the table: ``` /// <reference types="aws-sdk" /> import AWS = require("aws-sdk"); const tableName = process.env.TABLE_NAME || ""; const dynamo = new AWS.DynamoDB.DocumentClient(); const createResponse = ( body: string | AWS.DynamoDB.DocumentClient.ItemList, statusCode = 200 ) => { return { statusCode, body: JSON.stringify(body, null, 2) }; }; const getAllTodos = async () => { // Implement me! // Check out https://github.com/dabit3/dynamodb-documentclient-cheat-sheet }; exports.handler = async function(event: AWSLambda.APIGatewayEvent) { try { const { httpMethod, body: requestBody } = event; if (httpMethod === "GET") { const response = await getAllTodos(); return createResponse(response.Items || []); } return createResponse( `We only accept GET requests for now, not ${httpMethod}`, 500 ); } catch (error) { console.log(error); return createResponse(error, 500); } }; ``` - Deploy the `todoHandler.ts` function in the `TodoDatabase` stack -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,8 @@ Create an AWS account, install AWS CLI, AWS CDK, AWS SAM (including Docker) and configure your account Hide `node_modules`, `**/*.d.ts` and `**/lesson*/**/*.js` files in VSCode using `Exclude` option in Settings ### Note - check the cdk-spa-deploy version before the workshop because if there's a version mismatch it won't work ## Workshop: -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -608,6 +608,10 @@ NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.a Build the app using AWS Amplify - as of 04.03.2020, I was unable to do that via CDK because it's still experimental # Part 11 **TESTING!** ## Endgame - Destroy the stack by running `cdk destroy` -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 15 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ ## Pre-workshop: Create an AWS account, install AWS CLI, AWS CDK, AWS SAM (including Docker) and configure your account ### Note - check the cdk-spa-deploy version before the workshop because if there's a version mismatch it won't work @@ -152,7 +152,21 @@ export class NewTodoAppStack extends cdk.Stack { **Execute a lambda function locally** - Compile your AWS CDK app and create a AWS CloudFormation template - First, run `npm run build` to compile the app - Run `cdk synth --no-staging > template.yaml` to create a CloudFormation template - Find the logical ID for your Lambda function in template.yaml. It will look like `MyFunction12345678`, where 12345678 represents an 8-character unique ID that the AWS CDK generates for all resources. The line right after it should look like: `Type: AWS::Lambda::Function` - Run the function by executing: `sam local invoke HelloLambda3D9C82D6` - We can also pass custom events to the function, to do that - take a look at `sample_events` directory, there's a sample `hello.json` event in there - To execute a lambda function locally with a custom event, execute: `sam local invoke HelloLambda3D9C82D6 -e sample_events/hello.json` ## Part 3 -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -148,6 +148,12 @@ export class NewTodoAppStack extends cdk.Stack { - Using env variables in lambda functions - Attaching API Gateway to a lambda function and creating a REST endpoint ## Part 2.5 **Execute a lambda function locally** ## Part 3 **Working with S3** @@ -584,6 +590,10 @@ NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.a - We don't have to do everything ourselves, we can use constructs made by community - If we want, we can create an entire CDN distribution without leaving our editor # Part 10 Build the app using AWS Amplify - as of 04.03.2020, I was unable to do that via CDK because it's still experimental ## Endgame - Destroy the stack by running `cdk destroy` -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 14 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -569,6 +569,20 @@ NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.a # Part 9 - use CDK-SPA-Deploy to avoid Re:Inventing (hah) the wheel: - Run `npm install --save cdk-spa-deploy` in `frontend` directory https://github.com/nideveloper/CDK-SPA-Deploy - CDK-SPA-Deploy can either deploy a `basic` site or a full CloudFront distribution. Deploying a new distribution takes ~10 minutes so stick to a basic site instead: ``` // Using the SPA Deploy construct from npm: new SPADeploy(this, "spaDeploy").createBasicSite({ indexDoc: "index.html", websiteFolder: "../frontend/build" }); ``` **What we've learned in this section:** - We don't have to do everything ourselves, we can use constructs made by community - If we want, we can create an entire CDN distribution without leaving our editor ## Endgame -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -561,15 +561,15 @@ NewTodoAppStack.WebsiteUrl = http://newtodoappstack-websitebucket75c24d94-sod2pi NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.amazonaws.com/prod/ ``` **What we've learned in this section:** - Creating a S3 Bucket deployment to host a static website - Creating a custom CloudFormation stack output # Part 9 - use CDK-SPA-Deploy to avoid Re:Inventing (hah) the wheel: - Run `npm install --save cdk-spa-deploy` in `frontend` directory https://github.com/nideveloper/CDK-SPA-Deploy ## Endgame - Destroy the stack by running `cdk destroy` -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,7 @@ Create an AWS account, install AWS CDK and configure your account ### Note - check the cdk-spa-deploy version before the workshop because if there's a version mismatch it won't work ## Workshop: -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,8 @@ Create an AWS account, install AWS CDK and configure your account # Note - check the cdk-spa-deploy before the workshop because if there's a version mismatch it won't work ## Workshop: ## Part 1 -
Tomasz Łakomy revised this gist
Mar 4, 2020 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -559,6 +559,10 @@ NewTodoAppStack.WebsiteUrl = http://newtodoappstack-websitebucket75c24d94-sod2pi NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.amazonaws.com/prod/ ``` # Part 9 - use CDK-SPA-Deploy to avoid Re:Inventing (hah) the wheel: - Run `npm install --save cdk-spa-deploy` in `frontend` directory **What we've learned in this section:** - Creating a S3 Bucket deployment to host a static website -
Tomasz Łakomy revised this gist
Feb 11, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -112,7 +112,7 @@ and `console.log` it in the lambda function: **But how do we call this function?** - Run `npm install @aws-cdk/aws-apigateway` - Add an API Gateway to our stack, so it looks like this: ``` import * as cdk from "@aws-cdk/core"; -
Tomasz Łakomy revised this gist
Feb 10, 2020 . 1 changed file with 85 additions and 162 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -262,28 +262,7 @@ Resources - Create a `todoHandler.ts` lambda function that for now is going to list all items from the table: **REWRITE THIS SECTION** - Deploy the `todoHandler.ts` function in the `TodoDatabase` stack @@ -401,175 +380,119 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct ## Part 6 - Adding and removing data from Todos DynamoDB table - Refactor the `todoHandler` function so it can handle both `GET` and `POST` requests, along with some error handling (notice that currently the id is **HARDCODED**): **REWRITE THIS SECTION** - Go to the lambda directory and run `npm init` to create a `package.json` and install `uuid` package - Modify the `POST` section of the lambda function to use the `uuid` package: **REWRITE THIS SECTION** - Add a `DELETE` handler so we'll be able to delete a todo item: **REWRITE THIS SECTION** - At the end, our lambda function should look similar to this: ``` const { DynamoDB } = require("aws-sdk"); const uuid = require("uuid"); const createResponse = (body: string, statusCode = 200) => { return { statusCode, headers: { "Content-Type": "text/plain", "Access-Control-Allow-Origin": "*" // Required for CORS support to work }, body: JSON.stringify(body, null, 2) }; }; const tableName = process.env.TABLE_NAME; const dynamo = new DynamoDB(); const getAlllTodos = async () => { const scanResult = await dynamo .scan({ "TableName": tableName, "Limit": 10 }) .promise(); return scanResult.Items.map(DynamoDB.Converter.unmarshall); }; const addTodoItem = async (data: { todo: string; id: string }) => { const { id, todo } = data; if (todo && todo !== "") { await dynamo .putItem({ "TableName": tableName, "Item": { id: { S: id || uuid() }, todo: { S: todo } } }) .promise(); } return todo; }; const deleteTodoItem = async (data: { id: string }) => { const { id } = data; if (id && id !== "") { await dynamo .deleteItem({ "TableName": tableName, "Key": { id: { S: id } } }) .promise(); } return id; }; exports.handler = async function(event: AWSLambda.APIGatewayEvent) { try { const { httpMethod, body: requestBody } = event; if (httpMethod === "GET") { const response = await getAlllTodos(); return createResponse(response); } if (!requestBody) { return createResponse("Missing request body", 400); } const data = JSON.parse(requestBody); if (httpMethod === "POST") { const todo = await addTodoItem(data); return todo ? createResponse(`${todo} added to the database`) : createResponse("Todo is missing", 400); } if (httpMethod === "DELETE") { const id = await deleteTodoItem(data); return id ? createResponse( `Todo item with an id of ${id} deleted from the database` ) : createResponse("ID is missing", 400); } return createResponse( `We only accept GET, POST, and DELETE, not ${httpMethod}`, 400 ); } catch (error) { return createResponse(error, 400); } }; ``` **What we've learned in this section:** -
Tomasz Łakomy revised this gist
Feb 10, 2020 . 1 changed file with 154 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -472,6 +472,115 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { }) .promise(); ``` - Add a `DELETE` handler so we'll be able to delete a todo item: ``` if (httpMethod === "DELETE") { if (queryStringParameters && queryStringParameters.id) { const { id } = queryStringParameters; await dynamo .deleteItem({ "TableName": tableName, "Key": { id: { S: id } } }) .promise(); return createResponse( `Todo item with an id of ${id} deleted from the database` ); } return createResponse("ID is missing", 400); } ``` - At the end, our lambda function should look similar to this: ``` const { DynamoDB } = require("aws-sdk"); const uuid = require("uuid"); const createResponse = (body: string, statusCode = 200) => { return { statusCode, headers: { "Content-Type": "text/plain", "Access-Control-Allow-Origin": "*" // Required for CORS support to work }, body: JSON.stringify(body, null, 2) }; }; exports.handler = async function(event: AWSLambda.APIGatewayEvent) { try { const dynamo = new DynamoDB(); const { queryStringParameters, httpMethod } = event; const tableName = process.env.TABLE_NAME; if (httpMethod === "GET") { const scanResult = await dynamo .scan({ "TableName": tableName, "Limit": 10 }) .promise(); const response = scanResult.Items.map(DynamoDB.Converter.unmarshall); return createResponse(response); } if (httpMethod === "POST") { if (queryStringParameters && queryStringParameters.todo) { const { todo } = queryStringParameters; await dynamo .putItem({ "TableName": tableName, "Item": { id: { S: uuid() }, todo: { S: todo } } }) .promise(); return createResponse(`${todo} added to the database`); } return createResponse("Todo is missing", 400); } if (httpMethod === "DELETE") { if (queryStringParameters && queryStringParameters.id) { const { id } = queryStringParameters; await dynamo .deleteItem({ "TableName": tableName, "Key": { id: { S: id } } }) .promise(); return createResponse( `Todo item with an id of ${id} deleted from the database` ); } return createResponse("ID is missing", 400); } return createResponse( `We only accept GET, POST, and DELETE, not ${httpMethod}`, 400 ); } catch (error) { return createResponse(error, 400); } }; ``` **What we've learned in this section:** Okay, that section is not easy - Adding a new item to a DynamoDB table using `PutItem` - Using external packages (in this case - `uuid` in lambda functions created with CDK) - Deleting an item from DynamoDB table using `deleteItem` **Good news - we are not going to touch dynamoDB anymore!** ## Part 7 - Frontend integration @@ -488,10 +597,54 @@ headers: { ``` - Refresh the frontend app and notice that the data is loaded **What we've learned in this section:** - Connecting our new backend to frontend by plugging it into `.env` - Enabling CORS in our lambda function # Part 8 - Deploying the static page to an S3 bucket - Build the frontend app by running `npm run build` - Install `@aws-cdk/aws-s3-deployment` from npm - Go to our stack and create a new bucket for the website and configure a deployment ``` const websiteBucket = new s3.Bucket(this, "WebsiteBucket", { publicReadAccess: true, websiteIndexDocument: "index.html" }); ``` ``` new s3Deployment.BucketDeployment(this, "DeployWebsite", { sources: [s3Deployment.Source.asset("../frontend/build")], destinationBucket: websiteBucket }); ``` **Okay, but where the hell is my website?** - In order to find out website without digging into S3, we're going to add a new output to our stack using `CfnOutput`: ``` new cdk.CfnOutput(this, "WebsiteUrl", { value: websiteBucket.bucketWebsiteUrl }); ``` - which will give us a result similar to this one: ``` Outputs: NewTodoAppStack.WebsiteUrl = http://newtodoappstack-websitebucket75c24d94-sod2pi006ey5.s3-website.eu-central-1.amazonaws.com NewTodoAppStack.Endpoint8024A810 = https://hrqfdwbly9.execute-api.eu-central-1.amazonaws.com/prod/ ``` **What we've learned in this section:** - Creating a S3 Bucket deployment to host a static website - Creating a custom CloudFormation stack output ## Endgame - Destroy the stack by running `cdk destroy` > I've used `cdk` to destroy `cdk` - Tony Stark ## Useful tips: Add a following .prettierc file to the project to avoid problems with DynamoDB SDK: -
Tomasz Łakomy revised this gist
Feb 10, 2020 . 1 changed file with 11 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -475,9 +475,18 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { ## Part 7 - Frontend integration - Open the `frontend` directory, run the TypeScript React app inside with `yarn start` - Inject the API endpoint into the app to try to fetch current todos - Notice that backend doesn't work due to CORS - Go back to our stack and add CORS preflight options to our REST API. The only thing we need to add is a header in the lambda response since CORS is automatically enabled on the API Gateway level when using `lambdaRestApi` (source: https://github.com/aws/aws-cdk/issues/906). - Add following headers to the lambda function response: ``` headers: { "Content-Type": "text/plain", "Access-Control-Allow-Origin": "*" // Required for CORS support to work }, ``` - Refresh the frontend app and notice that the data is loaded ## Endgame -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 15 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -400,7 +400,7 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct ## Part 6 - Adding and removing data from Todos DynamoDB table - Refactor the `todoHandler` function so it can handle both `GET` and `POST` requests, along with some error handling (notice that currently the id is **HARDCODED**): ``` const { DynamoDB } = require("aws-sdk"); @@ -458,68 +458,26 @@ exports.handler = async function(event: AWSLambda.APIGatewayEvent) { } }; ``` - Go to the lambda directory and run `npm init` to create a `package.json` and install `uuid` package - Modify the `POST` section of the lambda function to use the `uuid` package: ``` await dynamo .putItem({ "TableName": tableName, "Item": { id: { S: uuid() }, todo: { S: todo } } }) .promise(); ``` ## Part 7 - Frontend integration - Open the `frontend` directory, run the TypeScript React app inside - Inject the API endpoint into the app to try to fetch current todos ## Endgame -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 59 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -400,6 +400,65 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct ## Part 6 - Adding and removing data from Todos DynamoDB table - Refactor the `todoHandler` function so it can handle both `GET` and `POST` requests, along with some error handling: ``` const { DynamoDB } = require("aws-sdk"); const createResponse = (body: string, statusCode = 200) => { return { statusCode, headers: { "Content-Type": "text/plain" }, body: JSON.stringify(body, null, 2) }; }; exports.handler = async function(event: AWSLambda.APIGatewayEvent) { try { const dynamo = new DynamoDB(); const { queryStringParameters, httpMethod } = event; const tableName = process.env.TABLE_NAME; if (httpMethod === "GET") { const scanResult = await dynamo .scan({ "TableName": tableName, "Limit": 10 }) .promise(); const response = scanResult.Items.map(DynamoDB.Converter.unmarshall); return createResponse(response); } if (httpMethod === "POST") { if (queryStringParameters && queryStringParameters.todo) { const { todo } = queryStringParameters; await dynamo .putItem({ "TableName": tableName, "Item": { id: { S: "random_id" }, todo: { S: todo } } }) .promise(); return createResponse(`${todo} added to the database`); } return createResponse("Todo is missing", 400); } return createResponse( `We only accept GET, POST, and DELETE, not ${httpMethod}`, 400 ); } catch (error) { return createResponse(error, 400); } }; ``` ## Part 7 - Frontend integration - Open the `frontend` directory, run the TypeScript React app inside -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,10 +18,11 @@ Create an AWS account, install AWS CDK and configure your account - Delete all the boilerplate code and run `cdk diff` to see the resources that will be deleted - Deploy the stack again - Check out CloudFront to see an empty stack - Install `npm install --save @types/aws-lambda` - Create a new lambda function handler in new `lambda` directory, call it `hello.ts` ``` exports.handler = async function(event: AWSLambda.APIGatewayEvent) { console.log("request:", JSON.stringify(event, null, 2)); return { -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 9 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -464,4 +464,12 @@ exports.handler = async function(event) { ## Endgame - Destroy the stack by running `cdk destroy` > I've used `cdk` to destroy `cdk` ## Useful tips: Add a following .prettierc file to the project to avoid problems with DynamoDB SDK: ``` { "quoteProps": "preserve" } ``` -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -257,7 +257,7 @@ Resources - Creating a DynamoDB table - Adding new items to a DynamoDB table ## Part 5 - Creating a DynamoDB table for todos - Create a `todoHandler.ts` lambda function that for now is going to list all items from the table: @@ -397,7 +397,9 @@ and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda funct - Debugging permission issues using CloudWatch logs - Granting DynamoDB read/write priviledges to a lambda function (with a single line of code, holy shit) ## Part 6 - Adding and removing data from Todos DynamoDB table ## Part 7 - Frontend integration - Open the `frontend` directory, run the TypeScript React app inside - Inject the API endpoint into the app to try to fetch current todos -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 13 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -251,6 +251,12 @@ Resources } ``` **What we've learned in this section:** - Creating a new CDK Construct from scratch and importing it in main stack - Creating a DynamoDB table - Adding new items to a DynamoDB table ## Part 5 - Adding DynamoDB backend - Create a `todoHandler.ts` lambda function that for now is going to list all items from the table: @@ -377,19 +383,19 @@ export class NewTodoAppStack extends cdk.Stack { - Grant the lambda role read/write permissions to table in `todoadder-stack`: ``` // Grant the lambda function role read/write permissions to this table todoDatabase.grantReadWriteData(this.todoHandler); ``` and run `cdk diff` to see `Get/Put/UpdateItem` etc. allowed for the lambda function and deploy the stack - Test the function and notice data being read from DynamoDB **What we've learned in this section:** - Scanning a DynamoDB table using `aws-cdk` - Debugging permission issues using CloudWatch logs - Granting DynamoDB read/write priviledges to a lambda function (with a single line of code, holy shit) ## Next up - frontend -
Tomasz Łakomy revised this gist
Feb 9, 2020 . 1 changed file with 4 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -366,15 +366,16 @@ export class NewTodoAppStack extends cdk.Stack { } } ``` - Take a look at the `cdk diff`, that's **A LOT** of changes we don't have to do ourselves - Deploy the function and `curl -i` the endpoint which is going to fail - Debug WTF is going in using CloudWatch - Shit's fucked: `"errorMessage": "User: arn:aws:sts::696785635119:assumed-role/NewTodoAppStack-TodoDatabasetodoHandlerServiceRole-1D3JXVMXTHV5G/NewTodoAppStack-TodoDatabasetodoHandlerA2559B62-IDSJIZW758II is not authorized to perform: dynamodb:Scan on resource: arn:aws:dynamodb:eu-central-1:696785635119:table/NewTodoAppStack-TodoDatabase08DB7F4F-F654XN49LOJF", ` - Grant the lambda role read/write permissions to table in `todoadder-stack`: ``` // Grant the lambda role read/write permissions to this table todosTable.grantReadWriteData(this.handler);
NewerOlder