When working with Terraform, the changes are good that you are not starting from scratch, but you already have something setup previously and now want to manage it with Terraform
Import a resource
Terraform allows you to import existing resources. I will show this with a simple example on hcloud. First I create a server manually in the console:
Before we can run terraform import we have to manually create a resource configuration in example.tf as follows:
The actual import command looks as follows
Where
ADDRESS is a resource address, which identifies zero or more resource instances in your overall configuration.
ID is the provider specific id of the resource to be imported.
So in my case, ADDRESS is hcloud_server.node1 and ID is 20389321 as we can see here
So running terraform import hcloud_server.node1 20389321 is the way to go:
This generates a terraform.tfstate, which contains the server resource we previously created:
Now, that we have the object, our example.tf still looks as defined above. So how to we get the a more complete tf file which? It requires some manual work. You would run a terraform plan, which would show you the difference, between the state in terraform.tfstate vs. the definition in your configuration files:
As in example.tf we did not specify an image, terraform plans to remove that. We also can see the *known after apply which basically means unknown. It’s a bit confusing, cause as soon as I adjust my example.tf adding the missing image ….
… after running a terraform plan, these unknowns are gone:
This looks better, but there are still elements, which will be added. Still, that should be fine, so running terraform apply, will apply the changes, including renaming the node to node1.
Remove objects from state
Using terraform state rm allows you to remove a binding to an existing remote object without first destroying it. According to Terraform, this should be “a less common situation”, I still show this by an example. Let’s add a second node node2 to example.tf …
… and then run terraform apply, which will create the second node.
Now let’s destroy everything with Terraform, but keep node2. For that we remove node2 from the state file by running
So now, when we run terraform destroy it will only destroy node1
A more complex example with hetzner firewalls
As we have seen above, when we imported node1, it actually had a firewall attached. This is cause I have some [Firewalls][hcloud_firewalls] defined:
As we destroyed everything, let’s create a new node node-with-firewall, which has one of the firewalls attached.
Before we create our terraform configuration, we have a look at the hcloud provider docu. Based on what I see there, I probably need, anhcloud_server object, two hcloud_firewall objects and a
hcloud_firewall_attachment, where latter “attaches resource to a Hetzner Cloud Firewall”. Hence my terraform configuration (example.tf) looks as follows:
Now let’s import these objects, as we learned above. For servers and firewalls the id can be found easily so I run
As we can see, firewall-ssh-only is missing the rules in example.tf, hence I add them:
After, I run a terraform apply which succeeds. Now let’s change the firewall assignment of our server to the firewall-ssh-only:
Let’s see what terraform plan says:
Once we apply the changes with terraform apply we can see, that the server is assigned to firewall-ssh-only
Unfortunately, the node is also still assigned to firewall-no-access. This is not wrong, cause a server can be attached to multiple firewall objects. Still it’s not what I want, hence the correct way is to add a second hcloud_firewall_attachment object to my terraform configuration, while I comment out the first object, which will trigger a destruction of it:
That should do the trick, looking at the changes terraform apply wants to do
Finally we got the correct configuration, where we switched the firewall assignment of our server to firewall-only-ssh
Summary
In this post I covered the basic concept of importing existing resources and how to remove the binding of objects Terraform manages. Real live example may be much more complex and it’s important you have a look at the documentation of your module, as well understand the basics of the resources you manage.