terra_boi 0.0.13 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +85 -156
  3. data/lib/generators/extensions.rb +5 -5
  4. data/lib/generators/terra_boi/boilerplate_generator.rb +39 -32
  5. data/lib/generators/terra_boi/dockerfile_generator.rb +19 -18
  6. data/lib/generators/terra_boi/host_initializer_generator.rb +18 -18
  7. data/lib/generators/terra_boi/templates/Dockerfile.erb +4 -23
  8. data/lib/generators/terra_boi/templates/cert/main.tf.erb +32 -0
  9. data/lib/generators/terra_boi/templates/cert/var.tf.erb +15 -0
  10. data/lib/generators/terra_boi/templates/data_storage_config.erb +7 -7
  11. data/lib/generators/terra_boi/templates/ecr/ecs_role.tf.erb +41 -0
  12. data/lib/generators/terra_boi/templates/ecr/main.tf.erb +26 -0
  13. data/lib/generators/terra_boi/templates/ecr/output.tf.erb +11 -0
  14. data/lib/generators/terra_boi/templates/ecr/var.tf.erb +15 -0
  15. data/lib/generators/terra_boi/templates/{data_main.erb → env/data/main.tf.erb} +2 -2
  16. data/lib/generators/terra_boi/templates/{data_output.erb → env/data/output.tf.erb} +1 -1
  17. data/lib/generators/terra_boi/templates/env/ecs_cluster/ecs_cluster.tf.erb +24 -0
  18. data/lib/generators/terra_boi/templates/env/head_worker/ecs.tf.erb +55 -0
  19. data/lib/generators/terra_boi/templates/env/web_app/ecs.tf.erb +59 -0
  20. data/lib/generators/terra_boi/templates/lib/scripts/push_to_ecr.sh.erb +25 -0
  21. data/lib/generators/terra_boi/templates/lib/scripts/update_service_pull_from_ecr.sh.erb +18 -0
  22. data/lib/generators/terra_boi/templates/lib/task_templates/head_worker.json.erb +61 -0
  23. data/lib/generators/terra_boi/templates/lib/task_templates/web_app.json.erb +58 -0
  24. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_cluster/main.tf.erb +12 -0
  25. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_cluster/var.tf.erb +20 -0
  26. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_web_app/ecs_role.tf.erb +7 -0
  27. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_web_app/load_balancer.tf.erb +92 -0
  28. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_web_app/main.tf.erb +134 -0
  29. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_web_app/output.tf.erb +11 -0
  30. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_web_app/var.tf.erb +63 -0
  31. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_worker/ecs_role.tf.erb +7 -0
  32. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_worker/main.tf.erb +120 -0
  33. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_worker/output.tf.erb +7 -0
  34. data/lib/generators/terra_boi/templates/lib/terraform_modules/ecs_worker/var.tf.erb +57 -0
  35. data/lib/generators/terra_boi/templates/state_main.erb +1 -1
  36. data/lib/generators/terra_boi/tf_cert_generator.rb +28 -0
  37. data/lib/generators/terra_boi/tf_ecr_generator.rb +28 -0
  38. data/lib/generators/terra_boi/tf_env_generator.rb +54 -0
  39. data/lib/generators/terra_boi/tf_lib_generator.rb +57 -0
  40. data/lib/generators/terra_boi/tf_state_generator.rb +24 -0
  41. data/lib/tasks/terra_boi_tasks.rake +274 -4
  42. data/lib/terra_boi/railtie.rb +5 -2
  43. data/lib/terra_boi/version.rb +1 -1
  44. metadata +60 -32
  45. data/lib/generators/terra_boi/data_generator.rb +0 -38
  46. data/lib/generators/terra_boi/master_worker_generator.rb +0 -54
  47. data/lib/generators/terra_boi/packer_generator.rb +0 -26
  48. data/lib/generators/terra_boi/state_generator.rb +0 -25
  49. data/lib/generators/terra_boi/templates/master_worker_main.erb +0 -26
  50. data/lib/generators/terra_boi/templates/master_worker_output.erb +0 -14
  51. data/lib/generators/terra_boi/templates/master_worker_start_script.erb +0 -12
  52. data/lib/generators/terra_boi/templates/master_worker_user_data.erb +0 -27
  53. data/lib/generators/terra_boi/templates/packer_ami_build.erb +0 -27
  54. data/lib/generators/terra_boi/templates/packer_application.erb +0 -49
  55. data/lib/generators/terra_boi/templates/web_servers_main.erb +0 -31
  56. data/lib/generators/terra_boi/templates/web_servers_output.erb +0 -14
  57. data/lib/generators/terra_boi/templates/web_servers_user_data.erb +0 -29
  58. data/lib/generators/terra_boi/web_servers_generator.rb +0 -48
