Let's play around with our VPC a bit to better understand how resource dependencies are handled. Instead of adding a subnet, let's destroy complete infrastructure we have so far and then plan creation from scratch:
$> terraform destroy $> terraform plan # ... + aws_subnet.public availability_zone: "<computed>" cidr_block: "10.0.1.0/24" map_public_ip_on_launch: "false" vpc_id: "${aws_vpc.my_vpc.id}" # ...
Terraform doesn't know the VPC ID yet, so it doesn't show it to you in the plan. Let's apply the template and observe the order of resource creation:
$> terraform apply aws_vpc.my_vpc: Creating... cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" dhcp_options_id: "" => "<computed>" enable_classiclink: "" => "<computed>" enable_dns_hostnames: "" => "<computed>" enable_dns_support: "" => "<computed>" instance_tenancy: "" => "<computed>" main_route_table_id: "" => "<computed>" aws_vpc.my_vpc: Creation complete aws_subnet.public: Creating... availability_zone: "" => "<computed>" cidr_block: "" => "10.0.1.0/24" map_public_ip_on_launch: "" => "false" vpc_id: "" => "vpc-8f8568e7" aws_subnet.public: Creation complete
Terraform knew (from the graph it built) that subnet requires VPC to exist, so it created it first, followed by subnet.
What happens if we recreate the VPC? Let's try it out with the help of the taint
command. terraform taint
marks a single resource for recreation. The resource will be destroyed and then created again.
$> terraform taint aws_vpc.my_vpc The resource aws_vpc.my_vpc in the module root has been marked as tainted! $> terraform plan -/+ aws_subnet.public availability_zone: "eu-central-1b" => "<computed>" cidr_block: "10.0.1.0/24" => "10.0.1.0/24" map_public_ip_on_launch: "false" => "false" vpc_id: "vpc-8f8568e7" => "${aws_vpc.my_vpc.id}" (forces new resource) -/+ aws_vpc.my_vpc (tainted) cidr_block: "10.0.0.0/16" => "10.0.0.0/16" default_network_acl_id: "acl-a52febcd" => "<computed>" default_security_group_id: "sg-feafde96" => "<computed>" dhcp_options_id: "dopt-b82bc8d1" => "<computed>" enable_classiclink: "" => "<computed>" enable_dns_hostnames: "false" => "<computed>" enable_dns_support: "true" => "<computed>" instance_tenancy: "default" => "<computed>" main_route_table_id: "rtb-1913d071" => "<computed>"
Terraform got us covered: after recreating a VPC, it will also recreate a subnet because it knows that subnet depends on the VPC to exist. As AWS doesn't allow to simply change the VPC ID of existing subnet, Terraform will force the creation of the completely new subnet.
Which parameters the resource will use depends on provider implementation. Normally, it is mentioned in the Terraform documentation page for a specific resource.
If you try to draw a graph again, you won't see much difference from the previous one. The special destroy nodes are not included by default, and in order to see them, you need to specify the -verbose
argument:
$> terraform graph -verbose | dot -Tpng > graph.png
Now we can see one node of the graph for the existing resource and another node to destroy it. Nodes are added to the graph in an order that will lead to the correct removal of resources that needs to be removed.
Before we finish with graphs, let's take a quick look at how dependencies are specified inside state file:
"aws_subnet.public": { "type": "aws_subnet", "depends_on": [ "aws_vpc.my_vpc" ], "primary": { "id": "subnet-2116e25b", "attributes": { "availability_zone": "eu-central-1b", "cidr_block": "10.0.1.0/24", "id": "subnet-2116e25b", "map_public_ip_on_launch": "false", "tags.%": "0", "vpc_id": "vpc-8f8568e7" }, "meta": {}, "tainted": false },
Note the depends_on
part--Terraform saves references to resources, and this one depends on inside this key. Most of the time, dependencies in Terraform just work. You just need to reference resources inside the template, and Terraform will do the job of building a graph and order operations with it. But sometimes, you need a little bit more control over the dependencies.
There is another advantage of graphs inside Terraform--it allows you to process nodes in parallel if they don't depend on each other. By default, up to 10 graph nodes can be processed in parallel. You could specify the -parallelism
flag for apply
, plan
, and destroy
commands, but it's rather an advanced operation, and in most cases, you don't need it.
18.119.105.239