terraform[Edit section][Copy link]
Terraform is an infrastructure as code tool that allows engineers to define, provision, and manage data center infrastructure using a declarative configuration language. It enables teams to version control their infrastructure definitions, collaborate on infrastructure changes, and automate the process of creating and updating cloud resources across multiple providers.
The core functionality of Terraform is implemented in the internal
directory, with several key subdirectories handling different aspects of the system:
-
Configuration Handling: The
…/configs
directory contains the logic for loading, parsing, and validating Terraform configuration files. It uses a custom implementation of the HashiCorp Configuration Language (HCL) to represent infrastructure definitions. -
State Management: The
…/states
directory implements the state management system, which tracks the current state of managed infrastructure. It includes functionality for reading and writing state files, as well as managing remote state storage. -
Provider System: The
…/providers
directory defines the interface for Terraform providers, which are plugins that allow Terraform to interact with various infrastructure platforms. The provider system uses a gRPC-based plugin architecture, implemented in the…/plugin
directory. -
Execution Engine: The
…/terraform
directory contains the core logic for planning and applying infrastructure changes. The planning process involves:- Comparing the desired configuration against the current state
- Generating a dependency graph of resources
- Determining the necessary actions to bring the infrastructure in line with the configuration
-
Command Line Interface: The
…/command
directory implements the various CLI commands that users interact with, such asinit
,plan
, andapply
.
Key design choices in Terraform include:
- Declarative language: Users specify the desired end state of their infrastructure, rather than the steps to achieve it.
- Provider plugin system: Allows for extensibility and support for a wide range of infrastructure platforms.
- State management: Enables Terraform to track the current state of resources and plan incremental changes.
- Dependency graph: Resources are organized into a directed acyclic graph (DAG) to determine the correct order of operations.
For more details on specific components, you can refer to the following sections:
Language and Configuration[Edit section][Copy link]
References: internal/lang
, internal/configs
The Scope
struct in …/scope.go
is the central component for managing the evaluation context of Terraform expressions and blocks. It contains fields for resolving references, parsing references, and managing available functions. The SetActiveExperiments
method allows activation of experimental behaviors for specific modules.
Core Language Implementation[Edit section][Copy link]
References: internal/lang
The Scope
struct in …/scope.go
is the central component for evaluating Terraform expressions and blocks. It manages the evaluation context, including:
Configuration Loading and Parsing[Edit section][Copy link]
References: internal/configs
, internal/configs/configload
, internal/configs/parser_config.go
, internal/configs/resource.go
, internal/configs/module.go
, internal/configs/config.go
The Loader
struct in …/loader.go
is the primary mechanism for loading Terraform configurations. It uses a configs.Parser
instance to read configuration files and a moduleMgr
to install and locate modules.
Schema and Type System[Edit section][Copy link]
References: internal/configs/configschema
The Block
struct in …/schema.go
is the core component for defining Terraform configuration schemas. It contains Attributes
and BlockTypes
maps, representing attributes and nested blocks respectively. The Attribute
struct defines individual attributes with properties like Type
, Required
, Optional
, and Computed
.
Module Management[Edit section][Copy link]
References: internal/configs/configload
The moduleMgr
struct in …/module_mgr.go
handles installation and tracking of Terraform modules. It uses:
State File Management[Edit section][Copy link]
References: internal/states/statefile
The statefile
package in …/statefile
manages Terraform state files. Key functionalities include:
Remote State Management[Edit section][Copy link]
References: internal/states/remote
The State
struct in …/state.go
is the primary implementation for managing remote state. It interacts with remote storage backends through the Client
interface defined in …/remote.go
. Key functionalities include:
State Manager Interfaces[Edit section][Copy link]
References: internal/states/statemgr
The statemgr
package defines key interfaces for managing Terraform state:
Stack State Management[Edit section][Copy link]
References: internal/stacks/stackstate
The State
struct in …/state.go
represents the state snapshot, containing information about component instances, resource instance objects, input variables, and output values. It provides methods for accessing and manipulating the state:
State Keys and Addressing[Edit section][Copy link]
References: internal/stacks/stackstate/statekeys
The statekeys
package manages state keys and addresses different elements of the Terraform stack state. The Key
interface defines the contract for state keys, with methods KeyType()
and rawSuffix()
. The String()
function generates string representations of Key
objects for use in the RPC API.
Provider Interface and Implementation[Edit section][Copy link]
References: internal/providers
The Interface
in …/provider.go
defines the core set of methods required for a Terraform resource provider plugin. Key methods include:
Plugin System[Edit section][Copy link]
References: internal/plugin
The Terraform plugin system uses gRPC for communication between the Terraform core and provider plugins. The …/plugin
directory contains the core implementation of this system.
Provider Discovery and Installation[Edit section][Copy link]
References: internal/getproviders
The RegistrySource
struct in …/registry_source.go
is responsible for discovering and installing providers from their originating registries. It uses a disco.Disco
instance to interact with provider registry services.
Provider Requirements and Version Management[Edit section][Copy link]
References: internal/getproviders/providerreqs
The Requirements
type manages provider version constraints, representing them as a map of addrs.Provider
to VersionConstraints
. Each entry defines the acceptable versions for a specific provider, with empty constraints indicating any version is allowed. The Merge()
method combines requirements from multiple sources, ensuring only selections that satisfy all source requirements are permitted.
Backend Implementations[Edit section][Copy link]
References: internal/backend/remote-state
, internal/backend/local
Terraform supports various backend types for storing state, including local, remote, and cloud-based options. The …/remote-state
directory contains implementations for several remote state backends:
Remote Execution[Edit section][Copy link]
References: internal/cloud
, internal/backend/remote
The Cloud
struct in …/backend.go
implements the core functionality for remote execution in Terraform Cloud. It provides methods for configuring the backend, managing workspaces, and executing Terraform operations remotely.
Backend Configuration[Edit section][Copy link]
References: internal/backend/init
, internal/backend/backendbase
Backend configuration in Terraform is handled primarily through the …/init
and …/backendbase
packages. The initialization process is managed by the Init()
function in …/init.go
, which populates a backends
map with available backend implementations.
State Management[Edit section][Copy link]
References: internal/states
, internal/backend
, internal/cloud
, internal/command/jsonstate
, internal/states/remote
, internal/states/statemgr
The State
struct in …/state.go
is the top-level representation of Terraform's state, containing the state for all modules, resources, and output values. It provides methods for managing resources, modules, and output values:
State Storage and Serialization[Edit section][Copy link]
References: internal/states
, internal/states/statefile
, internal/command/jsonstate
Terraform's state storage and serialization is primarily handled in the …/states
package. The State
struct represents the root of the state hierarchy, containing a map of child modules and their resources. Each resource is represented by Resource
structs, which contain Instance
objects holding the actual resource data. The State
struct includes fields for output values, with functions such as SetOutputValue
and RemoveOutputValue
to manage these values.
State Value Management[Edit section][Copy link]
References: internal/states/output_value.go
, internal/states/state.go
, internal/states/sync.go
In Terraform, state values are managed through structures and methods that handle output values. The …/output_value.go
file defines the OutputValue
struct, which encapsulates the details of an output value, including its address (Addr
), actual value (Value
), and sensitivity (Sensitive
). Non-ephemeral output values are stored and maintained across Terraform runs.
State Manager Interfaces[Edit section][Copy link]
References: internal/states/statemgr/filesystem.go
, internal/states/statemgr/lock.go
, internal/states/statemgr/persistent.go
, internal/states/statemgr/statemgr_fake.go
, internal/states/remote
The Terraform state manager interfaces facilitate the access and modification of the state, encapsulating the complexities of state handling. The Filesystem
struct in …/filesystem.go
manages persistent state files on the local filesystem. It implements the Full
, PersistentMeta
, and Migrator
interfaces, offering methods like State()
, WriteState()
, and RefreshState()
for state retrieval and updates. Locking mechanisms are provided through Lock()
and Unlock()
, controlling access to state files.
Error Handling and State Recovery[Edit section][Copy link]
References: internal/backend/local/backend_apply.go
, internal/states/remote/state.go
In Terraform's state operations, error handling and state recovery are critical for maintaining the integrity of state data. The opApply
function within …/backend_apply.go
orchestrates the application of Terraform plans, incorporating checks and a StateHook
for periodic state persistence. When persistence errors occur, the backupStateForError
function attempts to create a local backup of the state file, offering a safety net for state recovery.
Kubernetes Backend State Management[Edit section][Copy link]
References: internal/backend/remote-state/kubernetes/backend.go
, internal/backend/remote-state/kubernetes/client.go
In …/backend.go
, the Backend
struct is central to managing the state with the Kubernetes backend. It leverages the New()
function to instantiate the backend with necessary configurations. The Configure(configVal cty.Value)
method is pivotal in setting up the backend with user-provided configurations, which includes handling the secret_suffix
attribute. This attribute is crucial as it appends a user-defined suffix to the Kubernetes secret name, aiding in the organization and identification of Terraform state secrets.
Provider System[Edit section][Copy link]
References: internal/providers
, internal/plugin
, internal/getproviders
The provider system in Terraform is implemented primarily through the GRPCProvider
struct in …/grpc_provider.go
. This struct handles the client-side of gRPC communication with provider plugins, implementing methods defined in the providers.Interface
:
Provider Interfaces and Lifecycle Management[Edit section][Copy link]
References: internal/providers/provider.go
, internal/providers/ephemeral.go
In the Terraform codebase, the …/provider.go
file outlines the Interface
that all resource provider plugins must implement. This interface encapsulates a suite of methods essential for the lifecycle management of resources, including the creation, reading, updating, and deletion of infrastructure components. Among these methods, the following are integral to the provider's operation:
Provider Plugin Communication[Edit section][Copy link]
References: internal/plugin/grpc_provider.go
, internal/plugin6/grpc_provider.go
Communication between Terraform and provider plugins is facilitated through the gRPC protocol, managed by the types GRPCProviderPlugin
and GRPCProvider
located in …/grpc_provider.go
. These types are integral to the client-side operations, enabling Terraform Core to interact with various provider plugins.
Provider Schema Management[Edit section][Copy link]
References: internal/providers/schemas.go
Within …/schemas.go
, Terraform manages the definition and utilization of provider schemas, which are essential for understanding the configuration and capabilities of different types of resources within a provider. The ProviderSchema
type serves as a central repository for all the schemas related to configurable objects that a provider supports. It is essentially an alias for the GetProviderSchemaResponse
type, which encapsulates the schema information.
Provider Testing and Mocking[Edit section][Copy link]
References: internal/providers/testing/provider_mock.go
, internal/providers/mock.go
, internal/providers/functions_test.go
In …/provider_mock.go
, a MockProvider
struct is implemented to simulate the behavior of a real provider, crucial for testing the interaction between Terraform and various providers. This mock provider is designed to replicate the providers.Interface
, allowing developers to test without the need for actual cloud services. It provides a set of methods corresponding to provider operations, such as GetProviderSchema()
, ReadResource()
, and PlanResourceChange()
, among others. Developers can specify the behavior of these methods by setting fields like GetProviderSchemaResponse
and ReadResourceFn
to control the mock responses and simulate different scenarios.
Backend and Remote Operations[Edit section][Copy link]
References: internal/backend
, internal/cloud
, internal/states
The Backend
struct in …/backend.go
defines the core interface for Terraform backends. Key methods include:
Local Backend Operations[Edit section][Copy link]
References: internal/backend/local
In the …/local
directory, the Local
struct serves as the foundation for the local backend's operations. It manages the application of configurations by implementing the backend.Backend
interface, which includes methods for core operations such as apply, plan, and refresh. The local backend's primary role is to handle the Terraform state locally, ensuring that state management is consistent and reliable.
Cloud Backend State Management[Edit section][Copy link]
References: internal/cloud
In …/state.go
, the State
struct manages state information within the Terraform cloud backend. It implements interfaces such as statemgr.Full
, statemgr.Migrator
, and statemgr.IntermediateStateConditionalPersister
.
State Persistence and Error Handling[Edit section][Copy link]
References: internal/backend/local/backend_apply.go
In …/backend_apply.go
, the opApply
function orchestrates the application of a Terraform plan to the target infrastructure, with a focus on state persistence and error handling. The function follows these steps:
Remote Backend Error Handling[Edit section][Copy link]
References: internal/backend/remote
, internal/cloud
Error handling in the remote backend is implemented through a set of predefined error constants and specialized functions for processing and displaying error messages. Key error constants include:
Read moreState Management Refinements[Edit section][Copy link]
References: internal/states
, internal/states/remote
, internal/states/statemgr
The Terraform codebase has undergone a refinement in state management, particularly with the introduction of the State
struct in …/state.go
. This struct is central to the remote state management, facilitating the reading, writing, and persistence of state in remote storage. The State
struct's methods, such as WriteState()
and PersistState()
, are pivotal in maintaining the state's integrity during operations.
Core Execution Engine[Edit section][Copy link]
References: internal/terraform
, internal/plans
The Context
struct in …/context.go
is the central component for executing Terraform operations. It manages the overall state and orchestrates the planning and applying of infrastructure changes.
Apply Functionality Testing[Edit section][Copy link]
References: internal/terraform/context_apply_test.go
In …/context_apply_test.go
, a series of test cases scrutinize the Apply
operation's robustness within Terraform's context. These tests are pivotal in validating the correct application of resources, ensuring that the provider's stop behavior is executed as expected, and confirming the handling of unstable values and computed attributes. They also rigorously check the correct ordering and destruction of resources based on dependencies.
Plan Functionality Testing[Edit section][Copy link]
References: internal/terraform/context_plan2_test.go
In the context of Terraform's plan functionality, the …/context_plan2_test.go
file includes a suite of tests that validate the system's ability to detect and handle various changes to the infrastructure state. The file contains tests that ensure the correct behavior of Terraform during the planning phase, including the handling of orphaned data instances and the correct application of provider configurations.
Output Value Management[Edit section][Copy link]
References: internal/terraform/evaluate.go
, internal/terraform/node_output.go
, internal/terraform/transform_orphan_output.go
Terraform manages output values through a series of nodes defined in …/node_output.go
, which handle the lifecycle of these values, including their expansion, application, and destruction. The nodeExpandOutput
is responsible for expanding non-root module outputs before their module paths are fully known. Once expanded, NodeApplyableOutput
nodes apply changes to these values, while NodeDestroyableOutput
nodes handle their removal during destroy operations.
Validation Functionality Testing[Edit section][Copy link]
References: internal/terraform/context_validate_test.go
In …/context_validate_test.go
, the suite of tests focuses on the Validate
method within the terraform.Context
struct, which is crucial for ensuring Terraform configurations are correct before execution. The tests scrutinize a variety of validation scenarios, including the behavior of custom validation rules for root module variables when they are used in a child module context.
Command Line Interface[Edit section][Copy link]
References: internal/command
The Command Line Interface (CLI) implementation is primarily handled in the …/command
directory. Key components include:
Test Case Management[Edit section][Copy link]
References: internal/command
Test case management for the Terraform CLI is centralized within the …/command
directory, which contains a structured approach to validating command behaviors. Test cases are organized into subdirectories and files that correspond to specific commands and functionalities, ensuring that each aspect of the CLI is thoroughly tested. For example, the apply_test.go
file focuses on testing the ApplyCommand
struct, which includes scenarios such as handling locked state files, verifying parallelism, and testing input variable handling.
Output Command Functionality[Edit section][Copy link]
References: internal/command/output.go
, internal/command/jsonformat/state.go
, internal/command/views/output.go
The OutputCommand
struct in …/output.go
is responsible for handling the output
command in Terraform's CLI. This command is used to read and print output values from a Terraform state. The OutputCommand
has several key methods:
State Output Handling[Edit section][Copy link]
References: internal/command/jsonstate/state.go
Within the command line interface of Terraform, the handling of state outputs is managed through a series of marshaling functions located in …/state.go
. These functions are responsible for converting the internal state representation into a JSON format suitable for user consumption and further processing. The marshaling process pays particular attention to the treatment of sensitive and unknown values to ensure that sensitive information is not inadvertently exposed.
Refresh Command Enhancements[Edit section][Copy link]
References: internal/command/arguments/refresh.go
In the file …/refresh.go
, the refresh
command has a Refresh
struct that encapsulates the command-line arguments for the refresh
command. This struct includes essential fields such as pointers to State
, Operation
, and Vars
structs, as well as flags for InputEnabled
and determining the ViewType
.
Address and Dependency Management[Edit section][Copy link]
References: internal/addrs
, internal/dag
The addrs
package in …/addrs
provides types and functionality for managing resource addressing and dependencies in Terraform. Key components include:
Resource Address Parsing[Edit section][Copy link]
References: internal/addrs
In the …/addrs
directory, Terraform's codebase handles the parsing of resource addresses through a variety of structs and functions. The Resource
, ResourceInstance
, AbsResource
, and AbsResourceInstance
types are central to representing different levels of resource addressing. These types are equipped with methods for creating, manipulating, and comparing resource addresses.
Resource Mode Representation[Edit section][Copy link]
References: internal/addrs/resource.go
, internal/addrs/resourcemode_string.go
Within Terraform's internal structures, resource modes are represented by the ResourceMode
type, which is crucial for distinguishing between different kinds of resources such as managed, data, and ephemeral resources. The ResourceMode
type, defined in …/resource.go
, plays a pivotal role in how Terraform interprets and addresses resources within configurations.
Error Handling in Address Parsing[Edit section][Copy link]
References: internal/addrs/parse_ref.go
In …/parse_ref.go
, the Terraform codebase includes robust error handling mechanisms to ensure that resource addresses are parsed accurately and that any issues are reported clearly to the user. The file is integral to interpreting Terraform language references and ensuring that they conform to expected formats. Here's how the error handling is structured:
Testing Address Parsing[Edit section][Copy link]
References: internal/addrs/parse_ref_test.go
, internal/addrs/parse_target_test.go
In …/parse_ref_test.go
, the TestParseRef
and TestParseRefInTestingScope
functions are responsible for validating the parsing of resource addresses. These functions execute a series of test cases against the ParseRef
function, which translates string representations of Terraform resource references into structured Reference
objects. The tests are designed to ensure accurate parsing across a variety of reference types, including standard resources, modules, locals, and notably, ephemeral resources.
RPC and API[Edit section][Copy link]
References: internal/rpcapi
The RPC API in Terraform is implemented using gRPC and the go-plugin
library. The main entry point is the ServePlugin
function in …/server.go
, which starts the plugin server and handles the go-plugin protocol handshake.
Expression Evaluation and Dynamic Values[Edit section][Copy link]
References: internal/rpcapi/stacks_inspector.go
In …/stacks_inspector.go
, the stacksInspector
struct provides the means to evaluate expressions within a Terraform stack's context. The InspectExpressionResult
method is a key feature of this struct, enabling the evaluation of expressions and returning the results as dynamic values suitable for RPC communication.
Dynamic Value Construction and Conversion[Edit section][Copy link]
References: internal/rpcapi/terraform1/stacks/conversion.go
In …/conversion.go
, the ToDynamicValue()
function is central to transforming cty.Value
instances into DynamicValue
messages suitable for gRPC communication. This process includes the careful preservation of sensitive paths to ensure that sensitive information is adequately protected during serialization.
Stack Change Tracking and Enums[Edit section][Copy link]
References: internal/rpcapi/terraform1/stacks/stacks.pb.go
In …/stacks.pb.go
, the protocol buffer definitions play a crucial role in managing the lifecycle of stack changes within Terraform's architecture. The file includes a series of enums that map out the various states and types of changes that can occur within a stack, which are essential for tracking progress and managing the behavior of resources during operations like planning and applying changes.
Built-in Functionality[Edit section][Copy link]
References: internal/builtin
Terraform includes several built-in providers and provisioners to enhance its core functionality:
Read moreEphemeral Resource Type Handling[Edit section][Copy link]
References: internal/builtin/providers/terraform/provider.go
In …/provider.go
, the Provider
struct is responsible for implementing the providers.Interface
, which encompasses a variety of methods necessary for a Terraform provider's functionality. Among these methods, operations related to ephemeral resource types are included, specifically through ValidateEphemeralResourceConfig()
, OpenEphemeralResource()
, RenewEphemeralResource()
, and CloseEphemeralResource()
. These functions handle the validation and management of ephemeral resources, which are resources that are created and destroyed during the execution of a Terraform configuration.