Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Patterns to Refactor Terraform

Rosemary Wang
November 02, 2022

Patterns to Refactor Terraform

Originally presented at NYC HashiCorp User Group

Rosemary Wang

November 02, 2022
Tweet

More Decks by Rosemary Wang

Other Decks in Technology

Transcript

  1. Pattern: Find and Replace 😫😫😫 resource "aws_lb_target_group" "app" { port

    = 3000 } resource "aws_security_group" “app” { ingress { description = "Access to app." from_port = 3000 to_port = 3000 protocol = "tcp" security_groups = aws_security_group.ingress_alb.id } } CODE EDITOR
  2. Pattern: Variables with Defaults 😀😀😀 Easier to move into modules

    later variable "application_port" { default = 3000 } resource "aws_lb_target_group" "app" { port = var.application_port } resource "aws_security_group" “app” { ingress { description = "Access to app." from_port = var.application_port to_port = var.application_port protocol = "tcp" security_groups = aws_security_group.ingress_alb.id } } CODE EDITOR
  3. Pattern: Secrets as Variables 🧐 🧐 🧐 variable "password" {

    type = string sensitive = true } resource "aws_db_instance" "db" { password = var.password } CODE EDITOR
  4. Pattern: Secrets as Dynamic Values 😀😀😀 resource "random_password" "db" {

    length = 16 min_upper = 2 min_lower = 2 min_numeric = 2 min_special = 2 special = true override_special = "`~!#$%^&*?" } resource "aws_db_instance" "db" { password = random_password.db.result } CODE EDITOR
  5. Pattern: Secrets as Data Sources 🤩🤩🤩 data "vault_generic_secret" "db" {

    path = "app/database/admin" } resource "aws_db_instance" "db" { password = data.vault_generic_secret.db.data["password"] } CODE EDITOR
  6. Pattern: Prototype Module 😀😀😀 module "tags" { source = "example/tags/aws"

    organization = "HashiCorp" unit = "HUG" } ## Tags Module with Prototype Pattern variable "organization" {} variable "unit" {} output "tags" { value = { organization = var.organization unit = var.unit expiration = timestamp() } } CODE EDITOR
  7. 1. Variables - names, tags, environments 2. Constants - set

    defaults if overrides, otherwise locals 3. Dynamic Values - use interpolation / data sources 4. Secrets - generate dynamically / data sources
  8. Pattern: Use moved Module Refactor Only resource "aws_instance" "bastion" {}

    module "bastion" {} moved { from = aws_instance.bastion to = 
 module.bastion.aws_instance.bastion } CODE EDITOR developer.hashicorp.com/terraform/language/modules/develop/refactoring
  9. Pattern: Use import Module Refactor TERMINAL # Build module >

    terraform import \
 module.<name>.<resource>.<id> > terraform state rm <resource>.<id> # Comment out old resources in Terraform > terraform plan # check no drift # Delete old resources in Terraform
  10. Pattern: Dependency Injection with Terraform Outputs # create network in

    TFC workspace data "tfe_outputs" "network" { organization = "hashicorp" workspace = "network" } resource "aws_instance" "server" { subnet_id = data.tfe_outputs.network.values.private_subnets.0 } CODE EDITOR
  11. Pattern: Dependency Injection with Data Sources data "aws_vpcs" "network" {

    tags = { unit = "hug" } } data "aws_subnet_ids" "private" { vpc_id = data.aws_vpcs.network.ids.0 tags = { Type = "private" } } resource "aws_instance" "server" { subnet_id = data.aws_subnet_ids.private.ids.0 } CODE EDITOR
  12. Pattern: Use import State Refactor TERMINAL # Copy resource configurations

    to new working directory # Implement dependency injection > cd <new working directory> > terraform init > terraform import <resource>.<id> > terraform plan # check no drift
  13. Pattern: Use import State Refactor TERMINAL > cd <old working

    directory> > terraform state rm <resource>.<id> # Comment out old resources in Terraform > terraform plan # check no drift # Delete old resources in Terraform
  14. Refactor Rules 1. Go from high-level to low-level resources 2.

    Choose resources with fewer dependencies 3. terraform plan = test 4. terraform state = source of truth
  15. Pattern: Blue-green deployment Old Network New Network Servers Servers Modules

    in same state Module in separate state Module in separate state
  16. Pattern: Blue-green deployment Blue resources share the same state terraform

    { cloud { organization = "hashicorp" workspaces { name = “hug" } } } module "network" {} module "servers" { count = 3 subnet = module.network.subnet.0 } CODE EDITOR
  17. Pattern: Blue-green deployment Green resources in separate states terraform {

    cloud { organization = "hashicorp" workspaces { name = "hug-network" } } } module "network" {} output “subnets" { value = module.network.subnets } CODE EDITOR
  18. Pattern: Blue-green deployment Green resources in separate states terraform {

    cloud { organization = "hashicorp" workspaces { name = "hug-servers" } } } data "tfe_outputs" "network" { organization = "hashicorp" workspace = "hug-network" } module "servers" { count = 3 subnet = data.tfe_outputs.network.values.subnets.0 } CODE EDITOR
  19. Pattern: Blue-green deployment Old Network New Network Servers Servers Servers

    Modules in same state Module in separate state Module in separate state Load Balancer 50% 50%
  20. Refactoring is inevitable. 1. Takes time and effort. 2. Go

    high-level to low-level. 3. Roll forward.