Explorador de Recursos Terraform

Lista todos los recursos, data sources, variables, outputs y locals en tu código Terraform HCL

Terraform Resource Discovery and Dependency Visualization

Terraform resource exploration is the practice of analyzing Infrastructure-as-Code (IaC) configurations to discover all declared resources, map the dependency graph between them, visualize module structures, and understand the overall architecture of a Terraform project. A Terraform codebase of any significant size quickly grows beyond what a developer can hold in memory — dozens of resources spanning compute instances, networking components, storage buckets, IAM policies, and database clusters, all connected through implicit and explicit dependencies. Resource exploration tools parse these configurations and produce a structured view of what exists, how resources reference each other via depends_on blocks, interpolated attributes, data sources, and module outputs, and where the architectural boundaries lie between logical infrastructure layers.

Understanding resource composition and dependency flow is essential for safe infrastructure changes. Before modifying a security group, an engineer needs to know which instances, load balancers, or RDS databases reference it. Before refactoring a module, the team needs visibility into which outputs are consumed by other modules and root configurations. Resource exploration answers the fundamental questions that precede any infrastructure change: what do we have, how is it connected, and what will be affected if we change this resource? By building a dependency graph from static analysis of .tf files, teams gain architectural visibility without running terraform plan against live infrastructure — enabling faster code reviews, safer refactoring, and more confident change management across complex multi-module Terraform projects.

Resource Discovery and Inventory

The first capability of resource exploration is comprehensive inventory — discovering every resource, data source, variable, output, and local value declared across all .tf files in a project. This goes beyond a simple file listing to provide structured metadata:

  • Resource enumeration: Identifies every resource block with its type (e.g., aws_instance, google_compute_network, azurerm_resource_group), logical name, and source file location. For large projects with hundreds of resources spread across multiple directories, this inventory provides the definitive answer to "what infrastructure does this codebase define?"
  • Data source discovery: Catalogs all data blocks that query existing infrastructure — data.aws_ami, data.aws_vpc, data.terraform_remote_state — revealing external dependencies that are not managed by this Terraform project but are consumed by its resources.
  • Module inventory: Lists all module blocks with their source (local path, Terraform Registry, Git URL), version constraints, and the variables passed into each module invocation. This reveals the compositional structure — which reusable building blocks the project assembles into its final architecture.
  • Variable and output mapping: Tracks all variable declarations (the project's external interface), output declarations (the values exposed to consumers), and locals blocks (internal computed values). Together these define the data flow boundaries of the configuration.
  • Provider analysis: Identifies which providers the project requires (aws, google, azurerm, kubernetes), their version constraints, and any provider aliases for multi-region or multi-account deployments. This reveals the cloud platforms and services the infrastructure targets.

Dependency Graph and Reference Tracking

Terraform resources rarely exist in isolation — they form a directed acyclic graph (DAG) of dependencies where one resource's attributes flow into another's configuration. Resource exploration builds this dependency graph through static analysis of attribute references:

  • Implicit dependencies via attribute references: When a resource references another's attribute (e.g., subnet_id = aws_subnet.private.id), Terraform creates an implicit dependency. The explorer traces these references across all resources to build the complete dependency DAG without requiring depends_on annotations.
  • Explicit dependencies via depends_on: Some dependencies cannot be inferred from attribute references — for example, an IAM policy that must exist before an instance can assume a role. The explorer identifies all depends_on blocks and incorporates them into the graph as explicit edges.
  • Cross-module references: Module outputs consumed by other modules or root configurations create inter-module dependency edges. The explorer traces module.network.vpc_id references back to the originating module's output block, revealing how modules compose into the larger architecture.
  • Data source dependencies: Resources that depend on data sources inherit dependencies on external infrastructure. The explorer distinguishes between internally-managed dependencies (resource-to-resource) and external dependencies (resource-to-data-source) to clarify the project's boundary with pre-existing infrastructure.
  • Dependency depth and critical path: By analyzing the longest chain of sequential dependencies, the explorer identifies the critical path through the DAG — the sequence of resources that determines the minimum time for terraform apply to complete. Resources on parallel branches can be provisioned concurrently; resources on the critical path are sequential bottlenecks.

This dependency graph directly answers impact analysis questions: "if I modify aws_vpc.main, which downstream resources will be affected?" The explorer traces all transitive dependents — subnets, route tables, security groups, instances, load balancers — providing the full blast radius of any proposed change.

Module Structure and Composition Analysis

Terraform modules are the primary mechanism for organizing and reusing infrastructure code. Resource exploration analyzes module structure to reveal how a project composes its architecture from reusable building blocks:

  • Module hierarchy visualization: Displays the tree of module calls — root configuration calling child modules, which may in turn call nested sub-modules. This reveals the layered architecture: a root module might call module.network, module.compute, and module.database, each encapsulating a logical infrastructure tier.
  • Input/output interface analysis: For each module, the explorer lists its declared variables (inputs), outputs (exposed values), and which of those are actually used by callers. Unused outputs indicate dead code; required variables without defaults indicate mandatory configuration that callers must provide.
  • Module source tracking: Distinguishes between local modules (source = "./modules/network"), registry modules (source = "hashicorp/consul/aws"), and Git-sourced modules (source = "git::https://github.com/org/module.git"). This reveals supply chain dependencies — which external parties provide infrastructure building blocks.
  • Resource count per module: Summarizes how many resources each module manages, enabling teams to identify overly large modules that should be decomposed or trivially small modules that add unnecessary indirection. A well-structured module encapsulates a cohesive set of 5-15 related resources.
  • Cross-module data flow: Traces how values propagate from one module's outputs through another module's variables. For example, a network module outputs vpc_id and private_subnet_ids, which the compute module consumes as inputs. This data flow visualization reveals the contract between modules and highlights coupling points where changes propagate across module boundaries.

Resource Relationship Patterns

Beyond raw dependency edges, resource exploration identifies common architectural patterns that emerge from how resources relate to each other:

  • Parent-child relationships: Resources that form natural hierarchies — a VPC containing subnets, subnets containing instances, instances attached to security groups. The explorer identifies these containment patterns to present resources in logical groupings rather than flat lists.
  • Association resources: Many cloud resources use intermediary "association" or "attachment" resources to link two primary resources. For example, aws_route_table_association connects a subnet to a route table, and aws_iam_role_policy_attachment connects a role to a policy. The explorer recognizes these patterns and displays the logical connection they represent.
  • Count and for_each patterns: Resources using count or for_each meta-arguments create multiple instances from a single block. The explorer identifies these multiplied resources and shows how many instances will be created based on the input variable or local value driving the iteration.
  • Lifecycle and replacement chains: Resources with create_before_destroy lifecycle rules or those that trigger replacement on certain attribute changes form update chains. The explorer identifies resources with lifecycle blocks and flags those where attribute changes force replacement rather than in-place updates — critical knowledge for understanding change impact.
  • Provider-scoped groupings: In multi-cloud or multi-region projects, resources are grouped by their provider alias. The explorer groups resources by provider to show which cloud regions or accounts each set of resources targets, revealing the geographic or organizational distribution of infrastructure.

Code Examples

Multi-Module Terraform Project with Complex Dependencies

# Root configuration — composing modules with dependency flow

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  backend "s3" {
    bucket = "terraform-state-prod"
    key    = "infrastructure/terraform.tfstate"
    region = "us-east-1"
  }
}

provider "aws" {
  region = var.region
}

provider "aws" {
  alias  = "replica"
  region = var.replica_region
}

# ─── Module: Network Layer ───────────────────────────────

module "network" {
  source = "./modules/network"

  environment     = var.environment
  vpc_cidr        = var.vpc_cidr
  azs             = var.availability_zones
  private_subnets = var.private_subnet_cidrs
  public_subnets  = var.public_subnet_cidrs

  tags = local.common_tags
}

# ─── Module: Security Layer (depends on network) ────────

module "security" {
  source = "./modules/security"

  vpc_id             = module.network.vpc_id          # Cross-module reference
  private_subnet_ids = module.network.private_subnet_ids
  allowed_cidrs      = var.office_cidrs

  tags = local.common_tags
}

# ─── Module: Database Layer (depends on network + security) ──

module "database" {
  source = "./modules/database"

  vpc_id              = module.network.vpc_id
  subnet_ids          = module.network.private_subnet_ids
  security_group_id   = module.security.db_security_group_id  # Explicit dependency
  instance_class      = var.db_instance_class
  engine_version      = var.db_engine_version
  multi_az            = var.environment == "production"

  tags = local.common_tags
}

# ─── Module: Compute Layer (depends on all above) ────────

module "compute" {
  source = "./modules/compute"

  vpc_id            = module.network.vpc_id
  subnet_ids        = module.network.private_subnet_ids
  security_group_id = module.security.app_security_group_id
  db_endpoint       = module.database.endpoint           # Data flows from DB module
  db_port           = module.database.port
  instance_type     = var.instance_type
  min_size          = var.asg_min_size
  max_size          = var.asg_max_size

  tags = local.common_tags
}

# ─── Module: CDN / Edge (depends on compute) ────────────

module "cdn" {
  source = "./modules/cdn"

  providers = {
    aws         = aws
    aws.replica = aws.replica    # Multi-region provider alias
  }

  alb_dns_name    = module.compute.alb_dns_name
  domain_name     = var.domain_name
  certificate_arn = module.security.certificate_arn

  tags = local.common_tags
}

# ─── Data Sources (external dependencies) ───────────────

data "aws_caller_identity" "current" {}

data "aws_ami" "app" {
  most_recent = true
  owners      = ["self"]

  filter {
    name   = "name"
    values = ["app-server-*"]
  }
}

data "terraform_remote_state" "shared" {
  backend = "s3"
  config = {
    bucket = "terraform-state-shared"
    key    = "shared-services/terraform.tfstate"
    region = "us-east-1"
  }
}

# ─── Locals (computed values) ───────────────────────────

locals {
  common_tags = {
    Environment = var.environment
    Project     = var.project_name
    ManagedBy   = "terraform"
    Owner       = data.aws_caller_identity.current.account_id
  }

  db_connection_string = "postgresql://${module.database.endpoint}:${module.database.port}/${var.db_name}"
}

# ─── Outputs (exposed to consumers) ────────────────────

output "vpc_id" {
  description = "ID of the provisioned VPC"
  value       = module.network.vpc_id
}

output "alb_endpoint" {
  description = "DNS name of the application load balancer"
  value       = module.compute.alb_dns_name
}

output "cdn_domain" {
  description = "CloudFront distribution domain"
  value       = module.cdn.distribution_domain
}

output "db_endpoint" {
  description = "RDS instance endpoint"
  value       = module.database.endpoint
  sensitive   = true
}

Standards & Specifications

  • Terraform Configuration Language Documentation — Official HashiCorp reference for Terraform language syntax including resources, data sources, modules, variables, outputs, and expressions
  • Terraform Resource Dependencies — Documentation on how Terraform determines resource creation order through implicit and explicit dependency analysis
  • Terraform Module Composition — Official guide on module structure, calling conventions, input variables, output values, and module sources (local, registry, Git)
  • Terraform Graph Command — Built-in Terraform CLI command that generates a visual representation of the resource dependency graph in DOT format