Import an existing infrastructure into Terraform

Written by:
Stephane Jourdan
Stephane Jourdan

July 2, 2020

0 mins read

Editor's note: This post originally appeared on CloudSkiff joined Snyk in October 2021.

Sometimes you need to import an existing infrastructure into Terraform. This happens for a lot of reasons. Some people are only just getting started and need to migrate existing infrastructures and build a new code base out of it. Sometimes, even though you are an expert, you just need to go from a POC (proof of concept) that you rapidly built by clicking around in your console to a live project that needs to be stable in production.

Assuming that you already have a live infrastructure that you built from your cloud console… how do you get some Terraform code from it, and more importantly how do you make it work?

In this article, we’ll quickly review the main ways to automatically generate infrastructure code from an existing environment — how to clone an environment, make it work, and ensure that it’s repeatable.

Import an existing infrastructure into Terraform using Terraform import

If you have a small number of resources to turn into code, and the required skills, you can simply re-write the code. But obviously, you need to exactly know how those resources are configured.

In case you already have an existing Terraform code base, once the code is written, you’ll need to terraform import it within your codebase. terraform import is a subcommand from Terraform. And since this code will perfectly match the existing resources within your cloud provider's account, you will achieve a perfect balance between your code, your existing resources, and your TFState file.

Import an existing infrastructure into Terraform with an importer

The option we just mentioned can work for a small number of resources, but for larger environments, the task can be daunting. There are different importers converters, scanners terraform generators, etc. on the market that will help you.

One of them, Terraformer, was built by the Waze SRE Team in Tel Aviv.

Upon giving it your credentials, Terraformer will scan your cloud provider's account for resources and when it finds one, it will convert it into proper Terraform code with a working state file.

The code you will get is not super clean, certainly not DRY but it gets 80% of the job done and you can start building on top of it.

Key steps to turn your imported infrastructures into Terraform code that works

Once you have imported your existing resources into Terraform, it is crucial that you follow a couple of further steps to make it work. Indeed, at this stage, the code is neither clean nor optimized.

Ensure that everything is using variables and ensure that all the variables are unified.

Imagine you have a VPC network called VPC. This situation can be a problem in case you can only have one VPC name per region. This is the case for Amazon S3 buckets. For example, as you can have only one s3 bucket worldwide for all the customers.

Renaming the resources is going to take you a little bit of time. But once you ensure through variables that the names you use are unique, you get pretty sure that the code is repeatable in another region.

Explicitly declare your dependencies.

One of the problems with importing automatically resources to Terraform code is that very often the links between the resources are not made. You will see some resources that make sense as a whole, but that do not have dependencies explicitly declared. Or maybe that are declared but not through variables.

For example, you might face a situation where you have a security group rule declared and linked to an ID for this security group and the whole thing working properly. But if there is no internal link, or more precisely no dependency inside the code, the next time you will try to redeploy it in another region you will probably deploy rules and a security group that are not linked together.

Last but not least: Ensure repeatability through randomness

The last key step is to ensure repeatability through randomness. Basically, randomizing names with a few characters is enough.

I personally use a random string with a suffix. This generates a very simple eight characters long randomized string (without special characters because you don’t want weird characters in your name). I just create local variables here.

For my production and my staging system, I just add them as a suffix. Thus I’m sure that whether I’m in a production or in a staging environment, I will have a unique randomized name based on this. And I can very easily in just a copy-paste create another environment for testing.

1# cluster name needs to be unique
2resource "random_string" "suffix" {
3  length  = 8
4  special = false
6locals {
7  production_cluster_name = "eks-production-${random_string.suffix.result}"
8  staging_cluster_name    = "eks-staging-${random_string.suffix.result}"
10# Production Cluster
11module "production_cluster" {
12  source          = "terraform-aws-modules/eks/aws"
13  version         = "7.0.1"
14  cluster_name    = local.production_cluster_name
15  cluster_version = var.kubernetes_version
16  manage_aws_auth = true
17  worker_ami_name_filter = "amazon-eks-node-1.14-v20200312"
18  subnets = module.vpc.private_subnets
19  vpc_id = module.vpc.vpc_id
20  map_users = var.map_users
21  workers_additional_policies          = [aws_iam_policy.allow_ecr.arn]
22  worker_additional_security_group_ids = []
23  worker_groups = [
24    {
25      name                 = "production-1.14-wg-small"
26      instance_type        = "t3.small"
27      asg_max_size         = 2
28      asg_desired_capacity = 1
29    },
30    {
31      name                 = "production-1.14-wg-medium"
32      instance_type        = "t3.medium"
33      asg_max_size         = 3
34      asg_desired_capacity = 2
35      asg_min_size         = 2
36    }
37  ]
38  tags = {
39    environment = "production"
40    Terraform   = "true"
41  }
42  workers_group_defaults = {
43    key_name = aws_key_pair.admin.key_name
44  }

Wrap up

Importing your resources is just step 1 and rarely is enough.

To make your code actionable, your next steps are to:

  • Ensure that everything is using variables

  • Ensure that all the variables are unified.

  • Declare your dependencies and link them

  • Randomize variables to generate unique names.

Securing your Terraform code

Snyk IaC secures your Terraform configs (and Kubernetes, CloudFormation, and ARM templates!) as you code, with guided fixes so you can merge and move on. You can test as you write, monitor for changes in your git repositories, and automate testing in your build pipelines before deployment. Getting started with a Free plan takes minutes, while a breach from an IaC misconfiguration can cause damage to last a lifetime. Sign up and start securing your configs below.