Hacking Terraform
Engineer your Migration to IaC the Smart Way
11.03.2020, DevOps Gathering 2020
1
Slide 2
Slide 2 text
Infrastructure & Automation Lead at Novatec
Consultant, Trainer, Traveller, Music Addict
2
Constantin Weißer | iSibnZe
Slide 3
Slide 3 text
3
Working on Infrastructure
has changed … a lot!
Slide 4
Slide 4 text
● Productive infrastructure was provisioned without Terraform
● Other IaC tool was used (e.g. proprietary)
● Multiple code bases need to merge
● …
Now, you want to migrate to Terraform!
The Problem
4
Slide 5
Slide 5 text
Terraform Internals
5
Slide 6
Slide 6 text
Terraform Basics
6
The Cloud
Cloud API
Terraform
Code
State File
Terraform
(Provider)
Plan File
Slide 7
Slide 7 text
Terraform Reverse Engineered
7
The Cloud
Cloud API
Terraform
Code
State File
Terraform
(Provider)
Plan File
EMPTY
IMPORT
Custom Code
Generator
PICK
1.
2.
3.
Schema
Slide 8
Slide 8 text
Terraform Reverse Engineered
8
The Cloud
Cloud API
Terraform
Code
State File
Terraform
(Provider)
Plan File
EMPTY
IMPORT
Custom Code
Generator
PICK
1.
2.
3.
Schema
Slide 9
Slide 9 text
Hacker’s Setup
9
Slide 10
Slide 10 text
▪ Kotlin + JUnit
Run single functions without coding control flow
▪ Embedded bash snippets + JSON
Communication Terraform ⇔ Kotlin
▪ JSONPath + Kotlin built-ins
Examine and transform data
Choose your Weapons!
10
Slide 11
Slide 11 text
bash {
"""
echo 'What is a type system????'
exit 42
"""
}
Merging the Good and the Ugly
11
Slide 12
Slide 12 text
val format = "+%H:%M:%S"
println(bashCaptureOutput {"date $format"}) // 17:09:25
$format is not a Bash Variable!
12
Slide 13
Slide 13 text
▪ bash{""}
Run a bash script and redirect stdout/stderr to parent process
▪ bashCaptureOutput{""}
Run a bash script and capture output as a string
▪ bashCaptureJson{""}
Run a bash script and parse output as JSON into Kotlin types
Toolkit
13
Slide 14
Slide 14 text
Picking Resources to Import
14
Slide 15
Slide 15 text
▪ Compose a “shopping list”
▪ Multiple ways to proceed
− Compose the list manually
− Query a cloud API
− Use a preexisting IaC tool
In the end we need resource IDs
Picking Resources for Import
15
Slide 16
Slide 16 text
val importRgs = bashCaptureJson {
"""
az group list \
| jq '[ .[] | select (.name | test("^importtest")) ]'
"""
} as List>
Identifying Resources (2)
16
Slide 17
Slide 17 text
val importResources = importRgs.flatMap {
bashCaptureJson { """ az resource list -g "${it["name"]}" """ }
as List>
}.plus(importRgs)
Identifying Resources (3)
17
Slide 18
Slide 18 text
Migration Recipe
18
The Cloud
Cloud API
Terraform
Code
State File
Terraform
(Provider)
Plan File
EMPTY
IMPORT
Custom Code
Generator
PICK
1.
2.
3.
Schema
1. Produce our shopping list
2. Init terraform in an empty directory
3. Import with -allow-missing-config
From this point on, we are “cloud-agnostic”
(Disclaimer: Some providers still need tending)
Quick recap: What has happened so far?
23
BINGO
Slide 24
Slide 24 text
Migration Recipe
24
The Cloud
Cloud API
Terraform
Code
State File
Terraform
(Provider)
Plan File
EMPTY
IMPORT
Custom Code
Generator
PICK
1.
2.
3.
Schema
Slide 25
Slide 25 text
Generating Terraform Code
25
Slide 26
Slide 26 text
provider
generated
terraform
code base
Universal Code Generator
26
state file with
no code
plan file
schema file
provider
schema
plan
Code
generator
All resources are
marked for deletion!
plan command
yields empty plan
Slide 27
Slide 27 text
Plan file contains specified and computed attributes
Read the schema to get the essentials!
The provider schema has all the metadata we
need!
27
Slide 28
Slide 28 text
Post-order tree traversal on the plan file
28
/
R R
A
B
A A
/
R R
A
B
A A
R R
Plan Schema
B
Nodes are data Nodes are types
B
Slide 29
Slide 29 text
Each entry is one of
▪ Attribute / Single value → Value syntax is JSON
▪ Block → Identical to a Resource (except for the name)
→ Recurse
Post-order tree traversal on the plan file
29
Slide 30
Slide 30 text
▪ Resource import: easy
▪ Mapping to terraform types cloud-specific (effort!)
▪ General-purpose code generator in 60 LOC
▪ Quality depends on the provider
− Azure schema yields good results
− AWS schema is puzzling
▪ Better results with dedicated code generators!
− Specific code for each resource type
− It scales! (Time savings for big migrations)
Summary & Observations
30
Slide 31
Slide 31 text
▪ Semi-automate!
▪ Split import & and code generation!
▪ Don’t strive for perfection!
Learnings
31
Slide 32
Slide 32 text
Feel free to reach out:
Constantin Weißer | @iSibnZe
constantin.weisser@novatec-gmbh.de
Thank you for being here! Questions? Discussions?
32