mirror of
https://github.com/opelly27/streetmerchant.git
synced 2026-05-19 23:28:30 +00:00
feat: add terraform infra as code for AWS fargate (#1987)
This commit is contained in:
@@ -17,3 +17,5 @@ success-*.png
|
||||
desktop.ini
|
||||
|
||||
twitch.json
|
||||
terraform/terraform.tfstate
|
||||
terraform/terraform.tfstate.backup
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Terraform for AWS Fargate
|
||||
|
||||
Here's some configurable terraform to get you up and running with the streetmerchant docker image in AWS ECS Fargate.
|
||||
|
||||
Running on cloud infrastructure, your mileage may vary, and you'll need to integrate with one of the chat notifications rather than having your local browser navigate to a url for you.
|
||||
|
||||
The author's findings were that it worked ok; running the container from within EU-West-2 region was suficient to get a timely alert for PS5 stock on amazon, and follow the link to a successful basket add.
|
||||
|
||||
Dependencies:
|
||||
- Terraform 14
|
||||
|
||||
##Getting started
|
||||
|
||||
There's an example tfvars file to start you off; rename this with your own preferences. Anything you can set in the `dotenv` file you'll need to set in terraform.tfvars to get the env vars into your fargate container.
|
||||
|
||||
Authenticate yourself with your own AWS account as with any aws commandline tool.
|
||||
|
||||
If you wish, add a specific section to your aws credentials file and set that profile name in `terraform.tfvars`.
|
||||
|
||||
Then you can:
|
||||
```shell
|
||||
cd ./terraform
|
||||
terraform init
|
||||
|
||||
terraform plan
|
||||
terraform apply
|
||||
```
|
||||
|
||||
## What's included
|
||||
|
||||
- container, running streetmerchant, with your chosen config
|
||||
- cloud metrics and a dashboard tracking 'out of stock' and 'error' responses from your configured stores
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"widgets": [
|
||||
{
|
||||
"type": "metric",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 18,
|
||||
"height": 12,
|
||||
"properties": {
|
||||
"metrics": ${out_of_stock},
|
||||
"view": "timeSeries",
|
||||
"stacked": false,
|
||||
"region": "${region}",
|
||||
"start": "-PT1H",
|
||||
"end": "P0D",
|
||||
"stat": "Sum",
|
||||
"period": 300,
|
||||
"title": "out of stock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "metric",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 18,
|
||||
"height": 12,
|
||||
"properties": {
|
||||
"metrics": ${error},
|
||||
"view": "timeSeries",
|
||||
"stacked": false,
|
||||
"region": "${region}",
|
||||
"start": "-PT1H",
|
||||
"end": "P0D",
|
||||
"stat": "Sum",
|
||||
"period": 300,
|
||||
"title": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.region
|
||||
shared_credentials_file = var.credential_file
|
||||
profile = var.credential_profile
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
resource "aws_ecs_cluster" "main" {
|
||||
name = "${var.app_name}-ecs-cluster"
|
||||
}
|
||||
|
||||
resource "aws_ecs_service" "main" {
|
||||
name = "${var.app_name}-ecs-service"
|
||||
cluster = aws_ecs_cluster.main.id
|
||||
task_definition = aws_ecs_task_definition.main.id
|
||||
desired_count = 1
|
||||
network_configuration {
|
||||
subnets = [
|
||||
aws_subnet.aws-subnet.id
|
||||
]
|
||||
assign_public_ip = true
|
||||
}
|
||||
launch_type = "FARGATE"
|
||||
}
|
||||
|
||||
data "aws_iam_role" "ecs_task_execution_role" {
|
||||
name = "ecsTaskExecutionRole"
|
||||
}
|
||||
|
||||
locals {
|
||||
container_env = [for k, v in var.streetmerchant_env : { name: k, value: v}]
|
||||
}
|
||||
|
||||
resource "aws_ecs_task_definition" "main" {
|
||||
container_definitions = templatefile("taskdef.json.template", {
|
||||
"name": var.app_name
|
||||
"awslogs-group": aws_cloudwatch_log_group.main.name
|
||||
"region": var.region
|
||||
"cpu": var.cpu
|
||||
"memory": parseint(var.memory,10)
|
||||
"environment": jsonencode(local.container_env)
|
||||
})
|
||||
family = var.app_name
|
||||
requires_compatibilities = ["FARGATE"]
|
||||
network_mode = "awsvpc"
|
||||
cpu = var.cpu
|
||||
memory = var.memory
|
||||
execution_role_arn = data.aws_iam_role.ecs_task_execution_role.arn
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
resource "aws_cloudwatch_log_group" "main" {
|
||||
name = var.app_name
|
||||
retention_in_days = 3
|
||||
}
|
||||
|
||||
locals {
|
||||
stores = split(",",var.streetmerchant_env["STORES"])
|
||||
metrics = {
|
||||
out_of_stock = [for store in local.stores : ["${var.app_name}-out-of-stock", store]]
|
||||
error = [for store in local.stores : ["${var.app_name}-error", store]]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_log_metric_filter" "out_of_stock" {
|
||||
for_each = toset(local.stores)
|
||||
|
||||
log_group_name = aws_cloudwatch_log_group.main.name
|
||||
name = "${each.key}-out-of-stock"
|
||||
|
||||
pattern = "${each.key} \"OUT OF STOCK\""
|
||||
metric_transformation {
|
||||
name = each.key
|
||||
namespace = "${var.app_name}-out-of-stock"
|
||||
value = 1
|
||||
default_value = 0
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_log_metric_filter" "error" {
|
||||
for_each = toset(local.stores)
|
||||
|
||||
log_group_name = aws_cloudwatch_log_group.main.name
|
||||
name = "${each.key}-error"
|
||||
|
||||
pattern = "${each.key} \"ERROR\""
|
||||
metric_transformation {
|
||||
name = each.key
|
||||
namespace = "${var.app_name}-error"
|
||||
value = 1
|
||||
default_value = 0
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_dashboard" "main" {
|
||||
dashboard_name = "${var.app_name}-dashboard"
|
||||
dashboard_body = templatefile("dashboard.json.template", {
|
||||
out_of_stock = jsonencode(local.metrics.out_of_stock)
|
||||
error = jsonencode(local.metrics.error)
|
||||
region = var.region
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
resource "aws_vpc" "main" {
|
||||
enable_dns_support = true
|
||||
cidr_block = "10.0.0.0/16"
|
||||
tags = {
|
||||
app = "ps5"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_internet_gateway" "main" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
tags = {
|
||||
app = "ps5"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "aws-subnet" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
cidr_block = aws_vpc.main.cidr_block
|
||||
map_public_ip_on_launch = true
|
||||
tags = {
|
||||
app = "ps5"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route_table" "main" {
|
||||
vpc_id = aws_vpc.main.id
|
||||
route {
|
||||
cidr_block = "0.0.0.0/0"
|
||||
gateway_id = aws_internet_gateway.main.id
|
||||
}
|
||||
tags = {
|
||||
app = "ps5"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_main_route_table_association" "main" {
|
||||
route_table_id = aws_route_table.main.id
|
||||
vpc_id = aws_vpc.main.id
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"name": "${name}-task",
|
||||
"image": "ghcr.io/jef/streetmerchant:latest",
|
||||
"cpu": ${cpu},
|
||||
"memory": ${memory},
|
||||
"essential": true,
|
||||
"environment": ${environment},
|
||||
"logConfiguration": {
|
||||
"logDriver": "awslogs",
|
||||
"options": {
|
||||
"awslogs-group": "${awslogs-group}",
|
||||
"awslogs-region": "${region}",
|
||||
"awslogs-stream-prefix": "ecs"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
credential_profile = "ps5"
|
||||
|
||||
streetmerchant_env = {
|
||||
"STORES" = "amazon-uk,game,argos,box,currys,johnlewis,shopto,smythstoys,very,amazon-it,amazon-nl"
|
||||
"SHOW_ONLY_SERIES" = "sonyps5c,sonyps5de"
|
||||
"SLACK_TOKEN" = "your slack api token"
|
||||
"SLACK_CHANNEL" = "your slack channel name"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
variable "credential_file" {
|
||||
type = string
|
||||
description = "your aws credentials file"
|
||||
default = "~/.aws/credentials"
|
||||
}
|
||||
|
||||
variable "credential_profile" {
|
||||
type = string
|
||||
description = "the section in ~/.aws/credentials with your desired aws_access_key_id and aws_secret_access_key values"
|
||||
default = "default"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
description = "aws region"
|
||||
default = "eu-west-2"
|
||||
}
|
||||
|
||||
variable "app_name" {
|
||||
type = string
|
||||
default = "streetmerchant"
|
||||
}
|
||||
|
||||
variable "memory" {
|
||||
type = string
|
||||
default = "2048"
|
||||
description = "ecs task memory"
|
||||
}
|
||||
|
||||
variable "cpu" {
|
||||
type = number
|
||||
default = 1024
|
||||
description = "ecs task cpu"
|
||||
}
|
||||
|
||||
variable "streetmerchant_env" {
|
||||
type = map
|
||||
description = "name/value pairs for .env values"
|
||||
default = {}
|
||||
}
|
||||
Reference in New Issue
Block a user