124 lines
5.2 KiB
Plaintext
124 lines
5.2 KiB
Plaintext
|
---
|
||
|
page_title: Resource Graph
|
||
|
description: >-
|
||
|
Terraform builds a dependency graph from the Terraform configurations, and
|
||
|
walks this graph to generate plans, refresh state, and more. This page
|
||
|
documents the details of what are contained in this graph, what types of nodes
|
||
|
there are, and how the edges of the graph are determined.
|
||
|
---
|
||
|
|
||
|
# Resource Graph
|
||
|
|
||
|
Terraform builds a
|
||
|
[dependency graph](https://en.wikipedia.org/wiki/Dependency_graph)
|
||
|
from the Terraform configurations, and walks this graph to
|
||
|
generate plans, refresh state, and more. This page documents
|
||
|
the details of what are contained in this graph, what types
|
||
|
of nodes there are, and how the edges of the graph are determined.
|
||
|
|
||
|
~> **Advanced Topic!** This page covers technical details
|
||
|
of Terraform. You don't need to understand these details to
|
||
|
effectively use Terraform. The details are documented here for
|
||
|
those who wish to learn about them without having to go
|
||
|
spelunking through the source code.
|
||
|
|
||
|
For some background on graph theory, and a summary of how
|
||
|
Terraform applies it, see the HashiCorp 2016 presentation
|
||
|
[_Applying Graph Theory to Infrastructure as Code_](https://www.youtube.com/watch?v=Ce3RNfRbdZ0).
|
||
|
This presentation also covers some similar ideas to the following
|
||
|
guide.
|
||
|
|
||
|
## Graph Nodes
|
||
|
|
||
|
There are only a handful of node types that can exist within the
|
||
|
graph. We'll cover these first before explaining how they're
|
||
|
determined and built:
|
||
|
|
||
|
- **Resource Node** - Represents a single resource. If you have
|
||
|
the `count` metaparameter set, then there will be one resource
|
||
|
node for each count. The configuration, diff, state, etc. of
|
||
|
the resource under change is attached to this node.
|
||
|
|
||
|
- **Provider Configuration Node** - Represents the time to fully
|
||
|
configure a provider. This is when the provider configuration
|
||
|
block is given to a provider, such as AWS security credentials.
|
||
|
|
||
|
- **Resource Meta-Node** - Represents a group of resources, but
|
||
|
does not represent any action on its own. This is done for
|
||
|
convenience on dependencies and making a prettier graph. This
|
||
|
node is only present for resources that have a `count`
|
||
|
parameter greater than 1.
|
||
|
|
||
|
When visualizing a configuration with `terraform graph`, you can
|
||
|
see all of these nodes present.
|
||
|
|
||
|
## Building the Graph
|
||
|
|
||
|
Building the graph is done in a series of sequential steps:
|
||
|
|
||
|
1. Resources nodes are added based on the configuration. If a
|
||
|
diff (plan) or state is present, that meta-data is attached
|
||
|
to each resource node.
|
||
|
|
||
|
1. Resources are mapped to provisioners if they have any
|
||
|
defined. This must be done after all resource nodes are
|
||
|
created so resources with the same provisioner type can
|
||
|
share the provisioner implementation.
|
||
|
|
||
|
1. Explicit dependencies from the `depends_on` meta-parameter
|
||
|
are used to create edges between resources.
|
||
|
|
||
|
1. If a state is present, any "orphan" resources are added to
|
||
|
the graph. Orphan resources are any resources that are no
|
||
|
longer present in the configuration but are present in the
|
||
|
state file. Orphans never have any configuration associated
|
||
|
with them, since the state file does not store configuration.
|
||
|
|
||
|
1. Resources are mapped to providers. Provider configuration
|
||
|
nodes are created for these providers, and edges are created
|
||
|
such that the resources depend on their respective provider
|
||
|
being configured.
|
||
|
|
||
|
1. Interpolations are parsed in resource and provider configurations
|
||
|
to determine dependencies. References to resource attributes
|
||
|
are turned into dependencies from the resource with the interpolation
|
||
|
to the resource being referenced.
|
||
|
|
||
|
1. Create a root node. The root node points to all resources and
|
||
|
is created so there is a single root to the dependency graph. When
|
||
|
traversing the graph, the root node is ignored.
|
||
|
|
||
|
1. If a diff is present, traverse all resource nodes and find resources
|
||
|
that are being destroyed. These resource nodes are split into two:
|
||
|
one node that destroys the resource and another that creates
|
||
|
the resource (if it is being recreated). The reason the nodes must
|
||
|
be split is because the destroy order is often different from the
|
||
|
create order, and so they can't be represented by a single graph
|
||
|
node.
|
||
|
|
||
|
1. Validate the graph has no cycles and has a single root.
|
||
|
|
||
|
## Walking the Graph
|
||
|
|
||
|
<a id="walking-the-graph"></a>
|
||
|
|
||
|
To walk the graph, a standard depth-first traversal is done. Graph
|
||
|
walking is done in parallel: a node is walked as soon as all of its
|
||
|
dependencies are walked.
|
||
|
|
||
|
The amount of parallelism is limited using a semaphore to prevent too many
|
||
|
concurrent operations from overwhelming the resources of the machine running
|
||
|
Terraform. By default, up to 10 nodes in the graph will be processed
|
||
|
concurrently. This number can be set using the `-parallelism` flag on the
|
||
|
[plan](/cli/commands/plan), [apply](/cli/commands/apply), and
|
||
|
[destroy](/cli/commands/destroy) commands.
|
||
|
|
||
|
Setting `-parallelism` is considered an advanced operation and should not be
|
||
|
necessary for normal usage of Terraform. It may be helpful in certain special
|
||
|
use cases or to help debug Terraform issues.
|
||
|
|
||
|
Note that some providers (AWS, for example), handle API rate limiting issues at
|
||
|
a lower level by implementing graceful backoff/retry in their respective API
|
||
|
clients. For this reason, Terraform does not use this `parallelism` feature to
|
||
|
address API rate limits directly.
|