From 8fb92237c59a4ccb4297a24ce04d733943e7404a Mon Sep 17 00:00:00 2001 From: Yevgeniy Brikman Date: Wed, 16 Nov 2016 03:03:42 +0000 Subject: [PATCH] Generate code from book --- code/bash/01-why-terraform/setup-webserver.sh | 19 ++ .../run-webserver.sh | 3 + .../bash-unit-test-example.sh | 13 ++ code/bash/03-terraform-state/user-data.sh | 9 + code/packer/01-why-terraform/webserver.json | 19 ++ code/ruby/06-terraform-team/terraform-test.rb | 44 ++++ code/terraform/00-preface/hello-world/main.tf | 8 + .../declarative-examples/part-1/main.tf | 9 + .../declarative-examples/part-2/main.tf | 9 + .../declarative-examples/part-3/main.tf | 9 + .../multi-provider-example/main.tf | 20 ++ .../01-why-terraform/server-db-elb/main.tf | 36 +++ .../one-server/main.tf | 12 + .../one-webserver-with-vars/main.tf | 30 +++ .../one-webserver-with-vars/outputs.tf | 3 + .../one-webserver-with-vars/vars.tf | 21 ++ .../one-webserver/main.tf | 34 +++ .../webserver-cluster/main.tf | 92 ++++++++ .../webserver-cluster/outputs.tf | 3 + .../webserver-cluster/vars.tf | 4 + .../file-layout-example/global/s3/main.tf | 15 ++ .../file-layout-example/global/s3/outputs.tf | 3 + .../stage/data-stores/mysql/main.tf | 12 + .../stage/data-stores/mysql/outputs.tf | 7 + .../stage/data-stores/mysql/vars.tf | 3 + .../stage/services/webserver-cluster/main.tf | 107 +++++++++ .../services/webserver-cluster/outputs.tf | 3 + .../services/webserver-cluster/user-data.sh | 9 + .../stage/services/webserver-cluster/vars.tf | 12 + .../services/webserver-cluster/main.tf | 111 +++++++++ .../services/webserver-cluster/outputs.tf | 11 + .../services/webserver-cluster/user-data.sh | 9 + .../services/webserver-cluster/vars.tf | 28 +++ .../prod/data-stores/mysql/main.tf | 12 + .../prod/data-stores/mysql/outputs.tf | 7 + .../prod/data-stores/mysql/vars.tf | 3 + .../prod/services/webserver-cluster/main.tf | 35 +++ .../services/webserver-cluster/outputs.tf | 3 + .../prod/services/webserver-cluster/vars.tf | 7 + .../stage/data-stores/mysql/main.tf | 12 + .../stage/data-stores/mysql/outputs.tf | 7 + .../stage/data-stores/mysql/vars.tf | 3 + .../stage/services/webserver-cluster/main.tf | 25 +++ .../services/webserver-cluster/outputs.tf | 3 + .../stage/services/webserver-cluster/vars.tf | 7 + .../live/prod/data-stores/mysql/main.tf | 12 + .../live/prod/data-stores/mysql/outputs.tf | 7 + .../live/prod/data-stores/mysql/vars.tf | 3 + .../prod/services/webserver-cluster/main.tf | 33 +++ .../services/webserver-cluster/outputs.tf | 3 + .../prod/services/webserver-cluster/vars.tf | 7 + .../live/stage/data-stores/mysql/main.tf | 12 + .../live/stage/data-stores/mysql/outputs.tf | 7 + .../live/stage/data-stores/mysql/vars.tf | 3 + .../stage/services/webserver-cluster/main.tf | 25 +++ .../services/webserver-cluster/outputs.tf | 3 + .../stage/services/webserver-cluster/vars.tf | 7 + .../live/global/existing-iam-user/main.tf | 9 + .../live/global/one-iam-user/main.tf | 7 + .../three-iam-users-increment-name/main.tf | 8 + .../three-iam-users-unique-names/main.tf | 67 ++++++ .../three-iam-users-unique-names/outputs.tf | 7 + .../three-iam-users-unique-names/vars.tf | 9 + .../live/prod/data-stores/mysql/main.tf | 12 + .../live/prod/data-stores/mysql/outputs.tf | 7 + .../live/prod/data-stores/mysql/vars.tf | 3 + .../prod/services/webserver-cluster/main.tf | 18 ++ .../services/webserver-cluster/outputs.tf | 3 + .../prod/services/webserver-cluster/vars.tf | 7 + .../live/stage/data-stores/mysql/main.tf | 12 + .../live/stage/data-stores/mysql/outputs.tf | 7 + .../live/stage/data-stores/mysql/vars.tf | 3 + .../services/multiple-ec2-instances/main.tf | 19 ++ .../services/multiple-ec2-instances/vars.tf | 4 + .../stage/services/webserver-cluster/main.tf | 28 +++ .../services/webserver-cluster/outputs.tf | 3 + .../stage/services/webserver-cluster/vars.tf | 7 + .../services/webserver-cluster/main.tf | 186 +++++++++++++++ .../services/webserver-cluster/outputs.tf | 11 + .../webserver-cluster/user-data-new.sh | 4 + .../services/webserver-cluster/user-data.sh | 9 + .../services/webserver-cluster/vars.tf | 36 +++ .../live/prod/data-stores/mysql/main.tf | 12 + .../live/prod/data-stores/mysql/outputs.tf | 7 + .../live/prod/data-stores/mysql/vars.tf | 3 + .../services/microservices-example/main.tf | 33 +++ .../prod/services/webserver-cluster/main.tf | 19 ++ .../services/webserver-cluster/outputs.tf | 3 + .../prod/services/webserver-cluster/vars.tf | 18 ++ .../live/stage/data-stores/mysql/main.tf | 12 + .../live/stage/data-stores/mysql/outputs.tf | 7 + .../live/stage/data-stores/mysql/vars.tf | 3 + .../services/automated-deployment/main.tf | 8 + .../automated-deployment/terraform.tfvars | 1 + .../terraform.tfvars.json | 3 + .../services/automated-deployment/vars.tf | 4 + .../live/stage/services/conflict-anna/main.tf | 8 + .../live/stage/services/conflict-bill/main.tf | 12 + .../stage/services/conflict-original/main.tf | 8 + .../stage/services/webserver-cluster/main.tf | 29 +++ .../services/webserver-cluster/outputs.tf | 3 + .../stage/services/webserver-cluster/vars.tf | 18 ++ .../services/webserver-cluster/main.tf | 211 ++++++++++++++++++ .../services/webserver-cluster/outputs.tf | 11 + .../webserver-cluster/user-data-new.sh | 4 + .../services/webserver-cluster/user-data.sh | 9 + .../services/webserver-cluster/vars.tf | 40 ++++ 107 files changed, 1945 insertions(+) create mode 100644 code/bash/01-why-terraform/setup-webserver.sh create mode 100644 code/bash/02-intro-to-terraform-syntax/run-webserver.sh create mode 100644 code/bash/03-terraform-state/bash-unit-test-example.sh create mode 100644 code/bash/03-terraform-state/user-data.sh create mode 100644 code/packer/01-why-terraform/webserver.json create mode 100644 code/ruby/06-terraform-team/terraform-test.rb create mode 100644 code/terraform/00-preface/hello-world/main.tf create mode 100644 code/terraform/01-why-terraform/declarative-examples/part-1/main.tf create mode 100644 code/terraform/01-why-terraform/declarative-examples/part-2/main.tf create mode 100644 code/terraform/01-why-terraform/declarative-examples/part-3/main.tf create mode 100644 code/terraform/01-why-terraform/multi-provider-example/main.tf create mode 100644 code/terraform/01-why-terraform/server-db-elb/main.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/one-server/main.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/main.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/outputs.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/vars.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/one-webserver/main.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/webserver-cluster/main.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf create mode 100644 code/terraform/02-intro-to-terraform-syntax/webserver-cluster/vars.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/global/s3/outputs.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/main.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/outputs.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/vars.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/main.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/user-data.sh create mode 100644 code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/vars.tf create mode 100644 code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/main.tf create mode 100644 code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/user-data.sh create mode 100644 code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/vars.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/main.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/outputs.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/vars.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/main.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/vars.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/main.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/outputs.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/vars.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/vars.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/main.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/outputs.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/vars.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/main.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/vars.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/main.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/outputs.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/vars.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/main.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/existing-iam-user/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/one-iam-user/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/three-iam-users-increment-name/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/main.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/vars.tf create mode 100644 code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/main.tf create mode 100644 code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data-new.sh create mode 100644 code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data.sh create mode 100644 code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/vars.tf create mode 100644 code/terraform/06-terraform-team/live/prod/data-stores/mysql/main.tf create mode 100644 code/terraform/06-terraform-team/live/prod/data-stores/mysql/outputs.tf create mode 100644 code/terraform/06-terraform-team/live/prod/data-stores/mysql/vars.tf create mode 100644 code/terraform/06-terraform-team/live/prod/services/microservices-example/main.tf create mode 100644 code/terraform/06-terraform-team/live/prod/services/webserver-cluster/main.tf create mode 100644 code/terraform/06-terraform-team/live/prod/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/06-terraform-team/live/prod/services/webserver-cluster/vars.tf create mode 100644 code/terraform/06-terraform-team/live/stage/data-stores/mysql/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/data-stores/mysql/outputs.tf create mode 100644 code/terraform/06-terraform-team/live/stage/data-stores/mysql/vars.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/automated-deployment/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars create mode 100644 code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars.json create mode 100644 code/terraform/06-terraform-team/live/stage/services/automated-deployment/vars.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/conflict-anna/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/conflict-bill/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/conflict-original/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/webserver-cluster/main.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/06-terraform-team/live/stage/services/webserver-cluster/vars.tf create mode 100644 code/terraform/06-terraform-team/modules/services/webserver-cluster/main.tf create mode 100644 code/terraform/06-terraform-team/modules/services/webserver-cluster/outputs.tf create mode 100644 code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data-new.sh create mode 100644 code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data.sh create mode 100644 code/terraform/06-terraform-team/modules/services/webserver-cluster/vars.tf diff --git a/code/bash/01-why-terraform/setup-webserver.sh b/code/bash/01-why-terraform/setup-webserver.sh new file mode 100644 index 00000000..cba7dce8 --- /dev/null +++ b/code/bash/01-why-terraform/setup-webserver.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# A script that configures a web server + +set -e + +# Update the apt-get cache +sudo apt-get update + +# Install PHP +sudo apt-get install -y php + +# Install Apache +sudo apt-get install -y apache2 + +# Copy the code from repository +sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app + +# Start Apache +sudo service apache2 start diff --git a/code/bash/02-intro-to-terraform-syntax/run-webserver.sh b/code/bash/02-intro-to-terraform-syntax/run-webserver.sh new file mode 100644 index 00000000..de2f403f --- /dev/null +++ b/code/bash/02-intro-to-terraform-syntax/run-webserver.sh @@ -0,0 +1,3 @@ +#!/bin/bash +echo "Hello, World" > index.html +nohup busybox httpd -f -p 8080 & diff --git a/code/bash/03-terraform-state/bash-unit-test-example.sh b/code/bash/03-terraform-state/bash-unit-test-example.sh new file mode 100644 index 00000000..96c63c2f --- /dev/null +++ b/code/bash/03-terraform-state/bash-unit-test-example.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +export db_address=12.34.56.78 +export db_port=5555 +export server_port=8888 + +./user-data.sh + +output=$(curl "http://localhost:$server_port") + +if [[ $output != *"Hello, World"* ]]; then + echo "Did not get back expected text 'Hello, World'" +fi diff --git a/code/bash/03-terraform-state/user-data.sh b/code/bash/03-terraform-state/user-data.sh new file mode 100644 index 00000000..9fbcab53 --- /dev/null +++ b/code/bash/03-terraform-state/user-data.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cat > index.html <Hello, World +

