The document discusses refactoring Terraform configuration files to improve their design. It provides an example of refactoring a "supermarket-terraform" configuration that originally defined AWS resources across multiple files. The refactoring consolidates the configuration into a single file and adds testing using Test Kitchen. It emphasizes starting small by adding tests incrementally and not making changes without tests to avoid introducing errors.
50. • Test Kitchen (http://kitchen.ci)
• Kitchen Terraform
(http://github.com/newcontext/
kitchen-terraform)
• Inspec (http://chef.io/inspec)
How Can We Test Terraform?
60. …
#resource
“aws_instance”
“chef_server”
{
#
ami
=
“${var.ami}”
#
instance_type
=
“${var.instance_type}”
#
key_name
=
“${var.key_name}”
#
tags
{
#
Name
=
“dev-‐chef-‐server”
#
}
#
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
#
“${aws_security_group.allow-‐out.name}”]
#
(…)
#}
…
This is the
Chef Server
supermarket-cluster.tf
61. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
“${aws_security_group.allow-‐out.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
84. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
“${aws_security_group.allow-‐out.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
85. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
105. Spins up AWS
resources
Passes to
kitchen-terraform
Captures public_dns
of EC2 instances
in aws_hostnames
Using Outputs
106. Spins up AWS
resources
Captures public_dns
of EC2 instances
in aws_hostnames
Passes to
kitchen-terraform
kitchen-terraform
uses aws_hostnames
to ssh into the instances
Using Outputs
120. EC2
Chef Server $ terraform apply
EC2
Supermarket
Security
Group
Allow SSH
Security
Group
Allow Out
supermarket-cluster.tf
121. Now let’s call this
security group from our
Chef Server
122. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
123. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
“${aws_security_group.allow-‐out.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
136. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
“${aws_security_group.allow-‐out.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
137. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
138. …
resource
“aws_instance”
“supermarket_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐supermarket-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”,
“${aws_security_group.allow-‐out.name}”]
(…)
}
…
This is the
Supermarket
Server
supermarket-cluster.tf
139. …
resource
“aws_instance”
“supermarket_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐supermarket-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”]
(…)
}
…
This is the
Supermarket
Server
supermarket-cluster.tf
140. EC2
Chef Server
$ terraform apply EC2
Supermarket
Security
Group
Allow SSH
Allow Out
supermarket-cluster.tf
152. resource
“aws_security_group”
“allow-‐ssh”
{
name
=
“${var.user_name}-‐allow-‐ssh”
tags
=
{
Name
=
“${var.user_name}
Allow
All
SSH”
}
resource
“aws_security_group_rule”
“allow-‐ssh”
{
type
=
“ingress”
from_port
=
22
to_port
=
22
…
}
security-groups/main.tf
153. Now we need to
connect to the module
from main config
154. First, we need to
know what variables
the module needs
passed to it
155. resource
“aws_security_group”
“allow-‐ssh”
{
name
=
“${var.user_name}-‐allow-‐ssh”
tags
=
{
Name
=
“${var.user_name}
Allow
All
SSH”
}
resource
“aws_security_group_rule”
“allow-‐ssh”
{
type
=
“ingress”
from_port
=
22
…
security_group_id
=
“${aws_security_group.allow-‐ssh.id}”
}
Needs to be passed
to the module
security-groups/main.tf
156. resource
“aws_security_group”
“allow-‐ssh”
{
name
=
“${var.user_name}-‐allow-‐ssh”
tags
=
{
Name
=
“${var.user_name}
Allow
All
SSH”
}
resource
“aws_security_group_rule”
“allow-‐ssh”
{
type
=
“ingress”
from_port
=
22
…
security_group_id
=
“${aws_security_group.allow-‐ssh.id}”
}
security-groups/main.tf
Thank you,
Nikhil Vaze!
157. resource
“aws_security_group”
“allow-‐ssh”
{
name
=
“${var.user_name}-‐allow-‐ssh”
tags
=
{
Name
=
“${var.user_name}
Allow
All
SSH”
}
resource
“aws_security_group_rule”
“allow-‐ssh”
{
type
=
“ingress”
from_port
=
22
…
security_group_id
=
“${aws_security_group.allow-‐ssh.id}”
}
Does not need
to be passed in
security-groups/main.tf
173. output
“sg-‐name”
{
value
=
“${aws_security_group.allow-‐ssh.name}”
}
security-groups/output.tf
174. Now, we need to use
this output in our
supermarket-cluster
config
175. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh.name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
176. …
resource
“aws_instance”
“chef_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐chef-‐server”
}
security_groups
=
[“${module.security-‐groups.sg-‐name}”]
(…)
}
…
This is the
Chef Server
supermarket-cluster.tf
177. …
resource
“aws_instance”
“supermarket_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐supermarket-‐server”
}
security_groups
=
[“${aws_security_group.allow-‐ssh-‐name}”]
(…)
}
…
This is the
Supermarket
Server
supermarket-cluster.tf
178. …
resource
“aws_instance”
“supermarket_server”
{
ami
=
“${var.ami}”
instance_type
=
“${var.instance_type}”
key_name
=
“${var.key_name}”
tags
{
Name
=
“dev-‐supermarket-‐server”
}
security_groups
=
[“${module.security-‐groups.sg-‐name}”]
(…)
}
…
This is the
Supermarket
Server
supermarket-cluster.tf