Skip to main content

Components

Components are individual pieces of infrastructure within a stack. Each component maps to a Terraform module and its configuration.

What is a Component?

A component represents a single infrastructure resource or logical group of resources, such as:

  • A VPC network
  • A Kubernetes cluster
  • A database instance
  • A storage bucket
  • A load balancer

Defining Components

Use the component() function to define a component:

const componentName = component('name', 'module-path', {
// input variables
})

Parameters:

  • name - Unique identifier for the component within the stack
  • module-path - Path to the Terraform module (relative or absolute)
  • inputs - Object containing variable values for the module

Basic Example

stacks/dev.stack.js
const vpc = component('vpc', 'modules/vpc', {
cidr_block: '10.0.0.0/16',
region: 'us-central1',
enable_flow_logs: true
})

This creates a component named vpc that uses the module at modules/vpc/ with the specified input variables.

Component Dependencies

Components can reference each other within the same stack:

const vpc = component('vpc', 'modules/vpc', {
cidr_block: '10.0.0.0/16'
})

const subnet = component('subnet', 'modules/subnet', {
vpc_id: vpc.id, // Reference the VPC's output
cidr_block: '10.0.1.0/24'
})

const gke = component('gke', 'modules/gke', {
network: vpc.id,
subnetwork: subnet.id,
cluster_name: 'my-cluster'
})

When you reference vpc.id, Comet automatically creates a dependency, ensuring the VPC is created before the subnet and GKE cluster.

Using Templates in Components

Template variables and functions can be used in component inputs:

const database = component('db', 'modules/cloudsql', {
name: 'db-{{ .stack }}', // Becomes 'db-dev', 'db-prod', etc.
region: '{{ .settings.region }}',
tier: '{{ .settings.db_tier }}',

// Use conditional logic with templates
deletion_protection: '{{ if eq .stack "production" }}true{{ else }}false{{ end }}'
})

Component Operations

Plan Changes

Preview what changes will be made:

comet plan <stack> <component>

Example:

comet plan dev vpc

Apply Changes

Create or update infrastructure:

comet apply <stack> <component>

Example:

comet apply dev vpc

View Outputs

Display component outputs:

comet output <stack> <component>

Example:

comet output dev vpc

Destroy Infrastructure

Remove infrastructure:

comet destroy <stack> <component>

Example:

comet destroy dev vpc

Working with All Components

You can operate on all components in a stack by omitting the component name:

# Plan all components
comet plan dev

# Apply all components
comet apply dev

# Destroy all components
comet destroy dev

Component Naming Best Practices

DO: Use descriptive, unique names

component('vpc-main', 'modules/vpc', ...)
component('gke-primary-cluster', 'modules/gke', ...)
component('cloudsql-users-db', 'modules/database', ...)

DON'T: Use generic or cryptic names

component('v1', 'modules/vpc', ...)      // ❌ Too generic
component('k', 'modules/gke', ...) // ❌ Unclear
component('thing', 'modules/database', ...) // ❌ Not descriptive

Module Structure

Components use standard Terraform modules. A basic module structure:

modules/vpc/
├── main.tf # Main resource definitions
├── variables.tf # Input variables
└── outputs.tf # Output values

Example modules/vpc/variables.tf:

variable "cidr_block" {
type = string
description = "CIDR block for the VPC"
}

variable "region" {
type = string
description = "Region for the VPC"
}

Example modules/vpc/outputs.tf:

output "id" {
value = google_compute_network.vpc.id
description = "VPC ID"
}

output "self_link" {
value = google_compute_network.vpc.self_link
description = "VPC self link"
}

These outputs become available for other components to reference via vpc.id or vpc.self_link.