terra_boi 0.0.12 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +86 -157
  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 +21 -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 +280 -4
  42. data/lib/terra_boi/railtie.rb +5 -2
  43. data/lib/terra_boi/version.rb +1 -1
  44. metadata +60 -31
  45. data/lib/generators/terra_boi/data_generator.rb +0 -38
  46. data/lib/generators/terra_boi/master_worker_generator.rb +0 -47
  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_user_data.erb +0 -33
  52. data/lib/generators/terra_boi/templates/packer_ami_build.erb +0 -27
  53. data/lib/generators/terra_boi/templates/packer_application.erb +0 -49
  54. data/lib/generators/terra_boi/templates/web_servers_main.erb +0 -31
  55. data/lib/generators/terra_boi/templates/web_servers_output.erb +0 -14
  56. data/lib/generators/terra_boi/templates/web_servers_user_data.erb +0 -29
  57. 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
+ }