Playing with Terraform graphs

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 the 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>"
You might have noted already: in Terraform outputs, - means resource will be destroyed, -/+ means recreation, and + is for creation.

Terraform has got us covered: after recreating a VPC, it will also recreate a subnet because it knows that a subnet depends on the VPC to exist. As AWS doesn't allow simply changing the VPC ID of an existing subnet, Terraform will force the creation of a 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
As of Terraform version 0.8.2, the -verbose flag seems to be either broken or temporarily disabled and doesn't actually draw destroy nodes. The source code for this flag is still there, deep inside Terraform. The preceding diagram was generated with Terraform 0.7.2.

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 need to be removed.

Before we finish with graphs, let's take a quick look at how dependencies are specified inside the 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 dependencies.

There is another advantage of graphs inside Terraform - they allow 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.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset