A Terraform provider for Dokploy

Plugin-framework provider covering projects, environments, applications,
Compose stacks, managed databases, domains, mounts, ports, redirects,
basic auth, registries, SSH keys, certificates and backup destinations,
over Dokploy's tRPC-over-REST API.

The shim package exposes the provider to other Go modules, which is how
pulumi-dokploy bridges it.
This commit is contained in:
2026-08-09 12:17:26 +03:00
commit a6d8aa8b52
160 changed files with 24260 additions and 0 deletions

View File

@@ -0,0 +1,543 @@
# API Monitoring Reference
Complete guide for monitoring Terraform Stack deployments using the HCP Terraform API. Use this approach for automation, CI/CD pipelines, and non-interactive environments like AI agents.
## Table of Contents
1. [When to Use the API](#when-to-use-the-api)
2. [Authentication](#authentication)
3. [API Monitoring Workflow](#api-monitoring-workflow)
4. [Detailed Endpoint Reference](#detailed-endpoint-reference)
5. [Notes for AI Agents and Automation](#notes-for-ai-agents-and-automation)
## When to Use the API
Use the HCP Terraform API instead of CLI commands when:
- Running in non-interactive environments (CI/CD, automation scripts)
- Building tools or integrations that need programmatic access
- Monitoring multiple Stacks simultaneously
- Implementing custom retry logic or error handling
- Working in environments where streaming CLI commands don't work
**CLI commands that don't work in automation:**
- `terraform stacks deployment-run watch` - Streams output, blocks indefinitely
- `terraform stacks deployment-group watch` - Streams output, blocks indefinitely
- `terraform stacks configuration watch` - Streams output, blocks indefinitely
## Authentication
### Extract API Token from Credentials File
```bash
TOKEN=$(jq -r '.credentials["app.terraform.io"].token' ~/.terraform.d/credentials.tfrc.json)
```
### Alternative: Use Environment Variable
```bash
export TFC_TOKEN="your-token-here"
TOKEN=$TFC_TOKEN
```
### API Request Headers
All API requests require these headers:
```bash
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/vnd.api+json"
```
## API Monitoring Workflow
After uploading a configuration with `terraform stacks configuration upload`, follow this sequence to monitor deployment progress:
### Step 1: Get Configuration Status
**Endpoint:** `GET /api/v2/stack-configurations/{configuration-id}`
**Purpose:** Verify configuration upload completed successfully and get the configuration details.
**Request:**
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/stack-configurations/{configuration-id}" | jq '.'
```
**Response Fields:**
- `attributes.status` - Configuration processing status (pending/completed)
- `attributes.sequence-number` - Version number of this configuration
- `attributes.components-detected` - Number of components found
- `attributes.deployments-detected` - Number of deployments found
**Example Response:**
```json
{
"data": {
"id": "stc-ABC123",
"type": "stack-configurations",
"attributes": {
"status": "completed",
"sequence-number": 5,
"components-detected": 3,
"deployments-detected": 2,
"created-at": "2024-01-15T10:30:00.000Z",
"updated-at": "2024-01-15T10:30:45.000Z"
}
}
}
```
### Step 2: Get Deployment Group Summaries
**Endpoint:** `GET /api/v2/stack-configurations/{configuration-id}/stack-deployment-group-summaries`
**Purpose:** Get list of deployment groups, their IDs, and current status summary.
**Request:**
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/stack-configurations/{configuration-id}/stack-deployment-group-summaries" | jq '.'
```
**Response Fields:**
- `id` - Deployment group ID (needed for next step)
- `attributes.name` - Deployment group name (e.g., `dev_default`)
- `attributes.status` - Overall status (running/succeeded/failed)
- `attributes.status-counts` - Breakdown of deployment statuses
**Example Response:**
```json
{
"data": [
{
"id": "sdg-XYZ789",
"type": "stack-deployment-group-summaries",
"attributes": {
"name": "dev_default",
"status": "running",
"status-counts": {
"pending": 0,
"running": 1,
"succeeded": 1,
"failed": 0
}
}
}
]
}
```
### Step 3: Get Deployment Runs
**Endpoint:** `GET /api/v2/stack-deployment-groups/{group-id}/stack-deployment-runs`
**Purpose:** Get list of deployment runs for a specific group with their current status.
**Request:**
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/stack-deployment-groups/{group-id}/stack-deployment-runs" | jq '.'
```
**Response Fields:**
- `id` - Deployment run ID (needed for next step)
- `attributes.status` - Current status (planning/planned/applying/applied/failed)
- `attributes.created-at` - Run start time
- `attributes.updated-at` - Last update time
**Example Response:**
```json
{
"data": [
{
"id": "sdr-123ABC",
"type": "stack-deployment-runs",
"attributes": {
"status": "planning",
"created-at": "2024-01-15T10:31:00.000Z",
"updated-at": "2024-01-15T10:31:15.000Z"
}
}
]
}
```
### Step 4: Get Deployment Steps
**Endpoint:** `GET /api/v2/stack-deployment-runs/{run-id}/stack-deployment-steps`
**Purpose:** Get detailed information about individual plan and apply steps.
**Request:**
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/stack-deployment-runs/{run-id}/stack-deployment-steps" | jq '.'
```
**Response Fields:**
- `id` - Step ID (needed for diagnostics and outputs)
- `attributes.operation-type` - Type of operation (plan/apply)
- `attributes.status` - Step status (running/completed/failed)
- `attributes.component-name` - Which component is being processed
**Example Response:**
```json
{
"data": [
{
"id": "sds-PlanStep123",
"type": "stack-deployment-steps",
"attributes": {
"operation-type": "plan",
"status": "completed",
"component-name": "vpc",
"created-at": "2024-01-15T10:31:05.000Z",
"completed-at": "2024-01-15T10:31:30.000Z"
}
},
{
"id": "sds-ApplyStep456",
"type": "stack-deployment-steps",
"attributes": {
"operation-type": "apply",
"status": "running",
"component-name": "vpc",
"created-at": "2024-01-15T10:32:00.000Z"
}
}
]
}
```
### Step 5: Get Error Diagnostics (When Deployment Fails)
**Endpoint:** `GET /api/v2/stack-deployment-steps/{step-id}/stack-diagnostics`
**Purpose:** Retrieve detailed error messages when a deployment step fails.
**Critical:** The `stack_deployment_step_id` query parameter is **required**. Without it, the API returns empty results.
**Request:**
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/stack-deployment-steps/{step-id}/stack-diagnostics?stack_deployment_step_id={step-id}" | jq '.'
```
**Response Fields:**
- `attributes.severity` - Diagnostic level (error/warning)
- `attributes.summary` - Brief error description
- `attributes.detail` - Detailed error message
- `attributes.diags` - Array of diagnostic objects with file locations and code snippets
**Example Response (Error with Details):**
```json
{
"data": [
{
"id": "stf-ErrorExampleId",
"type": "stack-diagnostics",
"attributes": {
"severity": "error",
"summary": "Diagnostics reported",
"detail": "2 errors",
"diags": [
{
"summary": "Unsupported attribute",
"detail": "This object does not have an attribute named \"target_id\".",
"range": {
"filename": "main.tf",
"start": {
"line": 634,
"column": 33
},
"end": {
"line": 634,
"column": 43
},
"source": "registry.terraform.io/terraform-aws-modules/alb/aws@9.17.0//main.tf"
},
"snippet": {
"code": " target_id = each.value.target_id",
"context": "resource \"aws_lb_target_group_attachment\" \"this\""
}
},
{
"summary": "Invalid reference",
"detail": "A reference to a resource type must be followed by at least one attribute access.",
"range": {
"filename": "main.tf",
"start": {
"line": 142,
"column": 15
},
"end": {
"line": 142,
"column": 28
},
"source": "local-module//main.tf"
},
"snippet": {
"code": " vpc_id = aws_vpc.main",
"context": "resource \"aws_subnet\" \"private\""
}
}
],
"acknowledged": false,
"created-at": "2024-01-15T10:32:15.000Z"
}
}
]
}
```
**Parsing Diagnostics:**
Extract error information with jq:
```bash
# Get error summaries
curl -s -H "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/stack-deployment-steps/{step-id}/stack-diagnostics?stack_deployment_step_id={step-id}" | \
jq -r '.data[].attributes.diags[]? | "\(.summary): \(.detail)"'
# Get file locations
curl -s -H "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/stack-deployment-steps/{step-id}/stack-diagnostics?stack_deployment_step_id={step-id}" | \
jq -r '.data[].attributes.diags[]? | "\(.range.filename):\(.range.start.line)"'
```
### Step 6: Get Stack Outputs (After Successful Deployment)
**Endpoint:** `GET /api/v2/stack-deployment-steps/{final-apply-step-id}/artifacts?name=apply-description`
**Purpose:** Retrieve Stack outputs after a successful deployment completes.
**Important Notes:**
- This endpoint returns HTTP 307 redirect - use `curl -L` to follow redirects automatically
- This is currently the **only way** to retrieve Stack outputs programmatically
- This endpoint is **not documented** in public API documentation
- You need the final apply step ID from Step 4
**Request:**
```bash
curl -L -s -H "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/stack-deployment-steps/{final-apply-step-id}/artifacts?name=apply-description"
```
**Response Structure:**
The artifact response includes an `.outputs` object where each output contains a `change.after` property with the actual output value:
```json
{
"outputs": {
"alb_url": {
"change": {
"actions": ["no-op"],
"before": "http://my-alb-123456789.us-west-2.elb.amazonaws.com",
"after": "http://my-alb-123456789.us-west-2.elb.amazonaws.com",
"after_unknown": false,
"before_sensitive": false,
"after_sensitive": false
},
"type": "string"
},
"ecr_repository_url": {
"change": {
"actions": ["no-op"],
"before": "123456789.dkr.ecr.us-west-2.amazonaws.com/my-repo",
"after": "123456789.dkr.ecr.us-west-2.amazonaws.com/my-repo",
"after_unknown": false,
"before_sensitive": false,
"after_sensitive": false
},
"type": "string"
}
}
}
```
**Extract Only Output Values:**
```bash
curl -L -s --header "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/stack-deployment-steps/{final-apply-step-id}/artifacts?name=apply-description" | \
jq -r '.outputs | to_entries | .[] | "\(.key): \(.value.change.after)"'
```
**Example Output:**
```
alb_url: http://my-alb-123456789.us-west-2.elb.amazonaws.com
ecr_repository_url: 123456789.dkr.ecr.us-west-2.amazonaws.com/my-repo
```
## Detailed Endpoint Reference
### Available Artifact Types
The artifacts endpoint accepts these `name` parameter values:
- `plan-description` - Terraform plan output in JSON format
- `plan-debug-log` - Detailed debug logs from plan operation
- `apply-description` - Terraform apply output including outputs (JSON format)
- `apply-debug-log` - Detailed debug logs from apply operation
### Polling Best Practices
**Recommended polling intervals:**
- Configuration status: Check every 5 seconds until status is "completed"
- Deployment runs: Check every 10 seconds during active deployment
- Deployment steps: Check every 10 seconds for individual step status
**Implement exponential backoff:**
```bash
# Example polling script with backoff
RETRY_COUNT=0
MAX_RETRIES=30
BACKOFF=5
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
STATUS=$(curl -s -H "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/stack-deployment-runs/{run-id}" | \
jq -r '.data.attributes.status')
if [ "$STATUS" = "applied" ] || [ "$STATUS" = "failed" ]; then
echo "Deployment finished with status: $STATUS"
break
fi
echo "Current status: $STATUS. Waiting ${BACKOFF}s..."
sleep $BACKOFF
RETRY_COUNT=$((RETRY_COUNT + 1))
done
```
## Notes for AI Agents and Automation
### CLI Command Limitations
**These CLI commands DO NOT work in automation:**
- `terraform stacks deployment-run watch` - Streams output, blocks indefinitely
- `terraform stacks deployment-group watch` - Streams output, blocks indefinitely
- `terraform stacks configuration watch` - Streams output, blocks indefinitely
**Solution:** Use API polling instead of watch commands.
### No Direct Output Command
There is currently no CLI command to retrieve Stack outputs. You must:
1. Use API to get deployment steps
2. Find the final apply step ID
3. Request the `apply-description` artifact
4. Parse JSON to extract outputs
### Handling Redirects
The artifacts endpoint returns HTTP 307 redirect to the actual artifact location. Ensure your HTTP client follows redirects:
**curl:** Use `-L` flag
**Python requests:** Set `allow_redirects=True` (default)
**Node.js fetch:** Set `redirect: 'follow'` (default)
### Error Handling
**Common API errors:**
- **401 Unauthorized:** Invalid or expired token - refresh credentials
- **404 Not Found:** Invalid ID or resource doesn't exist yet - retry with backoff
- **429 Too Many Requests:** Rate limited - implement exponential backoff
- **Empty diagnostics:** Missing required `stack_deployment_step_id` query parameter
### Complete Monitoring Script Example
```bash
#!/bin/bash
# Configuration
TOKEN=$(jq -r '.credentials["app.terraform.io"].token' ~/.terraform.d/credentials.tfrc.json)
CONFIG_ID="stc-ABC123"
BASE_URL="https://app.terraform.io/api/v2"
# Helper function
api_get() {
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"$1"
}
# 1. Wait for configuration to complete
echo "Checking configuration status..."
while true; do
STATUS=$(api_get "$BASE_URL/stack-configurations/$CONFIG_ID" | jq -r '.data.attributes.status')
[ "$STATUS" = "completed" ] && break
echo "Configuration status: $STATUS. Waiting..."
sleep 5
done
# 2. Get deployment groups
echo "Getting deployment groups..."
GROUP_ID=$(api_get "$BASE_URL/stack-configurations/$CONFIG_ID/stack-deployment-group-summaries" | \
jq -r '.data[0].id')
# 3. Get deployment run
echo "Getting deployment run..."
RUN_ID=$(api_get "$BASE_URL/stack-deployment-groups/$GROUP_ID/stack-deployment-runs" | \
jq -r '.data[0].id')
# 4. Monitor deployment run
echo "Monitoring deployment run: $RUN_ID"
while true; do
STATUS=$(api_get "$BASE_URL/stack-deployment-runs/$RUN_ID" | jq -r '.data.attributes.status')
echo "Deployment status: $STATUS"
if [ "$STATUS" = "applied" ]; then
echo "Deployment succeeded!"
# 5. Get outputs from final apply step
APPLY_STEP=$(api_get "$BASE_URL/stack-deployment-runs/$RUN_ID/stack-deployment-steps" | \
jq -r '.data[] | select(.attributes["operation-type"] == "apply") | .id' | tail -1)
echo "Retrieving outputs from step: $APPLY_STEP"
curl -L -s -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/stack-deployment-steps/$APPLY_STEP/artifacts?name=apply-description" | \
jq -r '.outputs | to_entries | .[] | "\(.key): \(.value.change.after)"'
break
fi
if [ "$STATUS" = "failed" ]; then
echo "Deployment failed!"
# Get error diagnostics
FAILED_STEP=$(api_get "$BASE_URL/stack-deployment-runs/$RUN_ID/stack-deployment-steps" | \
jq -r '.data[] | select(.attributes.status == "failed") | .id' | head -1)
echo "Error diagnostics from step: $FAILED_STEP"
api_get "$BASE_URL/stack-deployment-steps/$FAILED_STEP/stack-diagnostics?stack_deployment_step_id=$FAILED_STEP" | \
jq -r '.data[].attributes.diags[]? | "\(.summary): \(.detail)"'
exit 1
fi
sleep 10
done
```
This script demonstrates a complete monitoring workflow from configuration upload to output retrieval with error handling.