@@ -0,0 +1,18 @@
1
+ # Requires AWS cli >= v2.x.x
2
+ # https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html
3
+
4
+ # Arg 1: prod or staging
5
+ # Arg 2: web_app or head_worker
6
+
7
+ SCRIPT_DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
8
+ ENV=$1
9
+ SUB_FOLDER=$2
10
+ cd $SCRIPT_DIR/../../$ENV/$SUB_FOLDER
11
+ pwd
12
+
13
+ echo "Deploying newest container pushed to ECR..."
14
+
15
+ OUTPUT=$(aws ecs update-service --cluster $(terraform output ecs_cluster_name) --service $(terraform output ecs_service_name) --force-new-deployment)
16
+
17
+ echo $OUTPUT
18
+ echo "Deployment complete! Please allow 1-2 minutes for your <%= application_name %> container to boot and join the cluster."
@@ -0,0 +1,61 @@
1
+ [
2
+ {
3
+ "name": "web_app",
4
+ "image": "${image}",
5
+ "entryPoint": ["sh", "-c", "rake db:migrate && touch /etc/crontab /etc/cron.*/* && service cron start && whenever --update-crontab && rake jobs:work"],
6
+ "essential": true,
7
+ "environment": [
8
+ {
9
+ "name": "RAILS_ENV",
10
+ "value": "production"
11
+ },
12
+ {
13
+ "name": "DB_HOST",
14
+ "value": "${db_host}"
15
+ },
16
+ {
17
+ "name": "DB_USERNAME",
18
+ "value": "${db_username}"
19
+ },
20
+ {
21
+ "name": "DB_PASSWORD",
22
+ "value": "${db_password}"
23
+ },
24
+ {
25
+ "name": "AWS_ACCESS_KEY_ID",
26
+ "value": "${aws_access_key}"
27
+ },
28
+ {
29
+ "name": "AWS_SECRET_ACCESS_KEY",
30
+ "value": "${aws_secret_key}"
31
+ },
32
+ {
33
+ "name": "RAILS_LOG_TO_STDOUT",
34
+ "value": "true"
35
+ },
36
+ {
37
+ "name": "RAILS_SERVE_STATIC_FILES",
38
+ "value": "true"
39
+ }
40
+ ],
41
+ "memory": ${memory},
42
+ "cpu": ${cpu},
43
+ "healthCheck": {
44
+ "command": [
45
+ "CMD-SHELL",
46
+ "echo hello"
47
+ ],
48
+ "interval": 5,
49
+ "timeout": 2,
50
+ "retries": 3
51
+ },
52
+ "logConfiguration": {
53
+ "logDriver": "awslogs",
54
+ "options": {
55
+ "awslogs-group": "/fargate/service/${app_name}-${environment}-${app_type}",
56
+ "awslogs-region": "${region}",
57
+ "awslogs-stream-prefix": "ecs"
58
+ }
59
+ }
60
+ }
61
+ ]
@@ -0,0 +1,58 @@
1
+ [
2
+ {
3
+ "name": "web_app",
4
+ "image": "${image}",
5
+ "entryPoint": ["sh", "-c", "rake db:migrate && bin/rails server --port 3000 -b 0.0.0.0"],
6
+ "essential": true,
7
+ "portMappings": [
8
+ {
9
+ "containerPort": ${port},
10
+ "hostPort": ${port}
11
+ }
12
+ ],
13
+ "environment": [
14
+ {
15
+ "name": "RAILS_ENV",
16
+ "value": "production"
17
+ },
18
+ {
19
+ "name": "DB_HOST",
20
+ "value": "${db_host}"
21
+ },
22
+ {
23
+ "name": "DB_USERNAME",
24
+ "value": "${db_username}"
25
+ },
26
+ {
27
+ "name": "DB_PASSWORD",
28
+ "value": "${db_password}"
29
+ },
30
+ {
31
+ "name": "AWS_ACCESS_KEY_ID",
32
+ "value": "${aws_access_key}"
33
+ },
34
+ {
35
+ "name": "AWS_SECRET_ACCESS_KEY",
36
+ "value": "${aws_secret_key}"
37
+ },
38
+ {
39
+ "name": "RAILS_LOG_TO_STDOUT",
40
+ "value": "true"
41
+ },
42
+ {
43
+ "name": "RAILS_SERVE_STATIC_FILES",
44
+ "value": "true"
45
+ }
46
+ ],
47
+ "memory": ${memory},
48
+ "cpu": ${cpu},
49
+ "logConfiguration": {
50
+ "logDriver": "awslogs",
51
+ "options": {
52
+ "awslogs-group": "/fargate/service/${app_name}-${environment}-${app_type}",
53
+ "awslogs-region": "${region}",
54
+ "awslogs-stream-prefix": "ecs"
55
+ }
56
+ }
57
+ }
58
+ ]
@@ -0,0 +1,12 @@
1
+ provider "aws" {
2
+ version = "~> 2.0"
3
+ region = var.region
4
+ }
5
+
6
+ # ---------------------------------------------------------------------------------------------------------------------
7
+ # 1. ECS CLUSTER
8
+ # ---------------------------------------------------------------------------------------------------------------------
9
+
10
+ resource "aws_ecs_cluster" "ecs_cluster" {
11
+ name = "${var.app_name}-${var.environment}"
12
+ }
@@ -0,0 +1,20 @@
1
+ # -----------------------------
2
+ # 1. GENERAL
3
+ # -----------------------------
4
+
5
+ # Optional
6
+
7
+ variable "region" {
8
+ type = string
9
+ default = "us-east-2"
10
+ }
11
+
12
+ variable "app_name" {
13
+ type = string
14
+ default = "<%= application_name %>"
15
+ }
16
+
17
+ variable "environment" {
18
+ type = string
19
+ default = "dev"
20
+ }
@@ -0,0 +1,7 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # 1. ECS IAM ROLE (Created in web_app)
3
+ # ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ data "aws_iam_role" "ecs_execution_role" {
6
+ name = "ecs_${var.app_name}_execution_role"
7
+ }
@@ -0,0 +1,92 @@
1
+ # ----------------------------------------------
2
+ # 1. AWS ALB
3
+ # ----------------------------------------------
4
+
5
+ resource "aws_alb" "application_load_balancer" {
6
+ name = "${var.app_name}-${var.environment}-lb"
7
+ load_balancer_type = "application"
8
+
9
+ subnets = [ # default subnets
10
+ aws_default_subnet.default_subnet_a.id,
11
+ aws_default_subnet.default_subnet_b.id,
12
+ aws_default_subnet.default_subnet_c.id,
13
+ ]
14
+
15
+ security_groups = [aws_security_group.load_balancer_sg.id]
16
+ }
17
+
18
+ resource "aws_security_group" "load_balancer_sg" {
19
+ ingress {
20
+ from_port = 80
21
+ to_port = 80
22
+ protocol = "tcp"
23
+ cidr_blocks = ["0.0.0.0/0"]
24
+ }
25
+
26
+ ingress {
27
+ from_port = 443
28
+ to_port = 443
29
+ protocol = "tcp"
30
+ cidr_blocks = ["0.0.0.0/0"]
31
+ }
32
+
33
+ egress {
34
+ from_port = 0
35
+ to_port = 0
36
+ protocol = "-1"
37
+ cidr_blocks = ["0.0.0.0/0"]
38
+ }
39
+ }
40
+
41
+ # ----------------------------------------------
42
+ # 2. AWS ALB TARGET GROUP + LISTENER
43
+ # ----------------------------------------------
44
+
45
+ resource "aws_lb_target_group" "target_group" {
46
+ name = "${var.app_name}-${var.environment}-target-group"
47
+ port = 80
48
+ protocol = "HTTP"
49
+ target_type = "ip"
50
+ vpc_id = aws_default_vpc.default_vpc.id
51
+ }
52
+
53
+ # 2.1 HTTP:
54
+
55
+ resource "aws_lb_listener" "listener" {
56
+ load_balancer_arn = aws_alb.application_load_balancer.arn
57
+ port = 80
58
+ protocol = "HTTP"
59
+
60
+ default_action {
61
+ type = "forward"
62
+ target_group_arn = aws_lb_target_group.target_group.arn
63
+ }
64
+ }
65
+
66
+ # 2.2 HTTPS:
67
+
68
+ resource "aws_lb_listener" "listener_https" {
69
+ load_balancer_arn = aws_alb.application_load_balancer.arn
70
+ port = 443
71
+ protocol = "HTTPS"
72
+ certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
73
+
74
+ default_action {
75
+ type = "forward"
76
+ target_group_arn = aws_lb_target_group.target_group.arn
77
+ }
78
+ }
79
+
80
+ # ----------------------------------------------
81
+ # 3. HTTPS CERT
82
+ # ----------------------------------------------
83
+
84
+ data "aws_acm_certificate" "cert" {
85
+ domain = "*.${var.domain_name}"
86
+ types = ["AMAZON_ISSUED"]
87
+ most_recent = true
88
+ }
89
+
90
+ resource "aws_acm_certificate_validation" "cert" {
91
+ certificate_arn = data.aws_acm_certificate.cert.arn
92
+ }
@@ -0,0 +1,134 @@
1
+ provider "aws" {
2
+ version = "~> 2.0"
3
+ region = var.region
4
+ }
5
+
6
+ # ---------------------------------------------------------------------------------------------------------------------
7
+ # 1. ECS TASK
8
+ # ---------------------------------------------------------------------------------------------------------------------
9
+
10
+ data "aws_ecr_repository" "ecr_repo" {
11
+ name = "${var.app_name}-ecr-repo"
12
+ }
13
+
14
+ data "aws_ecs_cluster" "ecs_cluster" {
15
+ cluster_name = "${var.app_name}-${var.environment}"
16
+ }
17
+
18
+ data "terraform_remote_state" "db" {
19
+ backend = "s3"
20
+
21
+ config = {
22
+ bucket = "${var.app_name}-terraform-state-storage"
23
+ key = "terraform/${var.environment}-state/terra-boi-data"
24
+ region = "us-east-2"
25
+ }
26
+ }
27
+
28
+ data "template_file" "task" {
29
+ template = "${file("../../lib/task_templates/${var.template_filename}")}"
30
+
31
+ vars = {
32
+ image = data.aws_ecr_repository.ecr_repo.repository_url
33
+ app_name = var.app_name
34
+ app_type = var.app_type
35
+ environment = var.environment
36
+ region = var.region
37
+ port = var.web_app_task.port
38
+ memory = var.web_app_task.memory
39
+ cpu = var.web_app_task.cpu
40
+ db_host = data.terraform_remote_state.db.outputs.address
41
+ db_username = data.terraform_remote_state.db.outputs.db_username
42
+ db_password = var.db_password
43
+ aws_access_key = var.aws_access_key
44
+ aws_secret_key = var.aws_secret_key
45
+ }
46
+ }
47
+
48
+ resource "aws_ecs_task_definition" "web_app" {
49
+ family = var.app_type # Naming our first task
50
+ requires_compatibilities = ["FARGATE"] # Stating that we are using ECS Fargate
51
+ network_mode = "awsvpc" # Using awsvpc as our network mode as this is required for Fargate
52
+ memory = var.web_app_task.memory # Specifying the memory our container requires
53
+ # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
54
+ cpu = var.web_app_task.cpu # Specifying the CPU our container requires
55
+ task_role_arn = data.aws_iam_role.ecs_execution_role.arn
56
+ execution_role_arn = data.aws_iam_role.ecs_execution_role.arn
57
+ container_definitions = data.template_file.task.rendered
58
+ }
59
+
60
+ # ---------------------------------------------------------------------------------------------------------------------
61
+ # 2. ECS SERVICE
62
+ # ---------------------------------------------------------------------------------------------------------------------
63
+
64
+ resource "aws_ecs_service" "app" {
65
+ name = var.app_type # Naming our first service
66
+ cluster = data.aws_ecs_cluster.ecs_cluster.id # Referencing our created Cluster
67
+ task_definition = aws_ecs_task_definition.web_app.arn # Referencing the task our service will spin up
68
+ launch_type = "FARGATE"
69
+ desired_count = var.web_app_task.desired_count
70
+
71
+ load_balancer {
72
+ target_group_arn = aws_lb_target_group.target_group.arn
73
+ container_name = aws_ecs_task_definition.web_app.family
74
+ container_port = var.web_app_task.port
75
+ }
76
+
77
+ network_configuration {
78
+ subnets = [aws_default_subnet.default_subnet_a.id, aws_default_subnet.default_subnet_b.id, aws_default_subnet.default_subnet_c.id]
79
+ assign_public_ip = true
80
+ security_groups = [aws_security_group.service_security_group.id]
81
+ }
82
+
83
+ depends_on = [aws_lb_listener.listener, aws_lb_target_group.target_group, aws_cloudwatch_log_group.logs]
84
+ }
85
+
86
+ resource "aws_security_group" "service_security_group" {
87
+ ingress {
88
+ from_port = 0
89
+ to_port = 0
90
+ protocol = "-1"
91
+ security_groups = [aws_security_group.load_balancer_sg.id]
92
+ }
93
+
94
+ egress {
95
+ from_port = 0
96
+ to_port = 0
97
+ protocol = "-1"
98
+ cidr_blocks = ["0.0.0.0/0"]
99
+ }
100
+ }
101
+
102
+ # ---------------------------------------------------------------------------------------------------------------------
103
+ # 3. REFERENCE NETWORK RESOURCES (to default VPC)
104
+ # ---------------------------------------------------------------------------------------------------------------------
105
+
106
+ # # Providing a reference to our default VPC
107
+ resource "aws_default_vpc" "default_vpc" {
108
+ }
109
+
110
+ # Providing a reference to our default subnets
111
+ resource "aws_default_subnet" "default_subnet_a" {
112
+ availability_zone = "${var.region}a"
113
+ }
114
+
115
+ resource "aws_default_subnet" "default_subnet_b" {
116
+ availability_zone = "${var.region}b"
117
+ }
118
+
119
+ resource "aws_default_subnet" "default_subnet_c" {
120
+ availability_zone = "${var.region}c"
121
+ }
122
+
123
+ # ---------------------------------------------------------------------------------------------------------------------
124
+ # 4. Logging
125
+ # ---------------------------------------------------------------------------------------------------------------------
126
+
127
+ resource "aws_cloudwatch_log_group" "logs" {
128
+ name = "/fargate/service/${var.app_name}-${var.environment}-${var.app_type}"
129
+ retention_in_days = 90
130
+
131
+ tags = {
132
+ app = var.app_name
133
+ }
134
+ }
@@ -0,0 +1,11 @@
1
+ output "ecs_service_name" {
2
+ value = aws_ecs_service.app.name
3
+ }
4
+
5
+ output "ecs_cluster_name" {
6
+ value = data.aws_ecs_cluster.ecs_cluster.cluster_name
7
+ }
8
+
9
+ output "alb_dns" {
10
+ value = aws_alb.application_load_balancer.dns_name
11
+ }
@@ -0,0 +1,63 @@
1
+ # -----------------------------
2
+ # 1. GENERAL
3
+ # -----------------------------
4
+
5
+ # Optional
6
+
7
+ variable "region" {
8
+ type = string
9
+ default = "us-east-2"
10
+ }
11
+
12
+ variable "app_name" {
13
+ type = string
14
+ default = "<%= application_name %>"
15
+ }
16
+
17
+ variable "environment" {
18
+ type = string
19
+ default = "dev"
20
+ }
21
+
22
+ variable "app_type" {
23
+ type = string
24
+ default = "web_app"
25
+ }
26
+
27
+ variable "template_filename" {
28
+ type = string
29
+ default = "web_app.json"
30
+ }
31
+
32
+ variable "db_password" {
33
+ description = "The password for the database"
34
+ type = string
35
+ }
36
+
37
+ variable "aws_access_key" {
38
+ type = string
39
+ }
40
+
41
+ variable "aws_secret_key" {
42
+ type = string
43
+ }
44
+
45
+ variable "domain_name" {
46
+ type = string
47
+ default = "<%= class_options[:domain_name] %>"
48
+ }
49
+
50
+ # -----------------------------
51
+ # 2. WEB APP TASK
52
+ # -----------------------------
53
+
54
+ variable "web_app_task" {
55
+ type = map
56
+
57
+ default = {
58
+ memory = 512
59
+ cpu = 256
60
+ desired_count = 2
61
+ port = 3000
62
+ }
63
+ }