Skip to content

Commit a7bc774

Browse files
Jamie-BitFlightaknysh
authored andcommitted
Implement Instance Groups (#1)
* Original code from terraform-aws-ec2-instance * Fixed issues when switching between 0 and 1+ instances. between applys. * Fixed output errors * Updated to use lists for all list outputs. Updated README. * Added clarity to README * Added consistancy to the outputs and README * Updated eni * Updated to address change suggestions. * Updated examples to use fixed values in README
1 parent fd23fb4 commit a7bc774

File tree

10 files changed

+984
-10
lines changed

10 files changed

+984
-10
lines changed

.gitignore

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# Local .terraform directories
2-
**/.terraform/*
3-
4-
# .tfstate files
5-
*.tfstate
6-
*.tfstate.*
7-
8-
# .tfvars files
9-
*.tfvars
1+
# Module directory
2+
**/.terraform/
3+
.idea
4+
*.iml
5+
**/terraform.tfstate
6+
**/terraform.tfstate.backup
7+
**/terraform.tfvars
8+
**/*.pem
9+
**/*.pub

README.md

Lines changed: 234 additions & 1 deletion
Large diffs are not rendered by default.

cloud_watch_alarm.tf

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Restart dead or hung instance
2+
3+
locals {
4+
action = "arn:aws:swf:${var.region}:${data.aws_caller_identity.default.account_id}:${var.default_alarm_action}"
5+
}
6+
7+
resource "aws_cloudwatch_metric_alarm" "default" {
8+
count = "${local.instance_count}"
9+
alarm_name = "${module.label.id}-${count.index}"
10+
comparison_operator = "${var.comparison_operator}"
11+
evaluation_periods = "${var.evaluation_periods}"
12+
metric_name = "${var.metric_name}"
13+
namespace = "${var.metric_namespace}"
14+
period = "${var.applying_period}"
15+
statistic = "${var.statistic_level}"
16+
threshold = "${var.metric_threshold}"
17+
18+
dimensions {
19+
InstanceId = "${element(sort(aws_instance.default.*.id), count.index)}"
20+
}
21+
22+
alarm_actions = [
23+
"${local.action}",
24+
]
25+
}

eni.tf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
locals {
2+
additional_ips_count = "${var.associate_public_ip_address == "true" && var.instance_enabled == "true" && var.additional_ips_count > 0 ? var.additional_ips_count : 0}"
3+
}
4+
5+
resource "aws_network_interface" "additional" {
6+
count = "${local.additional_ips_count * var.instance_count}"
7+
subnet_id = "${var.subnet}"
8+
9+
security_groups = [
10+
"${compact(concat(list(var.create_default_security_group == "true" ? join("", aws_security_group.default.*.id) : ""), var.security_groups))}",
11+
]
12+
13+
tags = "${module.label.tags}"
14+
depends_on = ["aws_instance.default"]
15+
}
16+
17+
resource "aws_network_interface_attachment" "additional" {
18+
count = "${local.additional_ips_count * var.instance_count}"
19+
instance_id = "${element(aws_instance.default.*.id, count.index % var.instance_count)}"
20+
network_interface_id = "${element(aws_network_interface.additional.*.id, count.index)}"
21+
device_index = "${1 + count.index}"
22+
depends_on = ["aws_instance.default"]
23+
}
24+
25+
resource "aws_eip" "additional" {
26+
count = "${local.additional_ips_count * var.instance_count}"
27+
vpc = "true"
28+
network_interface = "${element(aws_network_interface.additional.*.id, count.index)}"
29+
depends_on = ["aws_instance.default"]
30+
}

examples/main.tf

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
data "aws_region" "default" {}
2+
3+
data "aws_subnet" "default" {
4+
id = "${data.aws_subnet_ids.all.ids[0]}"
5+
}
6+
7+
data "aws_vpc" "default" {
8+
default = true
9+
}
10+
11+
data "aws_subnet_ids" "all" {
12+
vpc_id = "${data.aws_vpc.default.id}"
13+
}
14+
15+
provider "aws" {
16+
region = "us-east-1"
17+
}
18+
19+
data "aws_ami" "ubuntu" {
20+
most_recent = true
21+
22+
filter {
23+
name = "name"
24+
values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"]
25+
}
26+
27+
filter {
28+
name = "virtualization-type"
29+
values = ["hvm"]
30+
}
31+
32+
owners = ["099720109477"] # Canonical
33+
}
34+
35+
module "zero_servers" {
36+
source = "../"
37+
38+
instance_count = "0"
39+
ami = "${data.aws_ami.ubuntu.id}"
40+
namespace = "cp"
41+
stage = "prod"
42+
name = "zero"
43+
44+
create_default_security_group = "true"
45+
region = "${data.aws_region.default.name}"
46+
availability_zone = "${data.aws_subnet.default.availability_zone}"
47+
subnet = "${data.aws_subnet.default.id}"
48+
vpc_id = "${data.aws_vpc.default.id}"
49+
generate_ssh_key_pair = "true"
50+
}
51+
52+
module "one_server" {
53+
source = "../"
54+
55+
instance_count = "1"
56+
ami = "${data.aws_ami.ubuntu.id}"
57+
namespace = "cp"
58+
stage = "prod"
59+
name = "one"
60+
61+
create_default_security_group = "true"
62+
region = "${data.aws_region.default.name}"
63+
availability_zone = "${data.aws_subnet.default.availability_zone}"
64+
subnet = "${data.aws_subnet.default.id}"
65+
vpc_id = "${data.aws_vpc.default.id}"
66+
additional_ips_count = "1"
67+
generate_ssh_key_pair = "true"
68+
instance_type = "m1.large" // Allows up to 3 ENI, the default t2.micro allows only 1
69+
}
70+
71+
module "two_servers" {
72+
source = "../"
73+
74+
instance_count = "2"
75+
ami = "${data.aws_ami.ubuntu.id}"
76+
namespace = "cp"
77+
stage = "prod"
78+
name = "two"
79+
80+
create_default_security_group = "true"
81+
region = "${data.aws_region.default.name}"
82+
availability_zone = "${data.aws_subnet.default.availability_zone}"
83+
subnet = "${data.aws_subnet.default.id}"
84+
vpc_id = "${data.aws_vpc.default.id}"
85+
additional_ips_count = "1"
86+
generate_ssh_key_pair = "true"
87+
instance_type = "m1.large" // Allows up to 3 ENI, the default t2.micro allows only 1
88+
}
89+
90+
output "public_dns" {
91+
value = {
92+
zero = "${module.zero_servers.public_dns}"
93+
one = "${module.one_server.public_dns}"
94+
two = "${module.two_servers.public_dns}"
95+
}
96+
}
97+
98+
output "public_ips" {
99+
value = {
100+
zero = "${module.zero_servers.public_ips}"
101+
one = "${module.one_server.public_ips}"
102+
two = "${module.two_servers.public_ips}"
103+
}
104+
}
105+
106+
output "instance_count" {
107+
value = {
108+
zero = "${module.zero_servers.instance_count}"
109+
one = "${module.one_server.instance_count}"
110+
two = "${module.two_servers.instance_count}"
111+
}
112+
}
113+
114+
output "eni_to_eip_map" {
115+
value = {
116+
zero = "${module.zero_servers.eni_to_eip_map}"
117+
one = "${module.one_server.eni_to_eip_map}"
118+
two = "${module.two_servers.eni_to_eip_map}"
119+
}
120+
}
121+
122+
output "eip_per_instance_count" {
123+
value = {
124+
zero = "${module.zero_servers.eip_per_instance_count}"
125+
one = "${module.one_server.eip_per_instance_count}"
126+
two = "${module.two_servers.eip_per_instance_count}"
127+
}
128+
}
129+
130+
output "private_ips" {
131+
value = {
132+
zero = "${module.zero_servers.private_ips}"
133+
one = "${module.one_server.private_ips}"
134+
two = "${module.two_servers.private_ips}"
135+
}
136+
}
137+
138+
output "private_dns" {
139+
value = {
140+
zero = "${module.zero_servers.private_dns}"
141+
one = "${module.one_server.private_dns}"
142+
two = "${module.two_servers.private_dns}"
143+
}
144+
}
145+
146+
output "aws_key_pair_name" {
147+
value = {
148+
zero = "${module.zero_servers.aws_key_pair_name}"
149+
one = "${module.one_server.aws_key_pair_name}"
150+
two = "${module.two_servers.aws_key_pair_name}"
151+
}
152+
}
153+
154+
output "alarm" {
155+
value = {
156+
zero = "${module.zero_servers.alarm_ids}"
157+
one = "${module.one_server.alarm_ids}"
158+
two = "${module.two_servers.alarm_ids}"
159+
}
160+
}
161+
162+
output "ssh_key_pem_path" {
163+
value = {
164+
zero = "${module.zero_servers.ssh_key_pem_path}"
165+
one = "${module.one_server.ssh_key_pem_path}"
166+
two = "${module.two_servers.ssh_key_pem_path}"
167+
}
168+
}

main.tf

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
locals {
2+
instance_count = "${var.instance_enabled == "true" ? var.instance_count : 0}"
3+
security_group_count = "${var.create_default_security_group == "true" ? 1 : 0}"
4+
region = "${var.region}"
5+
root_iops = "${var.root_volume_type == "io1" ? var.root_iops : "0"}"
6+
ebs_iops = "${var.ebs_volume_type == "io1" ? var.ebs_iops : "0"}"
7+
availability_zone = "${var.availability_zone}"
8+
root_volume_type = "${var.root_volume_type != "" ? var.root_volume_type : data.aws_ami.info.root_device_type}"
9+
count_default_ips = "${var.associate_public_ip_address == "true" && var.assign_eip_address == "true" && var.instance_enabled == "true" && var.instance_count > 0 ? 1 : 0}"
10+
ssh_key_pair_path = "${var.ssh_key_pair_path == "" ? path.cwd : var.ssh_key_pair_path }"
11+
}
12+
13+
data "aws_caller_identity" "default" {}
14+
15+
data "aws_iam_policy_document" "default" {
16+
statement {
17+
sid = ""
18+
19+
actions = [
20+
"sts:AssumeRole",
21+
]
22+
23+
principals {
24+
type = "Service"
25+
identifiers = ["ec2.amazonaws.com"]
26+
}
27+
28+
effect = "Allow"
29+
}
30+
}
31+
32+
data "aws_ami" "info" {
33+
filter {
34+
name = "image-id"
35+
values = ["${var.ami}"]
36+
}
37+
}
38+
39+
# Apply the terraform-terraform-label module for this resource
40+
module "label" {
41+
source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.1.2"
42+
namespace = "${var.namespace}"
43+
stage = "${var.stage}"
44+
name = "${var.name}"
45+
attributes = "${var.attributes}"
46+
delimiter = "${var.delimiter}"
47+
tags = "${merge(map("AZ", "${local.availability_zone}"), var.tags)}"
48+
enabled = "true"
49+
}
50+
51+
resource "aws_iam_instance_profile" "default" {
52+
count = "${signum(local.instance_count)}"
53+
name = "${module.label.id}"
54+
role = "${element(aws_iam_role.default.*.name, 0)}"
55+
}
56+
57+
resource "aws_iam_role" "default" {
58+
count = "${signum(local.instance_count)}"
59+
name = "${module.label.id}"
60+
path = "/"
61+
assume_role_policy = "${data.aws_iam_policy_document.default.json}"
62+
}
63+
64+
resource "aws_instance" "default" {
65+
count = "${local.instance_count}"
66+
ami = "${data.aws_ami.info.id}"
67+
availability_zone = "${local.availability_zone}"
68+
instance_type = "${var.instance_type}"
69+
ebs_optimized = "${var.ebs_optimized}"
70+
disable_api_termination = "${var.disable_api_termination}"
71+
user_data = "${var.user_data}"
72+
iam_instance_profile = "${element(aws_iam_instance_profile.default.*.name, 0)}"
73+
associate_public_ip_address = "${var.associate_public_ip_address}"
74+
key_name = "${signum(length(var.ssh_key_pair)) == 1 ? var.ssh_key_pair : module.ssh_key_pair.key_name}"
75+
subnet_id = "${var.subnet}"
76+
monitoring = "${var.monitoring}"
77+
private_ip = "${element(concat(var.private_ips, list("")), min(length(var.private_ips), count.index))}"
78+
source_dest_check = "${var.source_dest_check}"
79+
ipv6_address_count = "${var.ipv6_address_count}"
80+
ipv6_addresses = "${var.ipv6_addresses}"
81+
82+
vpc_security_group_ids = [
83+
"${compact(concat(list(var.create_default_security_group == "true" ? join("", aws_security_group.default.*.id) : ""), var.security_groups))}",
84+
]
85+
86+
root_block_device {
87+
volume_type = "${local.root_volume_type}"
88+
volume_size = "${var.root_volume_size}"
89+
iops = "${local.root_iops}"
90+
delete_on_termination = "${var.delete_on_termination}"
91+
}
92+
93+
tags = "${merge(module.label.tags, map("instance_index", "${count.index}"))}"
94+
}
95+
96+
##
97+
## Create keypair if one isn't provided
98+
##
99+
100+
module "ssh_key_pair" {
101+
source = "git::https://github.com/cloudposse/terraform-aws-key-pair.git?ref=tags/0.2.3" //upcoming release
102+
namespace = "${var.namespace}"
103+
stage = "${var.stage}"
104+
name = "${var.name}"
105+
ssh_public_key_path = "${local.ssh_key_pair_path}"
106+
private_key_extension = ".pem"
107+
generate_ssh_key = "${var.generate_ssh_key_pair}"
108+
}
109+
110+
resource "aws_eip" "default" {
111+
count = "${local.count_default_ips}"
112+
network_interface = "${element(aws_instance.default.*.primary_network_interface_id, count.index)}"
113+
vpc = "true"
114+
depends_on = ["aws_instance.default"]
115+
}
116+
117+
resource "aws_ebs_volume" "default" {
118+
count = "${var.ebs_volume_count * local.instance_count}"
119+
availability_zone = "${local.availability_zone}"
120+
size = "${var.ebs_volume_size}"
121+
iops = "${local.ebs_iops}"
122+
type = "${var.ebs_volume_type}"
123+
tags = "${module.label.tags}"
124+
}
125+
126+
resource "aws_volume_attachment" "default" {
127+
count = "${signum(local.instance_count) == 1 ? floor(var.ebs_volume_count / max(local.instance_count, 1)) : 0 }"
128+
device_name = "${element(var.ebs_device_names, count.index)}"
129+
volume_id = "${element(aws_ebs_volume.default.*.id, count.index)}"
130+
instance_id = "${aws_instance.default.id}"
131+
}

0 commit comments

Comments
 (0)