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