{"id":16486508,"url":"https://github.com/brietsparks/guestbook","last_synced_at":"2025-03-21T07:31:11.564Z","repository":{"id":40930279,"uuid":"280780731","full_name":"brietsparks/guestbook","owner":"brietsparks","description":"A simple app with automated infrastructure provisioning, app deployment, and E2E testing","archived":false,"fork":false,"pushed_at":"2023-01-24T03:39:24.000Z","size":5844,"stargazers_count":31,"open_issues_count":34,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-17T22:38:30.350Z","etag":null,"topics":["aws","cypress","fargate","iac","terraform","terratest"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brietsparks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-19T03:00:50.000Z","updated_at":"2025-02-12T11:09:20.000Z","dependencies_parsed_at":"2023-02-13T16:01:21.148Z","dependency_job_id":null,"html_url":"https://github.com/brietsparks/guestbook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brietsparks%2Fguestbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brietsparks%2Fguestbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brietsparks%2Fguestbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brietsparks%2Fguestbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brietsparks","download_url":"https://codeload.github.com/brietsparks/guestbook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244757544,"owners_count":20505417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cypress","fargate","iac","terraform","terratest"],"created_at":"2024-10-11T13:29:32.749Z","updated_at":"2025-03-21T07:31:11.176Z","avatar_url":"https://github.com/brietsparks.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Guestbook\n\nA simple app with automated infrastructure provisioning, app deployment, and E2E testing.\n\n- Terraform IaC, modularized and multi-environment \n- Golang JSON+HTTP API server\n- React webapp client\n- Dockerized, horizontally scaled via ECS Fargate \n- DynamoDB\n- E2E Testing with [Terratest](https://terratest.gruntwork.io) and [Cypress](https://www.cypress.io/)\n\nTable of contents:\n- [Architecture](https://github.com/brietsparks/guestbook#architecture)\n- [Dependencies](https://github.com/brietsparks/guestbook#dependencies)\n- [Deployment and Tear Down](https://github.com/brietsparks/guestbook#deployment-and-tear-down)\n- [Infrastructure E2E Testing](https://github.com/brietsparks/guestbook#infrastructure--e2e-testing)\n- [Deploy dev environment infrastructure](https://github.com/brietsparks/guestbook#deploy-dev-environment-infrastructure)\n- [Next steps](https://github.com/brietsparks/guestbook#next-steps)\n- [LICENSE](https://github.com/brietsparks/guestbook#license)\n\n## Architecture\n\nThe frontend and backend applications each run in Docker containers and are horizontally scaled in an ECS Fargate cluster. They sit in private subnets but can be reached through an application load balancer and are able to pull from DockerHub ([server](https://hub.docker.com/repository/docker/brietsparks/guestbook-server) and [client](https://hub.docker.com/repository/docker/brietsparks/guestbook-client)) via a NAT instance. The backend application stores data in a DynamoDB table. All IAM permissions are provided via IAM roles so that no long-lived access keys exist.   \n\n![AWS Architecture Diagram for Guestbook Application](https://raw.githubusercontent.com/brietsparks/guestbook/master/aws-arch-diagram.png \"AWS Architecture Diagram for Guestbook Application\")\n\n## Dependencies\n- an AWS account with an IAM user capable of creating the resources. Currently, I have been using `AdministratorAccess`. Determining the minimum permission scope is on the list of todos (see [Next steps](https://github.com/brietsparks/guestbook#next-steps)).\n- a locally configured AWS profile for the above IAM user\n- Terraform `~\u003e 0.12.0`\n- GNU Make\n\n## Deployment and Tear Down\nThis section Deploying the infrastructure and applications to AWS requires just a few commands. **Warning: this will create AWS resources that cost money**. \n\n**Deployment steps**\n1. Clone the repo\n    ```\n    git clone git@github.com:brietsparks/guestbook.git\n    ```\n\n2. In the project root, create a Terraform var-file. Run:\n    ```\n    touch .tfvars\n    ```\n    and in the file, set your AWS profile:\n    ```\n    // .tfvars\n    profile = \u003ciam-profile\u003e\n    ```\n    See the [Prod Terraform Inputs](https://github.com/brietsparks/guestbook/blob/master/infrastructure/environments/prod/README.md) for additional optional parameters.\n    \n3. Next, run:\n    ```\n    make prod\n    ```\n    When prompted with the Terraform plan, type `yes` to create the resources. **These resources cost money.**\n   \n4. After Terraform creates the resources, it will output the load balancer DNS host address:\n    ```\n    alb_dns_host = http://guestbook-server-123456789.us-west-2.elb.amazonaws.com\n    ``` \n    Wait a minute or two for the ECS task containers to start. Then in the browser, navigate to DNS host address to use the app.\n\n5. To tear down the app and its AWS resources, run:\n    ```\n    make prod-down\n    ```\n    When prompted with the Terraform plan, type `yes` to destroy the resources.\n\nApp demo: a user can view and submit comments for their particular IP address:\n![Guestbook Application Demo GIF](https://raw.githubusercontent.com/brietsparks/guestbook/master/demo.gif \"Guestbook Application Demo GIF\")\n\n## Infrastructure + E2E Testing\nOn each test run:\n1. Terratest provisions the infrastructure\n2. Cypress runs E2E tests against the deployed frontend application\n3. Terratest deprovisions the infrastructure. \n\n**Dependencies**\n- the [base dependencies](https://github.com/brietsparks/guestbook#dependencies)\n- Go `\u003e=1.14`\n- NodeJS `\u003e=12.8.1` \n- yarn package manager. If you don't have yarn, then run `npm install` in the /client directory before running the tests.   \n\n**Testing steps**\n1. Follow steps 1 and 2 of [the deployment steps](https://github.com/brietsparks/guestbook#deployment-and-tear-down) above.\n\n2. In the project root, run:\n   ```\n   make test\n   ```\n   When prompted with the Terraform plan, type `yes` to create the resources.\n\n   \n## Deploy dev environment infrastructure\nThe dev environment creates a DynamoDB table and an IAM user+role that can access the table. Terraform outputs the credentials which the backend app can use for local development.\n\n**Steps:**\n1. In the project root, create a Terraform var-file and set the `profile`. See the [Dev Terraform Inputs](https://github.com/brietsparks/guestbook/blob/master/infrastructure/environments/dev/README.md) for additional optional parameters.\n\n2. Run:\n   ```\n   make dev\n   ```\n\n3. After Terraform creates the resources, it will output the IAM config and credentials for accessing the database:\n\n    ```\n    Outputs:\n\n    cli_config = \n    [local_dev_user]\n    region = us-west-2\n    \n    [local_dev_user_role]\n    role_arn = arn:aws:iam::0123456789012:role/dynamodb_data_access_role_dev\n    source_profile = local_dev_user\n    \n    cli_credentials = \n    [local_dev_user]\n    aws_access_key_id = \u003ckey\u003e\n    aws_secret_access_key = \u003csecret\u003e\n    ```\n   \n4. Paste the config and credential entries into your local shared AWS config and credentials files (in `~/.aws`)\n\n5. You can now run the server locally using the deployed dev database. See the [steps for using the server locally](https://github.com/brietsparks/guestbook/blob/master/server/README.md).\n\n6. To tear down the dev infrastructure, run:\n    ```\n    make down-down\n    ```\n    When prompted with the Terraform plan, type `yes` to destroy the resources.\n\n## Next steps\nHere are a few things that should be done next:\n\n- CI/CD pipeline\n- HTTPS via ELB SSL termination\n- VPC endpoints for DynamoDB\n- implement VPC without 3rd party module\n- minimize permission scope of TF AWS profile \n- vendor-neutral rewrite\n\n## LICENSE\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrietsparks%2Fguestbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrietsparks%2Fguestbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrietsparks%2Fguestbook/lists"}