generated from habedi/template-python-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added the files for a new use case that is a demo of setting up a simple GraphQL API using AWS AppSync and RDS Aurora. - Edited the main README file and added the information about the new use case. - Revised the README files and simplified them if it was possible.
- Loading branch information
Showing
19 changed files
with
1,127 additions
and
22 deletions.
There are no files selected for viewing
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,23 @@ | ||
# Learning Terraform with AWS | ||
# Terraform Playground | ||
|
||
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) | ||
[![CodeFactor](https://www.codefactor.io/repository/github/habedi/learning-terraform/badge)](https://www.codefactor.io/repository/github/habedi/learning-terraform) | ||
[![CodeFactor](https://www.codefactor.io/repository/github/habedi/terraform-playground/badge)](https://www.codefactor.io/repository/github/habedi/terraform-playground) | ||
|
||
The [use-cases](use-cases/) directory contains a collection of use cases where [Terraform](https://www.terraform.io/) | ||
is used to provision resources in [AWS](https://aws.amazon.com/). | ||
|
||
See the README file in each use case directory for more information about the use case. | ||
This repository contains a collection of use cases where [Terraform](https://www.terraform.io/) is used to provision resources | ||
in [AWS](https://aws.amazon.com/) to set up environments for various tasks. | ||
|
||
The list of currently implemented use cases: | ||
|
||
| Index | Task | | ||
|-------|----------------------------------------------------------------------| | ||
| 1 | [Use Case 1: Provision a server](modules/use-case-1/) | | ||
| 2 | [Use Case 2: Provision a server and a database](modules/use-case-2/) | | ||
| Index | Task | Complexity | | ||
|-------|-------------------------------------------------------------------------------|------------| | ||
| 1 | [Provision a Server](use-cases/use-case-1/) | Simple | | ||
| 2 | [Provision a Server and a Database](use-cases/use-case-2/) | Simple | | ||
| 3 | [Set up a GraphQL API with AWS AppSync and RDS Aurora](use-cases/use-case-3/) | Complex | | ||
|
||
## Installing Poetry | ||
## Poetry | ||
|
||
Optionally, you can use [Poetry](https://python-poetry.org/) to manage the Python dependencies | ||
(if you use Python for scripting, etc.). | ||
You can use [Poetry](https://python-poetry.org/) to manage the Python dependencies (if you use Python for scripting, etc.). | ||
|
||
```bash | ||
pip install poetry | ||
pipx install poetry # or uv tool install poetry | ||
``` |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
# Use Case 1: Provision a server in AWS | ||
# Provision a Server in AWS | ||
|
||
This use case provisions a single EC2 instance in AWS. | ||
The instance is created in a new VPC with a single public subnet and a security group that allows SSH access from the | ||
public internet. | ||
The instance is created in a new VPC with a single public subnet and a security group that allows SSH access from the public internet. |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
# Use Case 2: Provision a server and a database in AWS | ||
# Provision a Server and a Database in AWS | ||
|
||
This use case provisions an EC2 instance and an RDS MySQL database instance in AWS. | ||
The EC2 instance is created in a new VPC with a single public subnet and a security group that allows SSH access from | ||
the public internet. | ||
The EC2 instance is created in a new VPC with a single public subnet and a security group that allows SSH access from the public internet. | ||
The RDS MySQL database instance is created in the same VPC as the EC2 instance, however, in a private subnet. | ||
The security group of the RDS MySQL database instance allows inbound traffic only from the security group of the EC2 | ||
instance. | ||
The security group of the RDS MySQL database instance allows inbound traffic only from the security group of the EC2 instance. | ||
So, the ECT instance can connect to the RDS MySQL database instance. |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Set Up a GraphQL API with AWS AppSync and RDS Aurora Serverless | ||
|
||
This use case is a simple demo that shows how to create a [GraphQL API](https://graphql.org/) using [AWS AppSync](https://aws.amazon.com/appsync/) and | ||
an [RDS Aurora Serverless database](https://aws.amazon.com/rds/aurora/serverless/) as the data source. | ||
|
||
You can start and stop the demo by running the commands below in the terminal. | ||
The commands must be run in the directory where the `main.tf` file is located. | ||
|
||
#### Prepare the Environment | ||
|
||
```bash | ||
terraform init | ||
``` | ||
|
||
#### Create the Execution Plan | ||
|
||
```bash | ||
terraform plan -out=plan.tfplan | ||
``` | ||
|
||
#### Apply the Plan | ||
|
||
```bash | ||
terraform apply -parallelism=4 | ||
``` | ||
|
||
#### Clean Up | ||
|
||
```bash | ||
terraform destroy | ||
``` | ||
|
||
### Customizing the Demo | ||
|
||
Change the values for the variables in the [variables.tf](variables.tf) file to customize the demo (for example, region, database name, etc.). | ||
|
||
### Accessing the API | ||
|
||
After the `apply` command is run without errors, you should be able to access the API via | ||
the [AppSync console](https://us-east-1.console.aws.amazon.com/appsync/home?region=us-east-1#/). | ||
The console will show the URL for the GraphQL endpoint, which includes an API named `roles-api`. | ||
You can also access and invoke the API using the AWS CLI, the AWS SDKs, etc. | ||
|
||
Example queries, mutations, and subscriptions to interact with the API: | ||
|
||
```graphql | ||
mutation MyMutation1 { | ||
createRole(id: "3", name: "ROLE NAME") { | ||
id | ||
name | ||
description | ||
} | ||
updateRole(id: "3", name: "DUMMY_USER", description: "Dummy User") { | ||
id | ||
name | ||
description | ||
} | ||
} | ||
|
||
query Query { | ||
listRoles { | ||
id | ||
name | ||
description | ||
} | ||
} | ||
|
||
mutation MyMutation2 { | ||
deleteRole(id: "3") { | ||
id | ||
} | ||
} | ||
|
||
subscription MySubscription { | ||
onDeleteRole { | ||
description | ||
id | ||
name | ||
} | ||
} | ||
``` | ||
|
||
### API Schema and Resolvers | ||
|
||
The schema and resolvers for the API are defined in the [schema](assets/apis/roles/schema.graphql) file and [resolvers](assets/apis/roles/resolvers/) | ||
directory, respectively. | ||
|
||
### Cleanup | ||
|
||
After you are done with the demo, you can clean up the resources by running the `destroy` Terraform command. |
11 changes: 11 additions & 0 deletions
11
use-cases/use-case-3/assets/apis/roles/resolvers/createRole/request.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"version": "2018-05-29", | ||
"statements": [ | ||
"insert into core_model.roles (id, name, description) values (:id::integer, :name::text, :description::text) returning id, name, description" | ||
], | ||
"variableMap": { | ||
":id": $util.toJson($ctx.args.id), | ||
":name": $util.toJson($ctx.args.name), | ||
":description": $util.toJson($ctx.args.description) | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
use-cases/use-case-3/assets/apis/roles/resolvers/createRole/response.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#if ($ctx.error) | ||
$util.error($ctx.error.message, $ctx.error.type) | ||
#else | ||
#if ($ctx.result.length == 0) | ||
null | ||
#else | ||
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0]) | ||
#end | ||
#end |
67 changes: 67 additions & 0 deletions
67
use-cases/use-case-3/assets/apis/roles/resolvers/deleteRole/resolver.js
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* Sends a request to the attached data source for deleteRole | ||
* @param {import('@aws-appsync/utils').Context} ctx the context | ||
* @returns {*} the request | ||
*/ | ||
export function request(ctx) { | ||
// Extract the ID argument from the mutation input | ||
const {id} = ctx.args; | ||
|
||
// Construct the SQL query | ||
const sqlQuery = ` | ||
delete | ||
from core_model.roles | ||
where id = :id::integer | ||
returning id, name, description | ||
`; | ||
|
||
// Log the constructed query | ||
console.log(`Executing query: ${sqlQuery} with id=${id}`); | ||
|
||
// Return the SQL query with parameters | ||
return { | ||
version: "2018-05-29", | ||
statements: [sqlQuery], | ||
variableMap: { | ||
":id": id, | ||
}, | ||
}; | ||
} | ||
|
||
/** | ||
* Returns the resolver result for deleteRole | ||
* @param {import('@aws-appsync/utils').Context} ctx the context | ||
* @returns {*} the result | ||
*/ | ||
export function response(ctx) { | ||
// Log the raw database response | ||
console.log(`Raw response from data source: ${JSON.stringify(ctx.result)}`); | ||
|
||
// Parse the SQL statement results | ||
const sqlStatementResults = JSON.parse(ctx.result).sqlStatementResults; | ||
|
||
if (!sqlStatementResults || sqlStatementResults.length === 0) { | ||
console.log("No SQL statement results found."); | ||
return null; // No rows deleted | ||
} | ||
|
||
// Extract records from the first statement result | ||
const records = sqlStatementResults[0].records; | ||
|
||
if (!records || records.length === 0) { | ||
console.log("No records found in the database response."); | ||
return null; // No rows deleted | ||
} | ||
|
||
// Map the first record to the GraphQL schema | ||
const deletedRole = { | ||
id: records[0][0]?.longValue, // Assuming the first column is `id` | ||
name: records[0][1]?.stringValue, // Assuming the second column is `name` | ||
description: records[0][2]?.stringValue, // Assuming the third column is `description` | ||
}; | ||
|
||
// Log the processed role | ||
console.log(`Deleted role: ${JSON.stringify(deletedRole)}`); | ||
|
||
return deletedRole; | ||
} |
9 changes: 9 additions & 0 deletions
9
use-cases/use-case-3/assets/apis/roles/resolvers/getRole/request.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"version": "2018-05-29", | ||
"statements": [ | ||
"select id, name, description from core_model.roles where id = :id::integer", | ||
], | ||
"variableMap": { | ||
":id": $util.toJson($ctx.args.id) | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
use-cases/use-case-3/assets/apis/roles/resolvers/getRole/response.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#if ($ctx.error) | ||
$util.error($ctx.error.message, $ctx.error.type) | ||
#else | ||
#if ($ctx.result.length == 0) | ||
null | ||
#else | ||
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0]) | ||
#end | ||
#end |
58 changes: 58 additions & 0 deletions
58
use-cases/use-case-3/assets/apis/roles/resolvers/listRoles/resolver.js
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* Sends a request to the attached data source for listRoles | ||
* @param {import('@aws-appsync/utils').Context} ctx the context | ||
* @returns {*} the request | ||
*/ | ||
export function request(ctx) { | ||
// SQL query to fetch all roles | ||
const sqlQuery = "select id, name, description from core_model.roles"; | ||
|
||
// Log the constructed query | ||
console.log(`Executing query: ${sqlQuery}`); | ||
|
||
// Return the query to be executed | ||
return { | ||
version: "2018-05-29", | ||
statements: [sqlQuery], | ||
}; | ||
} | ||
|
||
/** | ||
* Returns the resolver result for listRoles | ||
* @param {import('@aws-appsync/utils').Context} ctx the context | ||
* @returns {*} the result | ||
*/ | ||
export function response(ctx) { | ||
// Log the raw database response | ||
console.log(`Raw response from data source: ${JSON.stringify(ctx.result)}`); | ||
|
||
// Parse the SQL statement results | ||
const sqlStatementResults = JSON.parse(ctx.result).sqlStatementResults; | ||
|
||
if (!sqlStatementResults || sqlStatementResults.length === 0) { | ||
console.log("No SQL statement results found."); | ||
return []; | ||
} | ||
|
||
// Extract records from the first statement result | ||
const records = sqlStatementResults[0].records; | ||
|
||
if (!records || records.length === 0) { | ||
console.log("No records found in the database response."); | ||
return []; | ||
} | ||
|
||
// Map records to the GraphQL schema | ||
const roles = records.map(row => { | ||
return { | ||
id: row[0]?.longValue, // Assuming the first column is `id` | ||
name: row[1]?.stringValue, // Assuming the second column is `name` | ||
description: row[2]?.stringValue, // Assuming the third column is `description` | ||
}; | ||
}); | ||
|
||
// Log the processed roles | ||
console.log(`Processed roles: ${JSON.stringify(roles)}`); | ||
|
||
return roles; | ||
} |
11 changes: 11 additions & 0 deletions
11
use-cases/use-case-3/assets/apis/roles/resolvers/updateRole/request.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"version": "2018-05-29", | ||
"statements": [ | ||
"update core_model.roles set name = :name::text, description = :description::text where id = :id::integer returning id, name, description" | ||
], | ||
"variableMap": { | ||
":id": $util.toJson($ctx.args.id), | ||
":name": $util.toJson($ctx.args.name), | ||
":description": $util.toJson($ctx.args.description) | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
use-cases/use-case-3/assets/apis/roles/resolvers/updateRole/response.vtl
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#if ($ctx.error) | ||
$util.error($ctx.error.message, $ctx.error.type) | ||
#else | ||
#if ($ctx.result.length == 0) | ||
null | ||
#else | ||
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0]) | ||
#end | ||
#end |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
type Role { | ||
id: ID! # The unique identifier for the role | ||
name: String # The name of the role | ||
description: String # The description of the role | ||
} | ||
|
||
# Queries | ||
type Query { | ||
getRole(id: ID!): Role # Fetch a role by its ID | ||
listRoles: [Role] # List all roles | ||
} | ||
|
||
# Mutations | ||
type Mutation { | ||
createRole(id: ID!, name: String, description: String): Role # Create a new role | ||
updateRole(id: ID!, name: String!, description: String!): Role # Update an existing role | ||
deleteRole(id: ID!): Role # Delete a role | ||
} | ||
|
||
# Subscription (Optional) | ||
type Subscription { | ||
onCreateRole: Role @aws_subscribe(mutations: ["createRole"]) # Listen for role creation | ||
onUpdateRole: Role @aws_subscribe(mutations: ["updateRole"]) # Listen for role updates | ||
onDeleteRole: Role @aws_subscribe(mutations: ["deleteRole"]) # Listen for role deletion | ||
} |
Git LFS file not shown
Oops, something went wrong.