Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit 7c0e8eb

Browse files
committed
Support multiple data volumes in single-node-asg module.
Tested in examples/single-node-asg-tester The change in all three modules is compatible with old code that defines just one data volume.
1 parent ca4962b commit 7c0e8eb

File tree

13 files changed

+203
-181
lines changed

13 files changed

+203
-181
lines changed
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
provider "aws" {
2+
region = "ap-northeast-1"
3+
}
4+
5+
locals {
6+
cidr = "192.168.0.0/16"
7+
private_subnet_cidrs = ["192.168.100.0/24", "192.168.101.0/24"]
8+
public_subnet_cidrs = ["192.168.0.0/24", "192.168.1.0/24"]
9+
}
10+
11+
data "aws_vpc" "vpc" {
12+
cidr_block = local.cidr
13+
}
14+
15+
data "aws_subnet" "public" {
16+
count = length(local.public_subnet_cidrs)
17+
cidr_block = local.public_subnet_cidrs[count.index]
18+
}
19+
20+
module "ubuntu" {
21+
source = "fpco/foundation/aws//modules/ami-ubuntu"
22+
}
23+
24+
resource "aws_security_group" "ssh" {
25+
vpc_id = data.aws_vpc.vpc.id
26+
ingress {
27+
from_port = 22
28+
to_port = 22
29+
protocol = "tcp"
30+
cidr_blocks = ["0.0.0.0/0"]
31+
}
32+
egress {
33+
from_port = 0
34+
to_port = 0
35+
protocol = "-1"
36+
cidr_blocks = ["0.0.0.0/0"]
37+
}
38+
}
39+
40+
module "tester" {
41+
source = "../../modules/single-node-asg"
42+
name_prefix = "ebs"
43+
name_suffix = "test"
44+
key_name = "tokyo"
45+
ami = module.ubuntu.id
46+
instance_type = "t2.micro"
47+
subnet_id = data.aws_subnet.public[0].id
48+
security_group_ids = [aws_security_group.ssh.id]
49+
region = "ap-northeast-1"
50+
data_volumes = [{ name = "a", device = "/dev/xvdm", size = 50 }, { name = "b", device = "/dev/xvdn" }]
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
if which wget; then
2+
INSTANCE_ID="$(wget -O- http://169.254.169.254/latest/meta-data/instance-id)"
3+
elif which curl; then
4+
INSTANCE_ID="$(curl http://169.254.169.254/latest/meta-data/instance-id)"
5+
fi
6+
7+
if [ "x$${INSTANCE_ID}" == "x" ]; then
8+
echo 'There is no wget or curl tool installed. Hence bootstrap cannot get instance ID.'
9+
exit 1
10+
fi

modules/init-snippet-attach-ebs-volume/main.tf

+14-52
Original file line numberDiff line numberDiff line change
@@ -9,70 +9,32 @@
99
*
1010
*/
1111

12-
# variables used by this snippet of init shellcode
13-
variable "device_path" {
14-
default = "/dev/xvdf"
15-
description = "path, to the device's path in /dev/"
16-
type = string
17-
}
18-
19-
variable "init_prefix" {
20-
default = ""
21-
description = "initial init (shellcode) to prefix this snippet with"
22-
type = string
23-
}
24-
25-
variable "init_suffix" {
26-
default = ""
27-
description = "init (shellcode) to append to the end of this snippet"
28-
type = string
29-
}
30-
31-
variable "log_level" {
32-
default = "info"
33-
description = "default log level verbosity for apps that support it"
34-
type = string
35-
}
36-
37-
variable "log_prefix" {
38-
default = "OPS: "
39-
description = "string to prefix log messages with"
40-
type = string
41-
}
42-
43-
variable "region" {
44-
description = "AWS region the volume is in"
45-
type = string
46-
}
47-
48-
variable "wait_interval" {
49-
default = "5"
50-
description = "time (in seconds) to wait when looping to find the device"
51-
type = number
52-
}
53-
54-
variable "volume_id" {
55-
description = "ID of the EBS volume to attach"
56-
type = string
57-
}
58-
5912
# render init script for a cluster using our generic template
6013
data "template_file" "init_snippet" {
14+
count = length(var.volume_ids)
15+
6116
template = file("${path.module}/snippet.tpl")
6217

6318
vars = {
64-
device_path = var.device_path
65-
init_prefix = var.init_prefix
66-
init_suffix = var.init_suffix
19+
device_path = var.device_paths[count.index]
6720
log_prefix = var.log_prefix
6821
log_level = var.log_level
6922
region = var.region
70-
volume_id = var.volume_id
23+
volume_id = var.volume_ids[count.index]
7124
wait_interval = var.wait_interval
7225
}
7326
}
7427

28+
data "template_file" "instance_id" {
29+
template = file("${path.module}/instance_id.tpl")
30+
}
31+
7532
output "init_snippet" {
76-
value = data.template_file.init_snippet.rendered
33+
value = <<EOF
34+
${var.init_prefix}
35+
${data.template_file.instance_id.rendered}
36+
${join("\n", data.template_file.init_snippet.*.rendered)}
37+
${var.init_suffix}
38+
EOF
7739
}
7840

Original file line numberDiff line numberDiff line change
@@ -1,34 +1,19 @@
1-
# start snippet - attach EBS volume
2-
${init_prefix}
31
export AWS_DEFAULT_REGION=${region}
42
VOLUME_ID=${volume_id}
5-
if which wget; then
6-
INSTANCE_ID="$(wget -O- http://169.254.169.254/latest/meta-data/instance-id)"
7-
elif which curl; then
8-
INSTANCE_ID="$(curl http://169.254.169.254/latest/meta-data/instance-id)"
9-
fi
3+
echo "${log_prefix} will attach $${VOLUME_ID} via the AWS API in ${region}"
4+
while ! aws ec2 attach-volume \
5+
--volume-id "$${VOLUME_ID}" \
6+
--instance-id "$${INSTANCE_ID}" \
7+
--device '${device_path}'; do
8+
echo "Attaching command failed to run. Retrying."
9+
sleep '${wait_interval}'
10+
done
11+
echo "${log_prefix} $${VOLUME_ID} attached."
12+
sleep '${wait_interval}' # Wait for device up
1013

11-
if [ "x$${INSTANCE_ID}" == "x" ]; then
12-
echo 'OS not functioning'
13-
else
14-
echo "${log_prefix} will attach $${VOLUME_ID} via the AWS API in ${region}"
15-
while ! aws ec2 attach-volume \
16-
--volume-id "$${VOLUME_ID}" \
17-
--instance-id "$${INSTANCE_ID}" \
18-
--device '${device_path}'; do
19-
echo "Attaching command failed to run. Retrying."
20-
sleep '${wait_interval}'
21-
done
22-
echo "${log_prefix} $${VOLUME_ID} attached."
23-
14+
if [ ! -e ${device_path} ]; then
2415
vol_id="$(echo "$${VOLUME_ID}" | tr -d '-')"
25-
while [ ! -e /dev/disk/by-id/*-Amazon_Elastic_Block_Store_$${vol_id} ]; do
26-
sleep '${wait_interval}'
27-
done
28-
2916
dev_id="$(ls /dev/disk/by-id/*-Amazon_Elastic_Block_Store_$${vol_id} | head -1)"
3017
dev_name="/dev/$(readlink "$${dev_id}" | tr / '\n' | tail -1)"
3118
[ "$${dev_name}" == "${device_path}" ] || ln -s "$${dev_name}" "${device_path}"
3219
fi
33-
34-
${init_suffix}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
variable "device_paths" {
2+
type = list(string)
3+
description = "paths, to the device's path in /dev/"
4+
default = []
5+
}
6+
7+
variable "init_prefix" {
8+
default = ""
9+
description = "initial init (shellcode) to prefix this snippet with"
10+
type = string
11+
}
12+
13+
variable "init_suffix" {
14+
default = ""
15+
description = "init (shellcode) to append to the end of this snippet"
16+
type = string
17+
}
18+
19+
variable "log_level" {
20+
default = "info"
21+
description = "default log level verbosity for apps that support it"
22+
type = string
23+
}
24+
25+
variable "log_prefix" {
26+
default = "OPS: "
27+
description = "string to prefix log messages with"
28+
type = string
29+
}
30+
31+
variable "region" {
32+
description = "AWS region the volume is in"
33+
type = string
34+
}
35+
36+
variable "wait_interval" {
37+
default = "5"
38+
description = "time (in seconds) to wait when looping to find the device"
39+
type = number
40+
}
41+
42+
variable "volume_ids" {
43+
description = "IDs of the EBS volumes to attach"
44+
type = list(string)
45+
default = []
46+
}

modules/persistent-ebs/data.tf

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ data "aws_iam_policy_document" "attach_ebs_policy_doc" {
1414
"ec2:DetachVolume",
1515
]
1616

17-
resources = [
18-
"arn:${data.aws_partition.current.partition}:ec2:${var.region}:${data.aws_caller_identity.current.account_id}:volume/${aws_ebs_volume.main.id}",
19-
"arn:${data.aws_partition.current.partition}:ec2:${var.region}:${data.aws_caller_identity.current.account_id}:instance/*",
20-
]
17+
resources = concat(["arn:${data.aws_partition.current.partition}:ec2:${var.region}:${data.aws_caller_identity.current.account_id}:instance/*"],
18+
[for x in aws_ebs_volume.main.*.id : "arn:${data.aws_partition.current.partition}:ec2:${var.region}:${data.aws_caller_identity.current.account_id}:volume/${x}"])
2119
}
2220
}

modules/persistent-ebs/locals.tf

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
locals {
2+
volume_default = {
3+
type = "gp2"
4+
iops = 0
5+
size = 15
6+
encrypted = true
7+
kms_key_id = ""
8+
snapshot_id = ""
9+
}
10+
volumes_default = [for x in var.volumes : merge(local.volume_default, x)]
11+
}

modules/persistent-ebs/main.tf

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,27 @@
99
*/
1010

1111
resource "aws_ebs_volume" "main" {
12+
count = length(local.volumes_default)
13+
1214
availability_zone = var.az
13-
size = var.size
14-
type = var.volume_type
15-
encrypted = var.encrypted
16-
kms_key_id = var.kms_key_id
17-
snapshot_id = var.snapshot_id
15+
size = local.volumes_default[count.index].size
16+
type = local.volumes_default[count.index].type
17+
encrypted = local.volumes_default[count.index].encrypted
18+
kms_key_id = local.volumes_default[count.index].kms_key_id
19+
snapshot_id = local.volumes_default[count.index].snapshot_id
1820

1921
# merge Name w/ extra_tags
2022
tags = merge(
2123
{
22-
"Name" = "${var.name_prefix}-${var.az}"
24+
"Name" = "${var.name_prefix}-${var.az}-${local.volumes_default[count.index].name}"
2325
},
2426
var.extra_tags,
2527
)
2628
}
2729

2830
# IAM policy that allows attaching this EBS volume to an EC2 instance
2931
resource "aws_iam_policy" "attach_ebs" {
30-
name = "${var.name_prefix}-attach-ebs-${aws_ebs_volume.main.id}"
32+
name = "${var.name_prefix}-attach-ebs"
3133
policy = data.aws_iam_policy_document.attach_ebs_policy_doc.json
3234
}
3335

modules/persistent-ebs/outputs.tf

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
output "volume_id" {
2-
value = aws_ebs_volume.main.id
1+
output "volume_ids" {
2+
value = aws_ebs_volume.main.*.id
33
description = "`id` exported from the `aws_ebs_volume`"
44
}
55

modules/persistent-ebs/variables.tf

+14-36
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,6 @@ variable "az" {
1414
type = string
1515
}
1616

17-
variable "volume_type" {
18-
default = "gp2"
19-
description = "Type of EBS volume to use for the EBS block device"
20-
type = string
21-
}
22-
23-
variable "size" {
24-
default = "15"
25-
description = "Size (in GB) of EBS volume to use for the EBS block device"
26-
type = string
27-
}
28-
29-
variable "snapshot_id" {
30-
default = ""
31-
description = "The ID of the snapshot to base the EBS block device on"
32-
type = string
33-
}
34-
35-
variable "encrypted" {
36-
default = true
37-
description = "Boolean, whether or not to encrypt the EBS block device"
38-
type = string
39-
}
40-
41-
variable "kms_key_id" {
42-
default = ""
43-
description = "ID of the KMS key to use when encyprting the EBS block device"
44-
type = string
45-
}
46-
47-
variable "iops" {
48-
default = ""
49-
description = "The amount of IOPS to provision for the EBS block device"
50-
type = string
51-
}
52-
5317
variable "extra_tags" {
5418
default = {}
5519
description = "Map with extra tags to be applied to all ebs volumes"
@@ -60,3 +24,17 @@ variable "iam_instance_profile_role_name" {
6024
description = "The role to attach policy needed by this module."
6125
type = string
6226
}
27+
28+
variable "volumes" {
29+
type = list(map(any))
30+
### Note: what should be contained.
31+
# type = string,
32+
# iops = number,
33+
# size = number,
34+
# encrypted = bool,
35+
# kms_key_id = string,
36+
# snapshot_id = string,
37+
# name = string
38+
description = "Definition of volumes. `name` is required."
39+
default = []
40+
}

0 commit comments

Comments
 (0)