diff --git a/.gitignore b/.gitignore index 3300a23..90f7941 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ Gemfile.lock .bundle vendor +terraform.tfvars +terraform.tfstate* +.terraform* diff --git a/infra/cloud-init.yaml b/infra/cloud-init.yaml new file mode 100644 index 0000000..04c8f43 --- /dev/null +++ b/infra/cloud-init.yaml @@ -0,0 +1,30 @@ +#cloud-config + +coreos: + update: + reboot-strategy: "off" + units: + - name: etcd2.service + command: stop + - name: fleet.service + command: stop + - name: flanneld.service + command: stop + + - name: nginx.service + command: start + enable: true + type: simple + content: | + [Unit] + Description=Runs nginx + After=docker.service + [Service] + ExecStart=/usr/bin/docker run --name nginx -p 8000:80 nginx + ExecStop=/usr/bin/docker stop nginx + ExecStop=/usr/bin/docker rm -f nginx + +users: + - name: core + coreos-ssh-import-github: ${github_handle} + diff --git a/infra/ec2.tf b/infra/ec2.tf new file mode 100644 index 0000000..2e6e49e --- /dev/null +++ b/infra/ec2.tf @@ -0,0 +1,42 @@ +resource "aws_instance" "nginx" { + ami = "${data.aws_ami.coreos.id}" + instance_type = "t2.small" + subnet_id = "${aws_subnet.subnet.id}" + associate_public_ip_address = true + vpc_security_group_ids = ["${aws_security_group.sg.id}"] + user_data = "${data.template_file.user_data.rendered}" + + tags { + Name = "${var.name}" + owner = "${var.owner}" + } +} + +data "template_file" "user_data" { + template = "${file("${path.module}/cloud-init.yaml")}" + + vars { + github_handle = "${var.github_handle}" + } +} + +data "aws_ami" "coreos" { + most_recent = true + + owners = ["595879546273"] + + filter { + name = "architecture" + values = ["x86_64"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + filter { + name = "name" + values = ["CoreOS-stable-*"] + } +} diff --git a/infra/elb.tf b/infra/elb.tf new file mode 100644 index 0000000..925e261 --- /dev/null +++ b/infra/elb.tf @@ -0,0 +1,32 @@ +resource "aws_elb" "elb" { + subnets = ["${aws_subnet.subnet.id}"] + security_groups = ["${aws_security_group.sg.id}"] + + access_logs { + bucket = "${aws_s3_bucket.bucket.id}" + bucket_prefix = "logs" + interval = 5 # minutes + } + + listener { + instance_port = 8000 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } + + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + target = "HTTP:8000/" + interval = 30 + } + + instances = ["${aws_instance.nginx.id}"] + + tags { + Name = "${var.name}" + owner = "${var.owner}" + } +} diff --git a/infra/outputs.tf b/infra/outputs.tf new file mode 100644 index 0000000..309d2e8 --- /dev/null +++ b/infra/outputs.tf @@ -0,0 +1,7 @@ +output "instance_ip" { + value = "${aws_instance.nginx.public_ip}" +} + +output "elb_dns_name" { + value = "${aws_elb.elb.dns_name}" +} diff --git a/infra/provider.tf b/infra/provider.tf new file mode 100644 index 0000000..0977ba5 --- /dev/null +++ b/infra/provider.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "${var.region}" +} diff --git a/infra/s3.tf b/infra/s3.tf new file mode 100644 index 0000000..8bf84b4 --- /dev/null +++ b/infra/s3.tf @@ -0,0 +1,45 @@ +resource "aws_s3_bucket" "bucket" { + bucket = "${var.s3_bucket}" + acl = "private" + + tags { + Name = "${var.name}" + onwer = "${var.owner}" + } +} + +resource "aws_s3_bucket_policy" "write_elb_logs" { + bucket = "${aws_s3_bucket.bucket.id}" + policy = "${data.aws_iam_policy_document.push_elb_logs.json}" +} + +data "aws_elb_service_account" "main" {} + +data "aws_iam_policy_document" "push_elb_logs" { + statement { + sid = "PushELBLogsToS3" + + actions = [ + "s3:PutObject", + ] + + resources = [ + "arn:aws:s3:::${var.s3_bucket}/*", + ] + + principals { + type = "AWS" + identifiers = ["${data.aws_elb_service_account.main.arn}"] + } + } +} + +resource "aws_s3_bucket_notification" "bucket_notification" { + bucket = "${aws_s3_bucket.bucket.id}" + + queue { + queue_arn = "${aws_sqs_queue.elb_log_queue.arn}" + events = ["s3:ObjectCreated:*"] + filter_suffix = ".log" + } +} diff --git a/infra/sg.tf b/infra/sg.tf new file mode 100644 index 0000000..c670b56 --- /dev/null +++ b/infra/sg.tf @@ -0,0 +1,33 @@ +resource "aws_security_group" "sg" { + name_prefix = "${var.name}-" + description = "Default Security group for ${var.name}" + vpc_id = "${aws_vpc.vpc.id}" + + tags { + managed-by = "terraform" + owner = "${var.owner}" + } + + lifecycle { + create_before_destroy = true + } + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Description = "Default Security group for ${var.name}" + } +} diff --git a/infra/sqs.tf b/infra/sqs.tf new file mode 100644 index 0000000..0ecf466 --- /dev/null +++ b/infra/sqs.tf @@ -0,0 +1,28 @@ +resource "aws_sqs_queue" "elb_log_queue" { + name_prefix = "elb-log-queue-" + message_retention_seconds = 86400 +} + +data "aws_iam_policy_document" "elb_notify_sqs" { + statement { + actions = ["sqs:SendMessage"] + resources = ["${aws_sqs_queue.elb_log_queue.arn}"] + effect = "Allow" + + principals { + type = "Service" + identifiers = ["s3.amazonaws.com"] + } + + condition = { + test = "ArnEquals" + variable = "aws:SourceArn" + values = ["arn:aws:s3:::${var.s3_bucket}"] + } + } +} + +resource "aws_sqs_queue_policy" "sqs_policy" { + queue_url = "${aws_sqs_queue.elb_log_queue.id}" + policy = "${data.aws_iam_policy_document.elb_notify_sqs.json}" +} diff --git a/infra/variables.tf b/infra/variables.tf new file mode 100644 index 0000000..7baacf7 --- /dev/null +++ b/infra/variables.tf @@ -0,0 +1,19 @@ +variable "name" { + default = "logstash" +} + +variable "owner" { + default = "logstash" +} + +variable "s3_bucket" { + default = "your-bucket" +} + +variable "github_handle" { + default = "pmoust" +} + +variable "region" { + default = "us-east-1" +} diff --git a/infra/vpc.tf b/infra/vpc.tf new file mode 100644 index 0000000..1001a43 --- /dev/null +++ b/infra/vpc.tf @@ -0,0 +1,67 @@ +resource "aws_vpc" "vpc" { + cidr_block = "10.0.0.0/16" + + tags { + Name = "${var.name}" + managed-by = "terraform" + owned-by = "${var.owner}" + created-on = "${timestamp()}" + } + + lifecycle { + create_before_destroy = true + ignore_changes = ["tags"] + } +} + +resource "aws_internet_gateway" "igw" { + vpc_id = "${aws_vpc.vpc.id}" + + tags { + Name = "${var.name}" + managed-by = "terraform" + owner = "${var.owner}" + } +} + +resource "aws_subnet" "subnet" { + vpc_id = "${aws_vpc.vpc.id}" + cidr_block = "10.0.0.0/24" + + map_public_ip_on_launch = true + + tags { + Name = "${var.name}" + managed-by = "terraform" + owner = "${var.owner}" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_route_table" "rt" { + vpc_id = "${aws_vpc.vpc.id}" + + tags { + Name = "${var.name}" + managed-by = "terraform" + owned-by = "${var.owner}" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_route" "default" { + route_table_id = "${aws_route_table.rt.id}" + destination_cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.igw.id}" +} + +resource "aws_route_table_association" "rta" { + subnet_id = "${aws_subnet.subnet.id}" + route_table_id = "${aws_route_table.rt.id}" +} diff --git a/terraform.tfvars.example b/terraform.tfvars.example new file mode 100644 index 0000000..af45007 --- /dev/null +++ b/terraform.tfvars.example @@ -0,0 +1,4 @@ +name = "logstash" +owner = "logstash" +s3_bucket = "my-lovely-bucket-yo" +github_handle = "pmoust" diff --git a/test.tf b/test.tf new file mode 100644 index 0000000..eed35e8 --- /dev/null +++ b/test.tf @@ -0,0 +1,21 @@ +variable "s3_bucket" {} +variable "name" {} +variable "owner" {} +variable "github_handle" {} + +output "instance_ip" { + value = "${module.infra.instance_ip}" +} + +output "elb_dns_name" { + value = "${module.infra.elb_dns_name}" +} + +module "infra" { + source = "./infra" + + s3_bucket = "${var.s3_bucket}" + name = "${var.name}" + owner = "${var.owner}" + github_handle = "${var.github_handle}" +}