DB address: ${db_address}

+

DB port: ${db_port}

+EOF + +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/packer/01-why-terraform/webserver.json b/code/packer/01-why-terraform/webserver.json new file mode 100644 index 00000000..2b273c74 --- /dev/null +++ b/code/packer/01-why-terraform/webserver.json @@ -0,0 +1,19 @@ +{ + "builders": [{ + "ami_name": "packer-example", + "instance_type": "t2.micro", + "region": "us-east-1", + "type": "amazon-ebs", + "source_ami": "ami-40d28157", + "ssh_username": "ubuntu" + }], + "provisioners": [{ + "type": "shell", + "inline": [ + "sudo apt-get update", + "sudo apt-get install -y php", + "sudo apt-get install -y apache2", + "sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app" + ] + }] +} \ No newline at end of file diff --git a/code/ruby/06-terraform-team/terraform-test.rb b/code/ruby/06-terraform-team/terraform-test.rb new file mode 100644 index 00000000..03a4e75e --- /dev/null +++ b/code/ruby/06-terraform-team/terraform-test.rb @@ -0,0 +1,44 @@ +require 'net/http' + +if ARGV.length != 3 + raise 'Invalid args. Usage: terraform-test.rb REGION DB_BUCKET DB_KEY' +end + +vars = { + # A unique (ish) 6-char string: http://stackoverflow.com/a/88341/483528 + :cluster_name => (0...6).map { (65 + rand(26)).chr }.join, + :aws_region => ARGV[0], + :db_remote_state_bucket => ARGV[1], + :db_remote_state_key => ARGV[2], +} +vars_string = vars.map{|key, value| "-var '#{key} = \"#{value}\"'"}.join(', ') + +begin + puts "Deploying code in #{Dir.pwd}" + puts `terraform get 2>&1` + puts `terraform apply #{vars_string} 2>&1` + + elb_dns_name = `terraform output -no-color elb_dns_name` + url = "http://#{elb_dns_name}/" + + retries = 0 + loop do + retries += 1 + raise "Didn't get expected response after 10 retries" if retries > 10 + + puts "Checking #{url}" + output = Net::HTTP.get(url) + puts "Output: #{output}" + + if output.include? 'Hello, World' + puts 'Success!' + break + end + + puts 'Sleeping for 30 seconds and trying again' + sleep(30.seconds) + end +ensure + puts "Undeploying code in #{Dir.pwd}" + puts `terraform destroy -force #{vars_string} 2>&1` +end diff --git a/code/terraform/00-preface/hello-world/main.tf b/code/terraform/00-preface/hello-world/main.tf new file mode 100644 index 00000000..cb0beda6 --- /dev/null +++ b/code/terraform/00-preface/hello-world/main.tf @@ -0,0 +1,8 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" +} diff --git a/code/terraform/01-why-terraform/declarative-examples/part-1/main.tf b/code/terraform/01-why-terraform/declarative-examples/part-1/main.tf new file mode 100644 index 00000000..15f48de1 --- /dev/null +++ b/code/terraform/01-why-terraform/declarative-examples/part-1/main.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + count = 10 + ami = "ami-40d28157" + instance_type = "t2.micro" +} diff --git a/code/terraform/01-why-terraform/declarative-examples/part-2/main.tf b/code/terraform/01-why-terraform/declarative-examples/part-2/main.tf new file mode 100644 index 00000000..082785b7 --- /dev/null +++ b/code/terraform/01-why-terraform/declarative-examples/part-2/main.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + count = 15 + ami = "ami-40d28157" + instance_type = "t2.micro" +} diff --git a/code/terraform/01-why-terraform/declarative-examples/part-3/main.tf b/code/terraform/01-why-terraform/declarative-examples/part-3/main.tf new file mode 100644 index 00000000..8495c1a0 --- /dev/null +++ b/code/terraform/01-why-terraform/declarative-examples/part-3/main.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + count = 15 + ami = "ami-408c7f28" + instance_type = "t2.micro" +} diff --git a/code/terraform/01-why-terraform/multi-provider-example/main.tf b/code/terraform/01-why-terraform/multi-provider-example/main.tf new file mode 100644 index 00000000..fff4d36d --- /dev/null +++ b/code/terraform/01-why-terraform/multi-provider-example/main.tf @@ -0,0 +1,20 @@ +provider "aws" { + region = "us-east-1" +} + +provider "dnsimple" { + token = "fake-token" + email = "fake-email" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" +} + +resource "dnsimple_record" "example" { + domain = "example.com" + name = "test" + value = "${aws_instance.example.public_ip}" + type = "A" +} diff --git a/code/terraform/01-why-terraform/server-db-elb/main.tf b/code/terraform/01-why-terraform/server-db-elb/main.tf new file mode 100644 index 00000000..1d4ba6b1 --- /dev/null +++ b/code/terraform/01-why-terraform/server-db-elb/main.tf @@ -0,0 +1,36 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "app" { + instance_type = "t2.micro" + availability_zone = "us-east-1a" + ami = "ami-40d28157" + + user_data = <<-EOF + #!/bin/bash + sudo service apache2 start + EOF +} + +resource "aws_db_instance" "db" { + allocated_storage = 10 + engine = "mysql" + instance_class = "db.t2.micro" + name = "mydb" + username = "admin" + password = "password" +} + +resource "aws_elb" "load_balancer" { + name = "frontend-load-balancer" + instances = ["${aws_instance.app.id}"] + availability_zones = ["us-east-1a"] + + listener { + instance_port = 8000 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } +} diff --git a/code/terraform/02-intro-to-terraform-syntax/one-server/main.tf b/code/terraform/02-intro-to-terraform-syntax/one-server/main.tf new file mode 100644 index 00000000..fa6c37ad --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/one-server/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" + + tags { + name = "terraform-example" + } +} diff --git a/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/main.tf b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/main.tf new file mode 100644 index 00000000..29966707 --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/main.tf @@ -0,0 +1,30 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" + vpc_security_group_ids = ["${aws_security_group.instance.id}"] + + user_data = < index.html +nohup busybox httpd -f -p "${var.server_port}" & +EOF + + tags { + Name = "terraform-example" + } +} + +resource "aws_security_group" "instance" { + name = "terraform-example-instance" + + ingress { + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/outputs.tf b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/outputs.tf new file mode 100644 index 00000000..b3f622cb --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/outputs.tf @@ -0,0 +1,3 @@ +output "public_ip" { + value = "${aws_instance.example.public_ip}" +} diff --git a/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/vars.tf b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/vars.tf new file mode 100644 index 00000000..618dbc75 --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/one-webserver-with-vars/vars.tf @@ -0,0 +1,21 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} + +variable "list_example" { + description = "An example of a list in Terraform" + type = "list" + default = [1, 2, 3] +} + +variable "map_example" { + description = "An example of a map in Terraform" + type = "map" + + default = { + key1 = "value1" + key2 = "value2" + key3 = "value3" + } +} diff --git a/code/terraform/02-intro-to-terraform-syntax/one-webserver/main.tf b/code/terraform/02-intro-to-terraform-syntax/one-webserver/main.tf new file mode 100644 index 00000000..26b39f7d --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/one-webserver/main.tf @@ -0,0 +1,34 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" + vpc_security_group_ids = ["${aws_security_group.instance.id}"] + + user_data = <<-EOF + #!/bin/bash + echo "Hello, World" > index.html + nohup busybox httpd -f -p 8080 & + EOF + + tags { + Name = "terraform-example" + } +} + +resource "aws_security_group" "instance" { + name = "terraform-example-instance" + + ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +output "public_ip" { + value = "${aws_instance.example.public_ip}" +} diff --git a/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/main.tf b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/main.tf new file mode 100644 index 00000000..4ab2f86f --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/main.tf @@ -0,0 +1,92 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_launch_configuration" "example" { + image_id = "ami-40d28157" + instance_type = "t2.micro" + security_groups = ["${aws_security_group.instance.id}"] + + user_data = <<-EOF + #!/bin/bash + echo "Hello, World" > index.html + nohup busybox httpd -f -p "${var.server_port}" & + EOF + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_group" "example" { + launch_configuration = "${aws_launch_configuration.example.id}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + + load_balancers = ["${aws_elb.example.name}"] + health_check_type = "ELB" + + min_size = 2 + max_size = 10 + + tag { + key = "Name" + value = "terraform-asg-example" + propagate_at_launch = true + } +} + +resource "aws_security_group" "instance" { + name = "terraform-example-instance" + + ingress { + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + lifecycle { + create_before_destroy = true + } +} + +data "aws_availability_zones" "all" {} + +resource "aws_elb" "example" { + name = "terraform-asg-example" + availability_zones = ["${data.aws_availability_zones.all.names}"] + security_groups = ["${aws_security_group.elb.id}"] + + listener { + lb_port = 80 + lb_protocol = "http" + instance_port = "${var.server_port}" + instance_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + interval = 30 + target = "HTTP:${var.server_port}/" + } +} + +resource "aws_security_group" "elb" { + name = "terraform-example-elb" + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf new file mode 100644 index 00000000..dea652d5 --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${aws_elb.example.dns_name}" +} diff --git a/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/vars.tf b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/vars.tf new file mode 100644 index 00000000..e2846d60 --- /dev/null +++ b/code/terraform/02-intro-to-terraform-syntax/webserver-cluster/vars.tf @@ -0,0 +1,4 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} diff --git a/code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf b/code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf new file mode 100644 index 00000000..6d07833e --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf @@ -0,0 +1,15 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_s3_bucket" "terraform_state" { + bucket = "terraform-up-and-running-state" + + versioning { + enabled = true + } + + lifecycle { + prevent_destroy = true + } +} diff --git a/code/terraform/03-terraform-state/file-layout-example/global/s3/outputs.tf b/code/terraform/03-terraform-state/file-layout-example/global/s3/outputs.tf new file mode 100644 index 00000000..f30a7f49 --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/global/s3/outputs.tf @@ -0,0 +1,3 @@ +output "s3_bucket_arn" { + value = "${aws_s3_bucket.terraform_state.arn}" +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/main.tf b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/main.tf new file mode 100644 index 00000000..2bceaa2c --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/outputs.tf b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/vars.tf b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/main.tf b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/main.tf new file mode 100644 index 00000000..2300563e --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/main.tf @@ -0,0 +1,107 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_launch_configuration" "example" { + image_id = "ami-40d28157" + instance_type = "t2.micro" + security_groups = ["${aws_security_group.instance.id}"] + user_data = "${data.template_file.user_data.rendered}" + + lifecycle { + create_before_destroy = true + } +} + +data "template_file" "user_data" { + template = "${file("user-data.sh")}" + + vars { + server_port = "${var.server_port}" + db_address = "${data.terraform_remote_state.db.address}" + db_port = "${data.terraform_remote_state.db.port}" + } +} + +resource "aws_autoscaling_group" "example" { + launch_configuration = "${aws_launch_configuration.example.id}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + + load_balancers = ["${aws_elb.example.name}"] + health_check_type = "ELB" + + min_size = 2 + max_size = 10 + + tag { + key = "Name" + value = "terraform-asg-example" + propagate_at_launch = true + } +} + +resource "aws_security_group" "instance" { + name = "terraform-example-instance" + + ingress { + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + lifecycle { + create_before_destroy = true + } +} + +data "aws_availability_zones" "all" {} + +resource "aws_elb" "example" { + name = "terraform-asg-example" + availability_zones = ["${data.aws_availability_zones.all.names}"] + security_groups = ["${aws_security_group.elb.id}"] + + listener { + lb_port = 80 + lb_protocol = "http" + instance_port = "${var.server_port}" + instance_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + interval = 30 + target = "HTTP:${var.server_port}/" + } +} + +resource "aws_security_group" "elb" { + name = "terraform-example-elb" + + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +data "terraform_remote_state" "db" { + backend = "s3" + + config { + bucket = "${var.db_remote_state_bucket}" + key = "${var.db_remote_state_key}" + region = "us-east-1" + } +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/outputs.tf b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..dea652d5 --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${aws_elb.example.dns_name}" +} diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/user-data.sh b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/user-data.sh new file mode 100644 index 00000000..9fbcab53 --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/user-data.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cat > index.html <Hello, World +

DB address: ${db_address}

+

DB port: ${db_port}

+EOF + +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/vars.tf b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..0b556a0b --- /dev/null +++ b/code/terraform/03-terraform-state/file-layout-example/stage/services/webserver-cluster/vars.tf @@ -0,0 +1,12 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} + +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/main.tf b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/main.tf new file mode 100644 index 00000000..d14c55f9 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/main.tf @@ -0,0 +1,111 @@ +resource "aws_launch_configuration" "example" { + image_id = "ami-40d28157" + instance_type = "${var.instance_type}" + security_groups = ["${aws_security_group.instance.id}"] + user_data = "${data.template_file.user_data.rendered}" + + lifecycle { + create_before_destroy = true + } +} + +data "template_file" "user_data" { + template = "${file("${path.module}/user-data.sh")}" + + vars { + server_port = "${var.server_port}" + db_address = "${data.terraform_remote_state.db.address}" + db_port = "${data.terraform_remote_state.db.port}" + } +} + +resource "aws_autoscaling_group" "example" { + launch_configuration = "${aws_launch_configuration.example.id}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + load_balancers = ["${aws_elb.example.name}"] + health_check_type = "ELB" + + min_size = "${var.min_size}" + max_size = "${var.max_size}" + + tag { + key = "Name" + value = "${var.cluster_name}" + propagate_at_launch = true + } +} + +resource "aws_security_group" "instance" { + name = "${var.cluster_name}-instance" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_security_group_rule" "allow_server_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.instance.id}" + + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +data "aws_availability_zones" "all" {} + +resource "aws_elb" "example" { + name = "${var.cluster_name}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + security_groups = ["${aws_security_group.elb.id}"] + + listener { + lb_port = 80 + lb_protocol = "http" + instance_port = "${var.server_port}" + instance_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + interval = 30 + target = "HTTP:${var.server_port}/" + } +} + +resource "aws_security_group" "elb" { + name = "${var.cluster_name}-elb" +} + +resource "aws_security_group_rule" "allow_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +resource "aws_security_group_rule" "allow_all_outbound" { + type = "egress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] +} + +data "terraform_remote_state" "db" { + backend = "s3" + + config { + bucket = "${var.db_remote_state_bucket}" + key = "${var.db_remote_state_key}" + region = "us-east-1" + } +} diff --git a/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/outputs.tf b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..03c2a53e --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/outputs.tf @@ -0,0 +1,11 @@ +output "elb_dns_name" { + value = "${aws_elb.example.dns_name}" +} + +output "asg_name" { + value = "${aws_autoscaling_group.example.name}" +} + +output "elb_security_group_id" { + value = "${aws_security_group.elb.id}" +} diff --git a/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/user-data.sh b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/user-data.sh new file mode 100644 index 00000000..9fbcab53 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/user-data.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cat > index.html <Hello, World +

DB address: ${db_address}

+

DB port: ${db_port}

+EOF + +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/vars.tf b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..072968ba --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster/vars.tf @@ -0,0 +1,28 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} + +variable "cluster_name" { + description = "The name to use for all the cluster resources" +} + +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket for the database's remote state" +} + +variable "db_remote_state_key" { + description = "The path for the database's remote state in S3" +} + +variable "instance_type" { + description = "The type of EC2 Instances to run (e.g. t2.micro)" +} + +variable "min_size" { + description = "The minimum number of EC2 Instances in the ASG" +} + +variable "max_size" { + description = "The maximum number of EC2 Instances in the ASG" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/main.tf b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/main.tf new file mode 100644 index 00000000..c1f6658e --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_prod" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/outputs.tf b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/vars.tf b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/main.tf b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/main.tf new file mode 100644 index 00000000..6863e1b5 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/main.tf @@ -0,0 +1,35 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "../../../modules/services/webserver-cluster" + + cluster_name = "webservers-prod" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "m4.large" + min_size = 2 + max_size = 10 +} + +resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { + scheduled_action_name = "scale-out-during-business-hours" + min_size = 2 + max_size = 10 + desired_capacity = 10 + recurrence = "0 9 * * *" + + autoscaling_group_name = "${module.webserver_cluster.asg_name}" +} + +resource "aws_autoscaling_schedule" "scale_in_at_night" { + scheduled_action_name = "scale-in-at-night" + min_size = 2 + max_size = 10 + desired_capacity = 2 + recurrence = "0 17 * * *" + + autoscaling_group_name = "${module.webserver_cluster.asg_name}" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/outputs.tf b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/vars.tf b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/prod/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/main.tf b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/main.tf new file mode 100644 index 00000000..8d238b06 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_stage" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/outputs.tf b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/vars.tf b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf new file mode 100644 index 00000000..7ee64084 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf @@ -0,0 +1,25 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "../../../modules/services/webserver-cluster" + + cluster_name = "webservers-stage" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "t2.micro" + min_size = 2 + max_size = 2 +} + +resource "aws_security_group_rule" "allow_testing_inbound" { + type = "ingress" + security_group_id = "${module.webserver_cluster.elb_security_group_id}" + + from_port = 12345 + to_port = 12345 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} diff --git a/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/outputs.tf b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/vars.tf b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/main.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/main.tf new file mode 100644 index 00000000..c1f6658e --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_prod" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/outputs.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/vars.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/main.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/main.tf new file mode 100644 index 00000000..5c86fa93 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/main.tf @@ -0,0 +1,33 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "git@github.com:brikis98/terraform-up-and-running-code.git//04-terraform-module/module-example/modules/services/webserver-cluster?ref=v0.0.1" + + cluster_name = "webservers-prod" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "m4.large" + min_size = 2 + max_size = 10 +} + +resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { + scheduled_action_name = "scale-out-during-business-hours" + min_size = 2 + max_size = 10 + desired_capacity = 10 + recurrence = "0 9 * * *" + autoscaling_group_name = "${module.webserver_cluster.asg_name}" +} + +resource "aws_autoscaling_schedule" "scale_in_at_night" { + scheduled_action_name = "scale-in-at-night" + min_size = 2 + max_size = 10 + desired_capacity = 2 + recurrence = "0 17 * * *" + autoscaling_group_name = "${module.webserver_cluster.asg_name}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/outputs.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/vars.tf b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/prod/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/main.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/main.tf new file mode 100644 index 00000000..8d238b06 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_stage" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/outputs.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/vars.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/main.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/main.tf new file mode 100644 index 00000000..7b823fcc --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/main.tf @@ -0,0 +1,25 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "git@github.com:brikis98/terraform-up-and-running-code.git//04-terraform-module/module-example/modules/services/webserver-cluster?ref=v0.0.1" + + cluster_name = "webservers-stage" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "t2.micro" + min_size = 2 + max_size = 2 +} + +resource "aws_security_group_rule" "allow_testing_inbound" { + type = "ingress" + security_group_id = "${module.webserver_cluster.elb_security_group_id}" + + from_port = 12345 + to_port = 12345 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/outputs.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/vars.tf b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/04-terraform-module/multi-repo-example/live/stage/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/05-tips-and-tricks/live/global/existing-iam-user/main.tf b/code/terraform/05-tips-and-tricks/live/global/existing-iam-user/main.tf new file mode 100644 index 00000000..cbb17af6 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/existing-iam-user/main.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_iam_user" "existing_user" { + # TODO: you should change this to the username of an IAM user that already + # exists so you can practice using the terraform import command + name = "yevgeniy.brikman" +} diff --git a/code/terraform/05-tips-and-tricks/live/global/one-iam-user/main.tf b/code/terraform/05-tips-and-tricks/live/global/one-iam-user/main.tf new file mode 100644 index 00000000..74af8257 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/one-iam-user/main.tf @@ -0,0 +1,7 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_iam_user" "example" { + name = "neo" +} diff --git a/code/terraform/05-tips-and-tricks/live/global/three-iam-users-increment-name/main.tf b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-increment-name/main.tf new file mode 100644 index 00000000..e061c250 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-increment-name/main.tf @@ -0,0 +1,8 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_iam_user" "example" { + count = 3 + name = "neo.${count.index}" +} diff --git a/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/main.tf b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/main.tf new file mode 100644 index 00000000..959dcaf6 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/main.tf @@ -0,0 +1,67 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_iam_user" "example" { + count = "${length(var.user_names)}" + name = "${element(var.user_names, count.index)}" +} + +resource "aws_iam_policy" "ec2_read_only" { + name = "ec2-read-only" + policy = "${data.aws_iam_policy_document.ec2_read_only.json}" +} + +data "aws_iam_policy_document" "ec2_read_only" { + statement { + effect = "Allow" + actions = ["ec2:Describe*"] + resources = ["*"] + } +} + +resource "aws_iam_user_policy_attachment" "ec2_access" { + count = "${length(var.user_names)}" + user = "${element(aws_iam_user.example.*.name, count.index)}" + policy_arn = "${aws_iam_policy.ec2_read_only.arn}" +} + +resource "aws_iam_policy" "cloudwatch_read_only" { + name = "cloudwatch-read-only" + policy = "${data.aws_iam_policy_document.cloudwatch_read_only.json}" +} + +data "aws_iam_policy_document" "cloudwatch_read_only" { + statement { + effect = "Allow" + actions = ["cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*"] + resources = ["*"] + } +} + +resource "aws_iam_policy" "cloudwatch_full_access" { + name = "cloudwatch-full-access" + policy = "${data.aws_iam_policy_document.cloudwatch_full_access.json}" +} + +data "aws_iam_policy_document" "cloudwatch_full_access" { + statement { + effect = "Allow" + actions = ["cloudwatch:*"] + resources = ["*"] + } +} + +resource "aws_iam_user_policy_attachment" "neo_cloudwatch_full_access" { + count = "${var.give_neo_cloudwatch_full_access}" + + user = "${aws_iam_user.example.0.name}" + policy_arn = "${aws_iam_policy.cloudwatch_full_access.arn}" +} + +resource "aws_iam_user_policy_attachment" "neo_cloudwatch_read_only" { + count = "${1 - var.give_neo_cloudwatch_full_access}" + + user = "${aws_iam_user.example.0.name}" + policy_arn = "${aws_iam_policy.cloudwatch_read_only.arn}" +} diff --git a/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/outputs.tf b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/outputs.tf new file mode 100644 index 00000000..3b8bedc2 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/outputs.tf @@ -0,0 +1,7 @@ +output "neo_arn" { + value = "${aws_iam_user.example.0.arn}" +} + +output "all_arns" { + value = ["${aws_iam_user.example.*.arn}"] +} diff --git a/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/vars.tf b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/vars.tf new file mode 100644 index 00000000..10c8f772 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/global/three-iam-users-unique-names/vars.tf @@ -0,0 +1,9 @@ +variable "user_names" { + description = "Create IAM users with these names" + type = "list" + default = ["neo", "trinity", "morpheus"] +} + +variable "give_neo_cloudwatch_full_access" { + description = "If true, neo gets full access to CloudWatch" +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/main.tf b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/main.tf new file mode 100644 index 00000000..c1f6658e --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_prod" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/outputs.tf b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/vars.tf b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/main.tf b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/main.tf new file mode 100644 index 00000000..2ce162d9 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/main.tf @@ -0,0 +1,18 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "../../../../modules/services/webserver-cluster" + + cluster_name = "webservers-prod" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "m4.large" + min_size = 2 + max_size = 10 + + enable_autoscaling = true + enable_new_user_data = false +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/outputs.tf b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/vars.tf b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/prod/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/main.tf b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/main.tf new file mode 100644 index 00000000..8d238b06 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_stage" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/outputs.tf b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/vars.tf b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/main.tf b/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/main.tf new file mode 100644 index 00000000..ad88675e --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/main.tf @@ -0,0 +1,19 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + count = 3 + ami = "ami-40d28157" + instance_type = "t2.micro" +} + +data "aws_availability_zones" "all" {} + +resource "aws_instance" "example" { + count = "${var.num_availability_zones}" + availability_zone = "${element(data.aws_availability_zones.all.names, count.index)}" + + ami = "ami-40d28157" + instance_type = "t2.micro" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/vars.tf b/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/vars.tf new file mode 100644 index 00000000..91b0b567 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/services/multiple-ec2-instances/vars.tf @@ -0,0 +1,4 @@ +variable "num_availability_zones" { + description = "The number of Availability Zones in the AWS region" + default = 3 +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/main.tf b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/main.tf new file mode 100644 index 00000000..cd4187d7 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/main.tf @@ -0,0 +1,28 @@ +provider "aws" { + region = "us-east-1" +} + +module "webserver_cluster" { + source = "../../../../modules/services/webserver-cluster" + + cluster_name = "webservers-stage" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "t2.micro" + min_size = 2 + max_size = 2 + + enable_autoscaling = false + enable_new_user_data = true +} + +resource "aws_security_group_rule" "allow_testing_inbound" { + type = "ingress" + security_group_id = "${module.webserver_cluster.elb_security_group_id}" + + from_port = 12345 + to_port = 12345 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/outputs.tf b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/vars.tf b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..b30fd3dc --- /dev/null +++ b/code/terraform/05-tips-and-tricks/live/stage/services/webserver-cluster/vars.tf @@ -0,0 +1,7 @@ +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket used for the database's remote state storage" +} + +variable "db_remote_state_key" { + description = "The name of the key in the S3 bucket used for the database's remote state storage" +} diff --git a/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/main.tf b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/main.tf new file mode 100644 index 00000000..85eedd65 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/main.tf @@ -0,0 +1,186 @@ +resource "aws_launch_configuration" "example" { + image_id = "ami-40d28157" + instance_type = "${var.instance_type}" + security_groups = ["${aws_security_group.instance.id}"] + + user_data = "${element( + concat(data.template_file.user_data.*.rendered, + data.template_file.user_data_new.*.rendered), + 0)}" + + lifecycle { + create_before_destroy = true + } +} + +data "template_file" "user_data" { + count = "${1 - var.enable_new_user_data}" + + template = "${file("${path.module}/user-data.sh")}" + + vars { + server_port = "${var.server_port}" + db_address = "${data.terraform_remote_state.db.address}" + db_port = "${data.terraform_remote_state.db.port}" + } +} + +data "template_file" "user_data_new" { + count = "${var.enable_new_user_data}" + + template = "${file("${path.module}/user-data-new.sh")}" + + vars { + server_port = "${var.server_port}" + } +} + +resource "aws_autoscaling_group" "example" { + launch_configuration = "${aws_launch_configuration.example.id}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + load_balancers = ["${aws_elb.example.name}"] + health_check_type = "ELB" + + min_size = "${var.min_size}" + max_size = "${var.max_size}" + + tag { + key = "Name" + value = "${var.cluster_name}" + propagate_at_launch = true + } +} + +resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { + count = "${var.enable_autoscaling}" + + scheduled_action_name = "scale-out-during-business-hours" + min_size = 2 + max_size = 10 + desired_capacity = 10 + recurrence = "0 9 * * *" + autoscaling_group_name = "${aws_autoscaling_group.example.name}" +} + +resource "aws_autoscaling_schedule" "scale_in_at_night" { + count = "${var.enable_autoscaling}" + + scheduled_action_name = "scale-in-at-night" + min_size = 2 + max_size = 10 + desired_capacity = 2 + recurrence = "0 17 * * *" + autoscaling_group_name = "${aws_autoscaling_group.example.name}" +} + +resource "aws_security_group" "instance" { + name = "${var.cluster_name}-instance" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_security_group_rule" "allow_server_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.instance.id}" + + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +data "aws_availability_zones" "all" {} + +resource "aws_elb" "example" { + name = "${var.cluster_name}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + security_groups = ["${aws_security_group.elb.id}"] + + listener { + lb_port = 80 + lb_protocol = "http" + instance_port = "${var.server_port}" + instance_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + interval = 30 + target = "HTTP:${var.server_port}/" + } +} + +resource "aws_security_group" "elb" { + name = "${var.cluster_name}-elb" +} + +resource "aws_security_group_rule" "allow_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +resource "aws_security_group_rule" "allow_all_outbound" { + type = "egress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] +} + +data "terraform_remote_state" "db" { + backend = "s3" + + config { + bucket = "${var.db_remote_state_bucket}" + key = "${var.db_remote_state_key}" + region = "us-east-1" + } +} + +resource "aws_cloudwatch_metric_alarm" "high_cpu_utilization" { + alarm_name = "${var.cluster_name}-high-cpu-utilization" + namespace = "AWS/EC2" + metric_name = "CPUUtilization" + + dimensions = { + AutoScalingGroupName = "${aws_autoscaling_group.example.name}" + } + + comparison_operator = "GreaterThanThreshold" + evaluation_periods = 1 + period = 300 + statistic = "Average" + threshold = 90 + unit = "Percent" +} + +resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { + count = "${replace(replace(var.instance_type, "/^[^t].*/", "0"), + "/^t.*$/", "1")}" + + alarm_name = "${var.cluster_name}-low-cpu-credit-balance" + namespace = "AWS/EC2" + metric_name = "CPUCreditBalance" + + dimensions = { + AutoScalingGroupName = "${aws_autoscaling_group.example.name}" + } + + comparison_operator = "LessThanThreshold" + evaluation_periods = 1 + period = 300 + statistic = "Minimum" + threshold = 10 + unit = "Count" +} diff --git a/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/outputs.tf b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..03c2a53e --- /dev/null +++ b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/outputs.tf @@ -0,0 +1,11 @@ +output "elb_dns_name" { + value = "${aws_elb.example.dns_name}" +} + +output "asg_name" { + value = "${aws_autoscaling_group.example.name}" +} + +output "elb_security_group_id" { + value = "${aws_security_group.elb.id}" +} diff --git a/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data-new.sh b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data-new.sh new file mode 100644 index 00000000..07cfd885 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data-new.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "Hello, World, v2" > index.html +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data.sh b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data.sh new file mode 100644 index 00000000..9fbcab53 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/user-data.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cat > index.html <Hello, World +

DB address: ${db_address}

+

DB port: ${db_port}

+EOF + +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/vars.tf b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..e4b60f10 --- /dev/null +++ b/code/terraform/05-tips-and-tricks/modules/services/webserver-cluster/vars.tf @@ -0,0 +1,36 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} + +variable "cluster_name" { + description = "The name to use for all the cluster resources" +} + +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket for the database's remote state" +} + +variable "db_remote_state_key" { + description = "The path for the database's remote state in S3" +} + +variable "instance_type" { + description = "The type of EC2 Instances to run (e.g. t2.micro)" +} + +variable "min_size" { + description = "The minimum number of EC2 Instances in the ASG" +} + +variable "max_size" { + description = "The maximum number of EC2 Instances in the ASG" +} + +variable "enable_autoscaling" { + description = "If set to true, enable auto scaling" +} + +variable "enable_new_user_data" { + description = "If set to true, use the new User Data script" +} diff --git a/code/terraform/06-terraform-team/live/prod/data-stores/mysql/main.tf b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/main.tf new file mode 100644 index 00000000..c1f6658e --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_prod" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/06-terraform-team/live/prod/data-stores/mysql/outputs.tf b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/06-terraform-team/live/prod/data-stores/mysql/vars.tf b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/06-terraform-team/live/prod/services/microservices-example/main.tf b/code/terraform/06-terraform-team/live/prod/services/microservices-example/main.tf new file mode 100644 index 00000000..cdd3e74a --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/services/microservices-example/main.tf @@ -0,0 +1,33 @@ +provider "aws" { + region = "us-east-1" +} + +module "search_service" { + source = "../../../../modules/services/webserver-cluster" + + cluster_name = "search-service-prod" + db_remote_state_bucket = "(YOUR_BUCKET_NAME)" + db_remote_state_key = "prod/data-stores/mysql/terraform.tfstate" + + instance_type = "x1.16xlarge" + min_size = 4 + max_size = 4 + + enable_autoscaling = false + enable_new_user_data = false +} + +module "profile_service" { + source = "../../../../modules/services/webserver-cluster" + + cluster_name = "profile-service-prod" + db_remote_state_bucket = "(YOUR_BUCKET_NAME)" + db_remote_state_key = "prod/data-stores/mysql/terraform.tfstate" + + instance_type = "m4.large" + min_size = 12 + max_size = 40 + + enable_autoscaling = true + enable_new_user_data = true +} diff --git a/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/main.tf b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/main.tf new file mode 100644 index 00000000..601fc20f --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/main.tf @@ -0,0 +1,19 @@ +provider "aws" { + region = "${var.aws_region}" +} + +module "webserver_cluster" { + source = "../../../../modules/services/webserver-cluster" + + aws_region = "${var.aws_region}" + cluster_name = "${var.cluster_name}" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "m4.large" + min_size = 2 + max_size = 10 + + enable_autoscaling = true + enable_new_user_data = false +} diff --git a/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/outputs.tf b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/vars.tf b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..646805de --- /dev/null +++ b/code/terraform/06-terraform-team/live/prod/services/webserver-cluster/vars.tf @@ -0,0 +1,18 @@ +variable "aws_region" { + description = "The AWS region to use" + default = "us-east-1" +} + +variable "cluster_name" { + description = "The name to use for all the cluster resources" + default = "webservers-prod" +} + +variable "db_remote_state_bucket" { + description = "The S3 bucket used for the database's remote state" +} + +variable "db_remote_state_key" { + description = "The path for the database's remote state in S3" + default = "prod/data-stores/mysql/terraform.tfstate" +} diff --git a/code/terraform/06-terraform-team/live/stage/data-stores/mysql/main.tf b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/main.tf new file mode 100644 index 00000000..8d238b06 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_db_instance" "example" { + engine = "mysql" + allocated_storage = 10 + instance_class = "db.t2.micro" + name = "example_database_stage" + username = "admin" + password = "${var.db_password}" +} diff --git a/code/terraform/06-terraform-team/live/stage/data-stores/mysql/outputs.tf b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/outputs.tf new file mode 100644 index 00000000..b8b44483 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/outputs.tf @@ -0,0 +1,7 @@ +output "address" { + value = "${aws_db_instance.example.address}" +} + +output "port" { + value = "${aws_db_instance.example.port}" +} diff --git a/code/terraform/06-terraform-team/live/stage/data-stores/mysql/vars.tf b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/vars.tf new file mode 100644 index 00000000..f63443c2 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/data-stores/mysql/vars.tf @@ -0,0 +1,3 @@ +variable "db_password" { + description = "The password for the database" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/automated-deployment/main.tf b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/main.tf new file mode 100644 index 00000000..d96decfe --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/main.tf @@ -0,0 +1,8 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "${var.version}" + instance_type = "t2.micro" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars new file mode 100644 index 00000000..8c3e54ee --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars @@ -0,0 +1 @@ +version = "ami-40d28157" \ No newline at end of file diff --git a/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars.json b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars.json new file mode 100644 index 00000000..af83741d --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/terraform.tfvars.json @@ -0,0 +1,3 @@ +{ + "version": "ami-40d28157" +} \ No newline at end of file diff --git a/code/terraform/06-terraform-team/live/stage/services/automated-deployment/vars.tf b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/vars.tf new file mode 100644 index 00000000..3276210e --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/automated-deployment/vars.tf @@ -0,0 +1,4 @@ +variable "version" { + description = "The version of the app to deploy" + default = "ami-40d28157" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/conflict-anna/main.tf b/code/terraform/06-terraform-team/live/stage/services/conflict-anna/main.tf new file mode 100644 index 00000000..62f19b2d --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/conflict-anna/main.tf @@ -0,0 +1,8 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.medium" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/conflict-bill/main.tf b/code/terraform/06-terraform-team/live/stage/services/conflict-bill/main.tf new file mode 100644 index 00000000..f0ffd1b2 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/conflict-bill/main.tf @@ -0,0 +1,12 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" + + tags { + Name = "foo" + } +} diff --git a/code/terraform/06-terraform-team/live/stage/services/conflict-original/main.tf b/code/terraform/06-terraform-team/live/stage/services/conflict-original/main.tf new file mode 100644 index 00000000..cb0beda6 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/conflict-original/main.tf @@ -0,0 +1,8 @@ +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "example" { + ami = "ami-40d28157" + instance_type = "t2.micro" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/main.tf b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/main.tf new file mode 100644 index 00000000..b6c52dcc --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/main.tf @@ -0,0 +1,29 @@ +provider "aws" { + region = "${var.aws_region}" +} + +module "webserver_cluster" { + source = "../../../../modules/services/webserver-cluster" + + aws_region = "${var.aws_region}" + cluster_name = "${var.cluster_name}" + db_remote_state_bucket = "${var.db_remote_state_bucket}" + db_remote_state_key = "${var.db_remote_state_key}" + + instance_type = "t2.micro" + min_size = 2 + max_size = 2 + + enable_autoscaling = false + enable_new_user_data = true +} + +resource "aws_security_group_rule" "allow_testing_inbound" { + type = "ingress" + security_group_id = "${module.webserver_cluster.elb_security_group_id}" + + from_port = 12345 + to_port = 12345 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} diff --git a/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/outputs.tf b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..7a9789b3 --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/outputs.tf @@ -0,0 +1,3 @@ +output "elb_dns_name" { + value = "${module.webserver_cluster.elb_dns_name}" +} diff --git a/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/vars.tf b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..0667660e --- /dev/null +++ b/code/terraform/06-terraform-team/live/stage/services/webserver-cluster/vars.tf @@ -0,0 +1,18 @@ +variable "aws_region" { + description = "The AWS region to use" + default = "us-east-1" +} + +variable "cluster_name" { + description = "The name to use for all the cluster resources" + default = "webservers-stage" +} + +variable "db_remote_state_bucket" { + description = "The S3 bucket used for the database's remote state" +} + +variable "db_remote_state_key" { + description = "The path for the database's remote state in S3" + default = "stage/data-stores/mysql/terraform.tfstate" +} diff --git a/code/terraform/06-terraform-team/modules/services/webserver-cluster/main.tf b/code/terraform/06-terraform-team/modules/services/webserver-cluster/main.tf new file mode 100644 index 00000000..101aa336 --- /dev/null +++ b/code/terraform/06-terraform-team/modules/services/webserver-cluster/main.tf @@ -0,0 +1,211 @@ +resource "aws_launch_configuration" "example" { + image_id = "${data.aws_ami.ubuntu.id}" + instance_type = "${var.instance_type}" + security_groups = ["${aws_security_group.instance.id}"] + + user_data = "${element( + concat(data.template_file.user_data.*.rendered, + data.template_file.user_data_new.*.rendered), + 0)}" + + lifecycle { + create_before_destroy = true + } +} + +data "aws_ami" "ubuntu" { + most_recent = true + owners = ["099720109477"] # Canonical + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + filter { + name = "architecture" + values = ["x86_64"] + } + + filter { + name = "image-type" + values = ["machine"] + } + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"] + } +} + +data "template_file" "user_data" { + count = "${1 - var.enable_new_user_data}" + + template = "${file("${path.module}/user-data.sh")}" + + vars { + server_port = "${var.server_port}" + db_address = "${data.terraform_remote_state.db.address}" + db_port = "${data.terraform_remote_state.db.port}" + } +} + +data "template_file" "user_data_new" { + count = "${var.enable_new_user_data}" + + template = "${file("${path.module}/user-data-new.sh")}" + + vars { + server_port = "${var.server_port}" + } +} + +resource "aws_autoscaling_group" "example" { + launch_configuration = "${aws_launch_configuration.example.id}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + load_balancers = ["${aws_elb.example.name}"] + health_check_type = "ELB" + + min_size = "${var.min_size}" + max_size = "${var.max_size}" + + tag { + key = "Name" + value = "${var.cluster_name}" + propagate_at_launch = true + } +} + +resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { + count = "${var.enable_autoscaling}" + + scheduled_action_name = "scale-out-during-business-hours" + min_size = 2 + max_size = 10 + desired_capacity = 10 + recurrence = "0 9 * * *" + autoscaling_group_name = "${aws_autoscaling_group.example.name}" +} + +resource "aws_autoscaling_schedule" "scale_in_at_night" { + count = "${var.enable_autoscaling}" + + scheduled_action_name = "scale-in-at-night" + min_size = 2 + max_size = 10 + desired_capacity = 2 + recurrence = "0 17 * * *" + autoscaling_group_name = "${aws_autoscaling_group.example.name}" +} + +resource "aws_security_group" "instance" { + name = "${var.cluster_name}-instance" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_security_group_rule" "allow_server_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.instance.id}" + + from_port = "${var.server_port}" + to_port = "${var.server_port}" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +data "aws_availability_zones" "all" {} + +resource "aws_elb" "example" { + name = "${var.cluster_name}" + availability_zones = ["${data.aws_availability_zones.all.names}"] + security_groups = ["${aws_security_group.elb.id}"] + + listener { + lb_port = 80 + lb_protocol = "http" + instance_port = "${var.server_port}" + instance_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + interval = 30 + target = "HTTP:${var.server_port}/" + } +} + +resource "aws_security_group" "elb" { + name = "${var.cluster_name}-elb" +} + +resource "aws_security_group_rule" "allow_http_inbound" { + type = "ingress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] +} + +resource "aws_security_group_rule" "allow_all_outbound" { + type = "egress" + security_group_id = "${aws_security_group.elb.id}" + + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] +} + +data "terraform_remote_state" "db" { + backend = "s3" + + config { + bucket = "${var.db_remote_state_bucket}" + key = "${var.db_remote_state_key}" + region = "${var.aws_region}" + } +} + +resource "aws_cloudwatch_metric_alarm" "high_cpu_utilization" { + alarm_name = "${var.cluster_name}-high-cpu-utilization" + namespace = "AWS/EC2" + metric_name = "CPUUtilization" + + dimensions = { + AutoScalingGroupName = "${aws_autoscaling_group.example.name}" + } + + comparison_operator = "GreaterThanThreshold" + evaluation_periods = 1 + period = 300 + statistic = "Average" + threshold = 90 + unit = "Percent" +} + +resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { + count = "${replace(replace(var.instance_type, "/^[^t].*/", "0"), + "/^t.*$/", "1")}" + + alarm_name = "${var.cluster_name}-low-cpu-credit-balance" + namespace = "AWS/EC2" + metric_name = "CPUCreditBalance" + + dimensions = { + AutoScalingGroupName = "${aws_autoscaling_group.example.name}" + } + + comparison_operator = "LessThanThreshold" + evaluation_periods = 1 + period = 300 + statistic = "Minimum" + threshold = 10 + unit = "Count" +} diff --git a/code/terraform/06-terraform-team/modules/services/webserver-cluster/outputs.tf b/code/terraform/06-terraform-team/modules/services/webserver-cluster/outputs.tf new file mode 100644 index 00000000..03c2a53e --- /dev/null +++ b/code/terraform/06-terraform-team/modules/services/webserver-cluster/outputs.tf @@ -0,0 +1,11 @@ +output "elb_dns_name" { + value = "${aws_elb.example.dns_name}" +} + +output "asg_name" { + value = "${aws_autoscaling_group.example.name}" +} + +output "elb_security_group_id" { + value = "${aws_security_group.elb.id}" +} diff --git a/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data-new.sh b/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data-new.sh new file mode 100644 index 00000000..07cfd885 --- /dev/null +++ b/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data-new.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "Hello, World, v2" > index.html +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data.sh b/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data.sh new file mode 100644 index 00000000..9fbcab53 --- /dev/null +++ b/code/terraform/06-terraform-team/modules/services/webserver-cluster/user-data.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cat > index.html <Hello, World +

DB address: ${db_address}

+

DB port: ${db_port}

+EOF + +nohup busybox httpd -f -p "${server_port}" & diff --git a/code/terraform/06-terraform-team/modules/services/webserver-cluster/vars.tf b/code/terraform/06-terraform-team/modules/services/webserver-cluster/vars.tf new file mode 100644 index 00000000..bb4d075f --- /dev/null +++ b/code/terraform/06-terraform-team/modules/services/webserver-cluster/vars.tf @@ -0,0 +1,40 @@ +variable "server_port" { + description = "The port the server will use for HTTP requests" + default = 8080 +} + +variable "cluster_name" { + description = "The name to use for all the cluster resources" +} + +variable "db_remote_state_bucket" { + description = "The name of the S3 bucket for the database's remote state" +} + +variable "db_remote_state_key" { + description = "The path for the database's remote state in S3" +} + +variable "instance_type" { + description = "The type of EC2 Instances to run (e.g. t2.micro)" +} + +variable "min_size" { + description = "The minimum number of EC2 Instances in the ASG" +} + +variable "max_size" { + description = "The maximum number of EC2 Instances in the ASG" +} + +variable "enable_autoscaling" { + description = "If set to true, enable auto scaling" +} + +variable "enable_new_user_data" { + description = "If set to true, use the new User Data script" +} + +variable "aws_region" { + description = "The AWS region to use" +}