Download - Refactoring Infrastructure Code
![Page 1: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/1.jpg)
Untangling InfrastructureCode Through Refactoring
DevOpsDays Chicago
@nellshamrell
![Page 2: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/2.jpg)
Who Am I?
Nell Shamrell-Harrington• Software Engineer at Chef
• @nellshamrell• [email protected]
• Former O’Fallon, IL resident (Southern IL ftw!)
![Page 3: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/3.jpg)
Why should I refactor my infrastructure code?
![Page 4: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/4.jpg)
Why Refactor?
• Add a feature
![Page 5: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/5.jpg)
• Add a feature • Fix a bug
Why Refactor?
![Page 6: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/6.jpg)
• Add a feature • Fix a bug • Improve the design
Why Refactor?
![Page 7: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/7.jpg)
• Add a feature • Fix a bug • Improve the design • Optimize resource usage
Why Refactor?
![Page 8: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/8.jpg)
Let’s go through an example!
![Page 9: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/9.jpg)
Refactoring a Terraform config
![Page 10: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/10.jpg)
Today, we will refactor supermarket-terraform
http://github.com/nellshamrell/supermarket-terraform
supermarket-terraform
![Page 11: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/11.jpg)
supermarket-cluster.tf
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” }
supermarket-terraform
![Page 12: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/12.jpg)
supermarket-cluster.tf
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” }
supermarket-terraform
![Page 13: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/13.jpg)
supermarket-cluster.tf
variables.tf
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” }
variable “access_key” = {} variable “secret_key” = {}
supermarket-terraform
![Page 14: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/14.jpg)
supermarket-cluster.tf
variables.tf
terraform.tfvars
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” }
variable “access_key” = {} variable “secret_key” = {}
access_key = “xxxxx” secret_key = “xxxxx”
supermarket-terraform
![Page 15: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/15.jpg)
Wait…should you use a credentials file?
![Page 16: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/16.jpg)
You can…but for the sake of the example, let’s supply them inline
![Page 17: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/17.jpg)
supermarket-cluster.tf
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” }
supermarket-terraform
![Page 18: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/18.jpg)
$ terraform apply
supermarket-cluster.tf
![Page 19: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/19.jpg)
Security Group
$ terraform apply
supermarket-cluster.tf
![Page 20: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/20.jpg)
Security Group
Allow SSH
$ terraform apply
supermarket-cluster.tf
![Page 21: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/21.jpg)
Security Group
Security Group
Allow SSH
$ terraform apply
supermarket-cluster.tf
![Page 22: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/22.jpg)
Security Group
Security Group
Allow SSH Allow Out
$ terraform apply
supermarket-cluster.tf
![Page 23: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/23.jpg)
Security Group
Security Group
EC2
Allow SSH Allow Out
$ terraform apply
supermarket-cluster.tf
![Page 24: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/24.jpg)
Security Group
Security Group
EC2Chef Server
Allow SSH Allow Out
$ terraform apply
supermarket-cluster.tf
![Page 25: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/25.jpg)
EC2
Security Group
Security Group
EC2Chef Server
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 26: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/26.jpg)
EC2
Security Group
Security Group
EC2Chef Server Supermarket
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 27: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/27.jpg)
EC2
Security Group
Security Group
EC2Chef Server Supermarket
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 28: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/28.jpg)
EC2
Security Group
Security Group
EC2Chef Server Supermarket
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 29: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/29.jpg)
EC2
Security Group
Security Group
EC2Chef Server Supermarket
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 30: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/30.jpg)
EC2
Security Group
Security Group
EC2Chef Server Supermarket
Allow OutAllow SSH
$ terraform apply
supermarket-cluster.tf
![Page 31: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/31.jpg)
Hypothetical: We are using too many AWS Security Groups
Why Refactor?
![Page 32: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/32.jpg)
We need this config to create only
one security group
Why Refactor?
![Page 33: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/33.jpg)
Source: Working Effectively with Legacy Code
How to Refactor?Two Approaches
![Page 34: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/34.jpg)
Source: Working Effectively with Legacy Code
How to Refactor?
• Edit and PrayTwo Approaches
![Page 35: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/35.jpg)
• Edit and Pray• Cover and Modify
Two Approaches
Source: Working Effectively with Legacy Code
How to Refactor?
![Page 36: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/36.jpg)
Confidence in code without tests is
false confidence
![Page 37: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/37.jpg)
What code is intended to do is much less important
than what it actually does
![Page 38: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/38.jpg)
Do I have to add tests for the entire thing?
![Page 39: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/39.jpg)
No.
![Page 40: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/40.jpg)
The point of adding tests is to not make things worse
![Page 41: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/41.jpg)
And to start making the code better here and now
![Page 42: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/42.jpg)
How can we test Terraform?
![Page 44: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/44.jpg)
How Can We Test Terraform?• Test Kitchen (http://kitchen.ci)
• Kitchen Terraform (http://github.com/newcontext/ kitchen-terraform)
![Page 45: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/45.jpg)
driver: name: terraform
provisioner: name: terraform variable_files: terraform.@vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla@orms: -‐ name: ubuntu
suites -‐ name: default
.kitchen.yml
![Page 46: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/46.jpg)
driver: name: terraform
provisioner: name: terraform variable_files: terraform.@vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla@orms: -‐ name: ubuntu
suites -‐ name: default
.kitchen.yml
![Page 47: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/47.jpg)
driver: name: terraform
provisioner: name: terraform variable_files: terraform.5vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla@orms: -‐ name: ubuntu
suites -‐ name: default
.kitchen.yml
![Page 48: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/48.jpg)
driver: name: terraform
provisioner: name: terraform variable_files: terraform.5vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla@orms: -‐ name: ubuntu
suites -‐ name: default
.kitchen.yml
![Page 49: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/49.jpg)
driver: name: terraform
provisioner: name: terraform variable_files: terraform.@vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla@orms: -‐ name: ubuntu
suites -‐ name: default
.kitchen.yml
![Page 50: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/50.jpg)
.kitchen.ymldriver: name: terraform
provisioner: name: terraform variable_files: terraform.@vars
transport: name: ssh ssh_key: ~/path/to/your/aws/key
pla5orms: -‐ name: ubuntu
suites -‐ name: default
Test KitchenBoilerplate
![Page 51: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/51.jpg)
• Test Kitchen (http://kitchen.ci)
• Kitchen Terraform (http://github.com/newcontext/ kitchen-terraform)
• Inspec (http://chef.io/inspec)
How Can We Test Terraform?
![Page 52: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/52.jpg)
Now that we have our tools…
![Page 53: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/53.jpg)
Let’s start from a clean slate
![Page 54: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/54.jpg)
#provider “aws” { # access_key = “${var.access_key}” # secret_key = “${var.secret_key}” # region = “${var.region}” #}
#resource “aws_security_group” “allow-‐ssh” { # name = “${var.user_name}-‐allow-‐ssh” # tags = { # Name = “${var.user_name} Allow All SSH” # } …
supermarket-cluster.tf
![Page 55: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/55.jpg)
$ terraform apply
supermarket-cluster.tf
![Page 56: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/56.jpg)
$ terraform apply
Nothing happens!
supermarket-cluster.tf
![Page 57: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/57.jpg)
First, we need the provider
![Page 58: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/58.jpg)
provider “aws” { access_key = “${var.access_key}” secret_key = “${var.secret_key}” region = “${var.region}” }
#resource “aws_security_group” “allow-‐ssh” { # name = “${var.user_name}-‐allow-‐ssh” # tags = { # Name = “${var.user_name} Allow All SSH” # } …
supermarket-cluster.tf
![Page 59: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/59.jpg)
We also need actual AWS instances
![Page 60: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/60.jpg)
Including both our Chef Server…
![Page 61: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/61.jpg)
… #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
![Page 62: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/62.jpg)
… 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
![Page 63: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/63.jpg)
$ terraform apply
supermarket-cluster.tf
![Page 64: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/64.jpg)
EC2Chef Server $ terraform apply
supermarket-cluster.tf
![Page 65: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/65.jpg)
And our supermarketserver
![Page 66: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/66.jpg)
… #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
![Page 67: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/67.jpg)
… 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
![Page 68: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/68.jpg)
EC2Chef Server $ terraform apply
EC2 Supermarket
supermarket-cluster.tf
![Page 69: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/69.jpg)
We also need at least one security group
![Page 70: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/70.jpg)
#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 … #}
supermarket-cluster.tf
![Page 71: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/71.jpg)
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 … #}
supermarket-cluster.tf
![Page 72: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/72.jpg)
EC2Chef Server
supermarket-cluster.tf
$ terraform applyEC2
Supermarket
Security Group
![Page 73: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/73.jpg)
kitchen-terraform needs to be able to
ssh into our instances
![Page 74: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/74.jpg)
We need a security group rule
![Page 75: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/75.jpg)
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 … #}
supermarket-cluster.tf
![Page 76: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/76.jpg)
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 … }
supermarket-cluster.tf
![Page 77: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/77.jpg)
EC2Chef Server $ terraform apply
EC2 Supermarket
Security Group
Allow SSH
supermarket-cluster.tf
![Page 78: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/78.jpg)
Now, let’s create our test cluster
![Page 79: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/79.jpg)
$ kitchen converge
![Page 80: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/80.jpg)
Like running terraform apply
$ kitchen converge
![Page 81: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/81.jpg)
$ kitchen converge (…) >>>>>> ------Exception------- >>>>>> Class: Kitchen::ActionFailed >>>>>> Message: 1 actions failed. >>>>>> Converge failed on instance <default-ubuntu>. >>>>>> Please see .kitchen/logs/kitchen.log for more details
![Page 82: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/82.jpg)
-‐-‐-‐-‐ Begin output of terraform validate /root/supermarket-‐terraform-‐2 -‐-‐-‐-‐ STDOUT: STDERR: ^[[31mError validaWng: 2 error(s) occurred:
* resource 'aws_instance.chef_server' config: unknown resource * 'aws_security_group.allow-‐egress' referenced in * variable aws_security_group.allow-‐egress.name * resource 'aws_instance.supermarket_server' config: * unknown resource 'aws_security_group.allow-‐egress' * referenced in variable aws_security_group.allow-‐egress. * name
.kitchen/logs/default-ubuntu.log
![Page 83: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/83.jpg)
We need our EC2 resources to reference only one
security group
![Page 84: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/84.jpg)
Let’s look at the Chef Server
![Page 85: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/85.jpg)
… 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
![Page 86: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/86.jpg)
… 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
![Page 87: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/87.jpg)
And the Supermarket Server
![Page 88: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/88.jpg)
… 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
![Page 89: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/89.jpg)
… 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
![Page 90: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/90.jpg)
$ kitchen converge$ kitchen converge
![Page 91: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/91.jpg)
$ kitchen converge Apply complete! Resources: 2 added, 0 changed, 0 destroyed. (…) Finished converging <default-ubuntu> (0m7.10s).
![Page 92: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/92.jpg)
EC2Chef Server
EC2 Supermarket
Security Group
Allow SSH
supermarket-cluster.tf
$ terraform apply
![Page 93: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/93.jpg)
Now let’s write some tests
![Page 94: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/94.jpg)
First, let’s define a test group
![Page 95: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/95.jpg)
driver: name: terraform (…)
verifier: name: terraform format: doc groups: -‐ name: default tests: -‐ security_groups hostnames: aws_hostnames username: ubuntu
.kitchen.yml
![Page 96: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/96.jpg)
driver: name: terraform (…)
verifier: name: terraform format: doc groups: -‐ name: default tests: -‐ security_groups hostnames: aws_hostnames username: ubuntu
.kitchen.yml
![Page 97: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/97.jpg)
driver: name: terraform (…)
verifier: name: terraform format: doc groups: -‐ name: default tests: -‐ security_groups hostnames: aws_hostnames username: ubuntu
.kitchen.yml
![Page 98: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/98.jpg)
driver: name: terraform (…)
verifier: name: terraform format: doc groups: -‐ name: default tests: -‐ security_groups hostnames: aws_hostnames username: ubuntu
.kitchen.yml
![Page 99: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/99.jpg)
Output variable
driver: name: terraform (…)
verifier: name: terraform format: doc groups: -‐ name: default tests: -‐ security_groups hostnames: aws_hostnames username: ubuntu
.kitchen.yml
![Page 100: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/100.jpg)
We need to create that output variable
![Page 101: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/101.jpg)
output “aws_hostnames” {
}
outputs.tf
![Page 102: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/102.jpg)
output “aws_hostnames” { value = “${aws_instance.chef_server.public_dns}, ${aws_instance.supermarket_server.public_dns}” }
outputs.tf
![Page 103: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/103.jpg)
output “aws_hostnames” { value = “${aws_instance.chef_server.public_dns}, ${aws_instance.supermarket_server.public_dns}” }
outputs.tf
![Page 104: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/104.jpg)
Spins up AWS resources
Using Outputs
![Page 105: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/105.jpg)
Spins up AWS resources
Captures public_dns of EC2 instances
in aws_hostnames
Using Outputs
![Page 106: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/106.jpg)
Spins up AWS resources
Passes to kitchen-terraform
Captures public_dns of EC2 instances
in aws_hostnames
Using Outputs
![Page 107: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/107.jpg)
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
![Page 108: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/108.jpg)
Spins up AWS resources
Runs Tests
kitchen-terraform uses aws_hostnames
to ssh into the instances
Captures public_dns of EC2 instances
in aws_hostnames
Passes to kitchen-terraform
Using Outputs
![Page 109: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/109.jpg)
$ kitchen destroy$ kitchen destroy
![Page 110: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/110.jpg)
$ kitchen destroy $ kitchen converge
$ kitchen destroy $ kitchen converge
![Page 111: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/111.jpg)
#resource “aws_security_group” “allow-‐egress” { # name = “${var.user_name}-‐allow-‐egress” # tags = { # Name = “${var.user_name} Allow connecLons out” # } #}
#resource “aws_security_group_rule” “allow-‐out” { # type = “egress” # from_port = 0 # to_port = 65535 # cidr_blocks = ["0.0.0.0/0"] …
supermarket-cluster.tf
![Page 112: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/112.jpg)
Let’s write a test
![Page 114: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/114.jpg)
describe command(‘ping -‐c 1 google.com’) do its(‘stdout’) { should match /1 packets transmiSed, 1 received/ } end
security_groups_spec.rb
![Page 115: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/115.jpg)
$ kitchen verify$ kitchen verify
![Page 116: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/116.jpg)
$ kitchen verify Failure/Error: expected "PING google.com (216.58.218.238) 56(84) bytes of data.\n\n--- google.com ping statistics —\n 1 packets transmitted, 0 received, to match /1 packets transmitted, 1 received/ Diff: @@ -1,2 +1,5 @@ -/1 packets transmitted, 1 received/
![Page 117: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/117.jpg)
Good! We have a failure!
![Page 118: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/118.jpg)
Now let’s make it pass
![Page 119: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/119.jpg)
#resource “aws_security_group” “allow-‐egress” { # name = “${var.user_name}-‐allow-‐egress” # tags = { # Name = “${var.user_name} Allow connecLons out” # } #}
#resource “aws_security_group_rule” “allow-‐out” { # type = “egress” # from_port = 0 # to_port = 65535 # cidr_blocks = ["0.0.0.0/0"] …
supermarket-cluster.tf
![Page 120: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/120.jpg)
resource “aws_security_group” “allow-‐egress” { name = “${var.user_name}-‐allow-‐egress” tags = { Name = “${var.user_name} Allow connecTons out” } }
resource “aws_security_group_rule” “allow-‐out” { type = “egress” from_port = 0 to_port = 65535 cidr_blocks = ["0.0.0.0/0"] …
supermarket-cluster.tf
![Page 121: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/121.jpg)
EC2Chef Server $ terraform apply
EC2 Supermarket
Security Group
Allow SSH
Security Group
Allow Out
supermarket-cluster.tf
![Page 122: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/122.jpg)
Now let’s call this security group from our
Chef Server
![Page 123: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/123.jpg)
… 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
![Page 124: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/124.jpg)
… 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
![Page 125: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/125.jpg)
And the Supermarket Server
![Page 126: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/126.jpg)
… 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
![Page 127: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/127.jpg)
… 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
![Page 128: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/128.jpg)
$ kitchen destroy $ kitchen converge
$ kitchen destroy $ kitchen converge
![Page 129: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/129.jpg)
$ kitchen destroy $ kitchen converge $ kitchen verify
![Page 130: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/130.jpg)
$ kitchen verify$ kitchen verify
$ kitchen verify Command ping -c 1 google.com stdout should match /1 packets transmitted, 1 received/ 1 example, 0 failures
![Page 131: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/131.jpg)
It passes! Now let’s make a
change
![Page 132: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/132.jpg)
Let’s condense the two security groups
into one security group
![Page 133: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/133.jpg)
resource “aws_security_group” “allow-‐egress” { name = “${var.user_name}-‐allow-‐egress” tags = { Name = “${var.user_name} Allow connecWons out” } }
resource “aws_security_group_rule” “allow-‐out” { type = “egress” from_port = 0 to_port = 65535 cidr_blocks = ["0.0.0.0/0"] …
supermarket-cluster.tf
![Page 134: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/134.jpg)
resource “aws_security_group_rule” “allow-‐out” { type = “egress” from_port = 0 to_port = 65535 cidr_blocks = ["0.0.0.0/0"] security_group_id “${aws_security_group.allow-‐egress.id}” }
supermarket-cluster.tf
![Page 135: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/135.jpg)
resource “aws_security_group_rule” “allow-‐out” { type = “egress” from_port = 0 to_port = 65535 cidr_blocks = ["0.0.0.0/0"] security_group_id “${aws_security_group.allow-‐ssh.id}” }
supermarket-cluster.tf
![Page 136: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/136.jpg)
Now our instances should only use the one security group
![Page 137: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/137.jpg)
… 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
![Page 138: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/138.jpg)
… 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
![Page 139: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/139.jpg)
… 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
![Page 140: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/140.jpg)
… 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
![Page 141: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/141.jpg)
EC2Chef Server
$ terraform apply EC2 Supermarket
Security Group
Allow SSHAllow Out
supermarket-cluster.tf
![Page 142: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/142.jpg)
$ kitchen destroy $ kitchen converge
![Page 143: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/143.jpg)
$ kitchen destroy $ kitchen converge $ kitchen verify
![Page 144: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/144.jpg)
$ kitchen verify$ kitchen verify Command ping -c 1 google.com stdout should match /1 packets transmitted, 1 received/
1 example, 0 failures
![Page 145: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/145.jpg)
Now let’s improve the design
![Page 146: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/146.jpg)
By moving the security group code into a module
![Page 147: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/147.jpg)
Source: Terraform Docs
Why Move into a Module?
• Self-contained package
![Page 148: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/148.jpg)
Source: Terraform Docs
Why Move into a Module?
• Self-contained package• Reusable component
![Page 149: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/149.jpg)
• Self-contained package• Reusable component • Improve organization
Source: Terraform Docs
Why Move into a Module?
![Page 150: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/150.jpg)
$ kitchen destroy
![Page 151: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/151.jpg)
$ mkdir security_groups
![Page 152: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/152.jpg)
security-groups/main.tf
![Page 153: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/153.jpg)
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
![Page 154: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/154.jpg)
Now we need to connect to the module
from main config
![Page 155: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/155.jpg)
First, we need to know what variables the module needs
passed to it
![Page 156: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/156.jpg)
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
![Page 157: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/157.jpg)
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 needto be passed in
security-groups/main.tf
![Page 158: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/158.jpg)
Uses variables
supermarket- cluster.tf
Using the Module
![Page 159: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/159.jpg)
variables.tf
supermarket- cluster.tf
Definesvariablesused by config
Using the Module
![Page 160: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/160.jpg)
terraform.tfvars
variables.tf
supermarket- cluster.tf
Definesvalues
for variables
Using the Module
![Page 161: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/161.jpg)
terraform.tfvars
variables.tf
supermarket- cluster.tf
security-groups module
Definesvariables used
by module config
variables.tf
Using the Module
![Page 162: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/162.jpg)
variable “user_name” {}
security-groups/variables.tf
![Page 163: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/163.jpg)
terraform.tfvars
variables.tf
supermarket- cluster.tf
security-groups module
Usesvariables
variables.tf
main.tf
Using the Module
![Page 164: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/164.jpg)
terraform.tfvars
variables.tf
supermarket- cluster.tf
security-groups modulePassesvariables
to module
variables.tf
main.tf
Using the Module
![Page 165: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/165.jpg)
module “security-‐groups” { source = “./security-‐groups” user_name = “${var.user_name}” }
supermarket-cluster.tf
![Page 166: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/166.jpg)
module “security-‐groups” { source = “./security-‐groups” user_name = “${var.user_name}” }
supermarket-cluster.tf
![Page 167: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/167.jpg)
$ kitchen converge
![Page 168: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/168.jpg)
$ kitchen converge -----> Starting Kitchen (v1.10.2) -----> Converging <default-ubuntu>… (…) >>>>>> ------Exception------- >>>>>> Class: Kitchen::ActionFailed Message: 1 actions failed. >>>>>> Converge failed on instance <default-ubuntu>. Please see .kitchen/logs/default-ubuntu.log for more details
![Page 169: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/169.jpg)
$ kitchen converge -----> Starting Kitchen (v1.10.2) -----> Converging <default-ubuntu>… (…) >>>>>> ------Exception------- >>>>>> Class: Kitchen::ActionFailed Message: 1 actions failed. >>>>>> Converge failed on instance <default-ubuntu>. Please see .kitchen/logs/default-ubuntu.log for more details
![Page 170: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/170.jpg)
-‐-‐-‐ Begin output of terraform validate (…) STDOUT: STDERR: Error validaWng: 2 error(s) occurred: * resource 'aws_instance.supermarket_server' config: * unknown resource 'aws_security_group.allow-‐ssh' * referenced in variable aws_security_group.allow-‐ssh.name * resource 'aws_instance.chef_server' config: * unknown resource 'aws_security_group.allow-‐ssh' * referenced in variable aws_security_group.allow-‐ssh.name
.kitchen/logs/default-ubuntu.log
![Page 171: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/171.jpg)
terraform.tfvars
variables.tf
supermarket- cluster.tf
security-groups module
variables.tf
main.tf
output.tf
Passesoutput
values to main
config
Workflow Into The Module
![Page 172: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/172.jpg)
output “sg-‐name” { }
security-groups/output.tf
![Page 173: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/173.jpg)
output “sg-‐name” { value = “${aws_security_group.allow-‐ssh.name}” }
security-groups/output.tf
![Page 174: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/174.jpg)
Now, we need to use this output in our
supermarket-cluster config
![Page 175: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/175.jpg)
… 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
![Page 176: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/176.jpg)
… 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
![Page 177: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/177.jpg)
… 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
![Page 178: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/178.jpg)
… 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
![Page 179: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/179.jpg)
$ kitchen converge
![Page 180: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/180.jpg)
$ kitchen converge $ kitchen verify
![Page 181: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/181.jpg)
$ kitchen verify$ kitchen verify
$ kitchen verify Command ping -c 1 google.com stdout should match /1 packets transmitted, 1 received/
1 example, 0 failures
![Page 182: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/182.jpg)
So we have improved our resource usage
![Page 183: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/183.jpg)
And the code’s organization and
design
![Page 184: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/184.jpg)
With minimal risk
![Page 185: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/185.jpg)
Infrastructure codemust be maintained
and refactored just like application code
![Page 186: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/186.jpg)
Even more so because infrastructure code involves so many
moving pieces
![Page 187: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/187.jpg)
When refactoring, always cover with tests
![Page 188: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/188.jpg)
And refactor one smallpiece at a time
![Page 189: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/189.jpg)
Thank you
![Page 190: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/190.jpg)
Who Am I?
• Software Engineer at Chef
• @nellshamrell• [email protected]
• Former O’Fallon, IL resident (Southern IL ftw!)
Nell Shamrell-Harrington
![Page 191: Refactoring Infrastructure Code](https://reader035.vdocuments.us/reader035/viewer/2022062503/5875f1b01a28ab006e8b50e1/html5/thumbnails/191.jpg)
Who Am I?
Any Questions?
• Software Engineer at Chef
• @nellshamrell• [email protected]
• Former O’Fallon, IL resident (Southern IL ftw!)
Nell Shamrell-Harrington