amazon-web-servicesterraform

How to use in Terraform resources already in AWS (created manually)?


Is there a way to use in my terraform resources that already exist in my AWS account, which were created manually? I don't want to change them, and honestly, I don't want to "touch" them. I just need some of those resources for the environment I'm creating. For example, vpc and IAM.

I have read a bit about import, but I am not sure that it is the answer?


Solution

  • Terraform has 2 ways of using resources that exist outside of the context or directory it's being applied on.

    The first is data sources which allow you to look up existing resources and pass information about them to other resources. The aws_ami data source documentation provides this useful example:

    data "aws_ami" "ubuntu" {
      most_recent = true
    
      filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
      }
    
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
    
      owners = ["099720109477"] # Canonical
    }
    
    resource "aws_instance" "web" {
      ami           = "${data.aws_ami.ubuntu.id}"
      instance_type = "t2.micro"
    
      tags = {
        Name = "HelloWorld"
      }
    }
    

    This allows Terraform to go and fetch the existing AMI that matches the criteria specified in the data source, selects the most recent AMI and then passes the AMI's ID to the aws_instance resource so that it will be built from that AMI.

    Even if you are creating all of your resources with Terraform this can still be useful as it allows you to split up your Terraform configuration to limit blast radius and control what things are updated at the same time while still allowing you to access information about those resources. The aws_subnet_ids documentation has an example that provides a good example of this where the subnets may have been created by Terraform in a different context or directory to the instances you want to create:

    data "aws_subnet_ids" "private" {
      vpc_id = "${var.vpc_id}"
    
      tags = {
        Tier = "Private"
      }
    }
    
    resource "aws_instance" "app" {
      count         = "3"
      ami           = "${var.ami}"
      instance_type = "t2.micro"
      subnet_id     = "${element(data.aws_subnet_ids.private.ids, count.index)}"
    }
    

    The second way of using existing resources is to import them into the state. This allows Terraform to begin managing existing resources as if Terraform had originally created them. As such, any changes made to the Terraform configuration will then be applied to the existing resource when you next run terraform apply. It also means that if you ran terraform destroy then the resource would be removed.