Skip to main content

HCP Workspaces

Workspace ใน HCP ≠ CLI workspace! — แต่ละ HCP workspace = state + variables + runs + history แยกกัน

HCP Workspace vs CLI Workspace

⚠️ ต่างกัน!

AspectCLI WorkspaceHCP Workspace
What is itMultiple state files in 1 directoryFull project (state + vars + runs)
ScopePer terraform codePer organization
Use caseMulti-env (dev/staging/prod) for SAME codeEach project + env combo
VariablesShared .tf filesWorkspace-specific vars
Runs historyLocalCentralized in HCP UI

→ ใน HCP ห้ามใช้ CLI workspace — แต่ละ HCP workspace = 1 directory + 1 set of variables

Workspace Types

CLI-Driven

รัน Terraform จาก laptop:

terraform {
cloud {
organization = "my-org"
workspaces {
name = "prod-network"
}
}
}
terraform login
terraform init
terraform apply # runs in HCP, output streams to laptop

VCS-Driven

Connect to Git repo, auto plan/apply on push:

Workspace → Settings → Version Control
└── Repository: myorg/infra
Branch: main
Working directory: ./prod/network
Trigger patterns: prod/network/**

→ Push to main → auto plan + apply (or manual approve)

API-Driven

Programmatic create runs:

curl -X POST https://app.terraform.io/api/v2/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "runs",
"attributes": {"is-destroy": false},
"relationships": {
"workspace": {"data": {"type": "workspaces", "id": "ws-xxx"}}
}
}
}'

Create Workspace

UI

HCP → Organization → New Workspace
└── Choose: CLI-Driven / VCS-Driven / API-Driven
Name: prod-network
Project: production
Tags: [prod, network]

Terraform (Self-Manage HCP with TF!)

provider "tfe" {
organization = "my-org"
}

resource "tfe_workspace" "prod_network" {
name = "prod-network"
organization = "my-org"
working_directory = "prod/network"

vcs_repo {
identifier = "myorg/infra"
branch = "main"
oauth_token_id = data.tfe_oauth_client.github.oauth_token_id
}

trigger_patterns = ["prod/network/**"]

tag_names = ["prod", "network"]
}

Workspace Variables

Terraform Variables

Workspace → Variables → Add
└── Key: region
Value: us-east-1
Category: Terraform variable
Sensitive: false

ใน code:

variable "region" { type = string }

provider "aws" {
region = var.region
}

Environment Variables

Key: AWS_ACCESS_KEY_ID
Value: AKIA...
Category: Environment variable
Sensitive: true

→ Set as env in run, accessible via provider

Variable Sets (Reusable)

Settings → Variable Sets → Create
└── Name: aws-credentials
Variables:
AWS_ACCESS_KEY_ID (env, sensitive)
AWS_SECRET_ACCESS_KEY (env, sensitive)
Apply to: All workspaces / Specific workspaces / By tag

→ Define once, apply to many workspaces

Variable Priority

(highest precedence wins)

  1. Workspace variables
  2. Variable sets (more specific tags first)
  3. Variable sets (less specific)
  4. Variable defaults in .tf

Workspace Settings

General

  • Name (immutable after create)
  • Description
  • Working directory (subdirectory in repo)
  • Auto Apply (after plan: yes/no/require approval)
  • Terraform version (specific version per workspace)
  • Execution mode (remote / agent / local)

Notifications

Workspace → Settings → Notifications
└── Slack webhook
Triggers: applying, completed, errored, needs_attention

Run Triggers

Trigger this workspace when another workspace applies:

Workspace: prod-app
Run Trigger: Source = prod-network

→ When prod-network applies, prod-app queues a run

Project (Group Workspaces)

Organization → Projects → New Project
└── Name: production
Workspaces:
- prod-network
- prod-data
- prod-compute

→ Group + permission management

resource "tfe_project" "production" {
organization = "my-org"
name = "production"
}

resource "tfe_workspace" "prod_network" {
name = "prod-network"
project_id = tfe_project.production.id
}

Tags

Workspace → Settings → Tags
└── Tags: [prod, network, critical]

ใช้:

  • Filter ใน UI
  • Variable set targeting
  • Bulk operations

Multi-Workspace ใน 1 Repo

infra/
├── prod/
│ ├── network/ # workspace: prod-network
│ ├── data/ # workspace: prod-data
│ └── compute/ # workspace: prod-compute
└── staging/
├── network/ # workspace: staging-network
└── ...

แต่ละ folder = workspace ตัวเอง

Workspace State

Read State

# In workspace B, read state from workspace A
data "tfe_outputs" "network" {
organization = "my-org"
workspace = "prod-network"
}

resource "aws_instance" "app" {
subnet_id = data.tfe_outputs.network.values.subnet_id
}

→ Cross-workspace state references (alternative to terraform_remote_state)

State Sharing

Workspace prod-network → Settings → State Sharing
└── Share with: prod-app, prod-monitoring

→ Other workspaces can read your outputs

Workspace Locking

Auto-lock during runs (prevent concurrent apply)

Manual lock:

Workspace → Lock
└── Reason: "Migration in progress"

→ No new runs until unlocked

Run History

ทุก plan/apply เก็บ:

  • Plan output
  • Apply output
  • Triggered by (user/VCS)
  • Duration
  • Resources changed
  • Cost estimation

→ Audit trail สมบูรณ์

Auto-Apply

Workspace → Settings → Auto Apply
└── ☑ Auto-apply successful plans

⚠️ ใช้เฉพาะ dev — prod ควร manual approve

Manual Apply (Approval)

Plan complete!
Plan: 5 to add, 0 to change, 0 to destroy.

[Click "Confirm & Apply"]

ผู้ที่มี Apply permission กดปุ่ม

Workspace Deletion

Settings → Destruction & Deletion

2 actions:

  • Queue destroy plan — destroy resources first
  • Delete workspace — delete metadata (resources still in cloud!)

Best practice:

  1. Queue destroy plan → apply → confirm 0 resources
  2. Delete workspace

Best Practices

✅ DO:
- 1 workspace = 1 logical scope (env + layer)
- Naming convention: <env>-<layer> (prod-network, staging-data)
- Use projects + tags
- Variable sets for shared credentials
- VCS-driven for production
- Auto-apply for dev only

❌ DON'T:
- ห้าม mix CLI workspace กับ HCP workspace
- ห้าม share workspace สำหรับ env ต่าง
- ห้าม delete workspace ก่อน destroy resources
- ห้ามใช้ auto-apply ใน prod

ตัวอย่าง: Mature Setup

Organization: my-company
├── Projects:
│ ├── shared
│ │ ├── workspace: shared-dns
│ │ └── workspace: shared-iam
│ ├── production
│ │ ├── workspace: prod-network
│ │ ├── workspace: prod-data
│ │ ├── workspace: prod-compute
│ │ └── workspace: prod-apps
│ ├── staging
│ │ └── workspace: staging-*
│ └── development
│ └── workspace: dev-*
├── Variable Sets:
│ ├── aws-credentials → all workspaces (sensitive env vars)
│ ├── prod-config → tag:prod (production-specific)
│ └── shared-tags → all (default tags)
└── Teams:
├── platform-eng → admin all workspaces
├── dev-team → write dev/staging workspaces
└── viewers → read all

สรุป

  • HCP Workspace = state + vars + runs + history (ต่างจาก CLI workspace)
  • 3 modes: CLI-driven, VCS-driven, API-driven
  • Variables + Variable Sets สำหรับ config
  • Projects + Tags จัดกลุ่ม
  • Run Triggers สำหรับ chain workspaces
  • VCS-driven for prod, auto-apply for dev

ต่อไป → VCS Integration