Importing Infrastructure

Sign Up to Build

About this Architecture

Here is some information about this architecture.

How to Build This Solution

Here are the steps you can follow to build this solution on your own.

At some point, you may want to import an existing resource into your Terraform configuration. This could be a one-off operation, or it could be something you do as you transition a larger project to being managed by Terraform.

Whatever your reason, we’ll show you how to do it here!

It is important to note that Terraform can only import the external resource into its state file. You will have to write the configuration for the resource manually. However, Terraform does say that future versions of Terraform will create the configuration.

Get Your AWS Credentials

If you're using the Skillmix Labs feature, open the lab settings (the beaker icon) on the right side of the code editor. Then, click the Start Lab button to start hte lab environment.

Wait for the credentials to load. Then run this in the terminal.

Be sure to enter in your own access key and secret key and name your profile 'smx-lab'.

$ aws configure --profile smx-lab
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: us-west-2
Default output format [None]: 

Note: If you're using your own AWS account you'll need to ensure that you've created and configured a named AWS CLI profile named smx-lab.

Create a Working Directory & Files

Let’s start off by creating a working directory and the files that we’ll need to use. Open your terminal or command prompt and create a working directory.

# create the directory
$ mkdir import-lab && cd import-lab

# create the files needed
$ touch main.tf 

Open the main.tf file and add the following code to bootstrap our project:

terraform {
  required_version = ">= 0.15"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.46"
    }
  }
}

provider "aws" {
  region  = "us-west-2"
  profile = "skillmix-lab"
}

Then, initialize the project:

$ terraform init

Open the EC2 Console

Great, now that we have a project setup, let’s continue this journey by importing the EC2 instance. We need to have some information about the EC2 instance. We’ll get this info from the page.

Using the lab or AWS account credentials, open the EC2 Console. Make sure you’re in the Oregon (us-west-2) region.

From the EC2 Console, open the details page of the EC2 instance and collect the following details:

  • Instance ID e.g. i-xxxxxxxxxxxxxxx

  • AMI ID e.g. ami-xxxxxxxxxxxx

  • Subnet ID e.g. subnet-xxxxxxxxx

  • Security Group ID e.g. sg-xxxxxxxxxx

Create the EC2 Configuration

The first step in our journey is to create the EC2 instance configuration. Open the main.tf file and append the following code:

// previous code

resource "aws_instance" "lab_server" {
  ami           = ""
  instance_type = ""
  vpc_security_group_ids = [""]
  subnet_id              = ""
}

For example:

// previous code

resource "aws_instance" "lab_server" {
  ami           = "ami-0ddf424f81ddb0720"
  instance_type = "t2.micro"
  vpc_security_group_ids = ["sg-080634c1a0af961b3"]
  subnet_id              = "subnet-0b57244bf89031a4a"
}

Import the EC2 Resource & Apply Configuration

Now, we can run the import command. You’ll need your instance ID.

$ terraform import aws_instance.lab_server i-0dffa0dd83e8f490c

aws_instance.lab_server: Importing from ID "i-0dffa0dd83e8f490c"...
aws_instance.lab_server: Import prepared!
  Prepared aws_instance for import
aws_instance.lab_server: Refreshing state... [id=i-0dffa0dd83e8f490c]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Now that you’ve run the import command, let’s run the plan command to see what Terraform thinks of the new resource. It’s important that the plan command returns a result like the following, and does not recommend to delete the instance.

$ terraform plan

aws_instance.lab_server: Refreshing state... [id=i-0cc0c4d8531bd7717]

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your configuration and the remote system(s). As a result,
there are no actions to take.

If that’s what you see, then we’re all good!

Inspect State

Let’s check on our state to see what it shows.

$ terraform show

# aws_instance.lab_server:
resource "aws_instance" "lab_server" {
    ami                                  = "ami-0ddf424f81ddb0720"
    arn                                  = "arn:aws:ec2:us-west-2:422445542010:instance/i-0cc0c4d8531bd7717"
    associate_public_ip_address          = true
    availability_zone                    = "us-west-2b"
    cpu_core_count                       = 1
    cpu_threads_per_core                 = 1
    disable_api_termination              = false
    ebs_optimized                        = false
    get_password_data                    = false
    hibernation                          = false
    id                                   = "i-0cc0c4d8531bd7717"
    instance_initiated_shutdown_behavior = "stop"
    instance_state                       = "running"
    instance_type                        = "t2.micro"

...more output

Create the Security Group Configuration

Let’s import one more resource. Our lab account has a security group. Go to the Security Group Console, and collect the following information:

  • Name = “ImportTfLab”

  • Security Group ID e.g. sg-xxxxxxx

  • VPC ID e.g. vpc-xxxxxxx

  • Description

Then, open the main.tf for editing and append this code.

// previous code

resource "aws_security_group" "web_sg" {
  name   = "ImportTfLab"
  vpc_id = "<your vpc ID>"
  description = "learning how to import resources"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = -1
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Import the Security Group

Now, run the command to import the security group. Remember to replace the sg-xxx value with your security group ID.

$ terraform import aws_security_group.web_sg sg-xxxxx

aws_security_group.web_sg: Import prepared!
  Prepared aws_security_group for import
aws_security_group.web_sg: Refreshing state... [id=sg-080634c1a0af961b3]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

You can run terraform plan to ensure all was imported properly. If Terraform wants to destroy the security group, then you’ve made a mistake somewhere.

$ terraform plan

aws_security_group.web_sg: Refreshing state... [id=sg-080634c1a0af961b3]
aws_instance.lab_server: Refreshing state... [id=i-0cc0c4d8531bd7717]

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your configuration and the remote system(s). As a result,
there are no actions to take.

Inspect State

Now that we have the EC2 instance and security group imported, let’s check our state.

$ terraform show

# aws_instance.lab_server:
resource "aws_instance" "lab_server" {
    ami                                  = "ami-0ddf424f81ddb0720"
    arn                                  = "arn:aws:ec2:us-west-2:422445542010:instance/i-0cc0c4d8531bd7717"
    associate_public_ip_address          = true
    availability_zone                    = "us-west-2b"
    cpu_core_count                       = 1
    cpu_threads_per_core                 = 1
    disable_api_termination              = false
    ebs_optimized                        = false
    get_password_data                    = false
    hibernation                          = false
    id                                   = "i-0cc0c4d8531bd7717"
    instance_initiated_shutdown_behavior = "stop"
    instance_state                       = "running"
    instance_type                        = "t2.micro"

...more output

# aws_security_group.web_sg:
resource "aws_security_group" "web_sg" {
    arn         = "arn:aws:ec2:us-west-2:422445542010:security-group/sg-080634c1a0af961b3"
    description = "learning how to import resources"
    egress      = [
        {
            cidr_blocks      = [
                "0.0.0.0/0",
            ]
            description      = ""
            from_port        = 0
            ipv6_cidr_blocks = []
            prefix_list_ids  = []
            protocol         = "-1"
            security_groups  = []
            self             = false
            to_port          = 0
        },
    ]
    id          = "sg-080634c1a0af961b3"

...more output

Done!