main.go
This is the Terraform CLI — HashiCorp's infrastructure-as-code tool that lets users declaratively define cloud and on-premises infrastructure in HCL configuration files, then plan and apply changes to provision and manage that infrastructure. It includes a core engine for dependency graph construction, diff planning, and state management, plus a gRPC-based plugin system for communicating with providers (AWS, GCP, Azure, etc.) and provisioners.
Key Features
- Plan & Apply Engine
- HCL Configuration Parsing
- State Management
- Provider Plugin System (gRPC v5/v6)
- HCP Terraform / Terraform Enterprise Backend
- CLI Command Framework
- Address System
- JSON Plan/State Rendering
- Configuration Checks
- Provider Source & Installation
Entry Points
Start here when working with this codebase
main.goApplication entry point
Start here to understand how the application initializes
Coding Conventions
Standards and patterns used in this codebase
Use a factory pattern for CLI command registration, where each command is registered via a closure that returns a new command instance with injected dependencies (Meta struct, views, etc.)
"apply": func() (cli.Command, error) { return &command.ApplyCommand{Meta: meta}, nil }Separate interface definitions from implementations using dedicated interface files, with provider/provisioner interfaces defined in their own packages and gRPC implementations wrapped separately
The providers.Interface is defined in internal/providers/, gRPC client in internal/plugin/, and gRPC server wrapper in internal/grpcwrap/Use dedicated address types (in internal/addrs) to represent all referenceable Terraform objects, providing type safety and consistent string representation across the codebase
addrs.Resource, addrs.Module, addrs.Provider types used throughout core, configs, states, and plans packagesSeparate command logic from output rendering using a Views pattern, with distinct human-readable and JSON output implementations behind a common interface
internal/command/views/ contains separate human and JSON view implementations for each command (e.g., ApplyHuman, ApplyJSON)Provide dedicated testing utility files (testing.go) within packages that define interfaces or complex types, offering helper functions for backend validation, state management testing, etc.
internal/backend/testing.go provides TestBackendConfig, TestBackendStates helper functions for validating backend implementationsCentralize version information in a dedicated version package to avoid import cycles, with SemVer string and prerelease metadata managed separately
version/version.go provides Version, Prerelease, and SemVer variables used throughout the codebaseSeparate representation from serialization: core domain types (states, plans, configs) live in their own packages, with JSON serialization handled in dedicated sibling packages (command/json*)
internal/states/ defines state types, internal/command/jsonstate/ handles JSON serialization of stateUse a layered plugin protocol with protobuf definitions (tfplugin5, tfplugin6) separate from Go interface wrappers, supporting multiple protocol versions simultaneously
internal/tfplugin5/ and internal/tfplugin6/ contain proto definitions; internal/plugin/ contains GRPCProvider for v5 and internal/plugin6/ for v6Track check/validation states using a centralized state object with explicit status enums (Unknown, Pass, Fail, Error) initialized from configuration and updated during execution
checks.State manages statuses with StatusUnknown, StatusPass, StatusFail, StatusError and separates init (state_init.go) from reporting (state_report.go)Separate argument/flag parsing into dedicated packages (internal/command/arguments) distinct from command execution logic, with validation handled at parse time
internal/command/arguments/ contains flag definitions and validation separate from command implementations in internal/command/Use signal handling and deferred cleanup in the main entry point, with graceful shutdown support via context cancellation and OS signal interception
main.go sets up signal handlers for SIGINT/SIGTERM and propagates cancellation through contextSupport optional OpenTelemetry tracing via environment-driven configuration, keeping telemetry initialization isolated in its own file
telemetry.go initializes OTLP exporter when environment variables are set, with no impact when disabled