Skip to content

Commit 45db857

Browse files
committed
Updated docs with Stack scenarios
1 parent 1f65255 commit 45db857

3 files changed

Lines changed: 618 additions & 2 deletions

File tree

docs/api/index.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,29 @@ column.
107107
| `client.organization_tags` | `OrganizationTags` | `list`, `delete`, `add_workspaces` | [organization_tags.py](../../examples/organization_tags.py) | [Organization tags](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/organization-tags) |
108108
| `client.comments` | `Comments` | `list`, `read`, `create` | [comment.py](../../examples/comment.py) | [Comments](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/comments) |
109109
| `client.explorer` | `Explorer` | query and saved-view helpers | [explorer.py](../../examples/explorer.py) | [Explorer](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/explorer) |
110-
| `client.stacks` | `Stacks` | `list`, `read`, `create`, `update`, `delete`, `force_delete`, VCS fetch | [stack.py](../../examples/stack.py) | [Stacks](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks) |
111-
| `client.stack_configurations` | `StackConfigurations` | `list`, `read`, `create` | [stack_configuration.py](../../examples/stack_configuration.py) | [Stacks](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks) |
112110
| `client.github_app_installations` | `GitHubAppInstallations` | `list`, `read` | [github_app_installations.py](../../examples/github_app_installations.py) | [GitHub App installations](https://developer.hashicorp.com/terraform/enterprise/api-docs/github-app-installations) |
113111
| `client.organization_token_ttl_policies` | `OrganizationTokenTTLPolicies` | `list`, `update`, `reset_to_defaults` | [org_token_ttl.py](../../examples/org_token_ttl.py) | [Org token TTL settings](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/organizations/settings#api-tokens) |
114112

113+
## Stacks
114+
115+
HCP Terraform Stacks coordinate multi-component, multi-environment Terraform
116+
deployments. See [stacks.md](stacks.md) for full method details and
117+
[stack-deployment.md](../scenarios/stack-deployment.md) for an end-to-end
118+
scenario.
119+
120+
| Client attribute | Resource class | Common methods | Example | Upstream API docs |
121+
|---|---|---|---|---|
122+
| `client.stacks` | `Stacks` | `list`, `read`, `create`, `update`, `delete`, `force_delete` | [stack.py](../../examples/stack.py) | [Stacks](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stacks) |
123+
| `client.stack_configurations` | `StackConfigurations` | `list`, `read`, `create` | [stack_configuration.py](../../examples/stack_configuration.py) | [Stack configurations](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-configurations) |
124+
| `client.stack_configuration_summaries` | `StackConfigurationSummaries` | `list` | [stack_configuration_summary.py](../../examples/stack_configuration_summary.py) | [Stack configurations](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-configurations) |
125+
| `client.stack_deployments` | `StackDeployments` | `list` | [stack_deployment.py](../../examples/stack_deployment.py) | [Stack deployments](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployments) |
126+
| `client.stack_deployment_groups` | `StackDeploymentGroups` | `list`, `read`, `read_by_name`, `approve_all_plans`, `rerun` | [stack_deployment_group.py](../../examples/stack_deployment_group.py) | [Stack deployment groups](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-groups) |
127+
| `client.stack_deployment_group_summaries` | `StackDeploymentGroupSummaries` | `list` | [stack_deployment_group_summary.py](../../examples/stack_deployment_group_summary.py) | [Stack deployment groups](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-groups) |
128+
| `client.stack_deployment_runs` | `StackDeploymentRuns` | `list`, `read`, `approve_all_plans`, `cancel` | [stack_deployment_run.py](../../examples/stack_deployment_run.py) | [Stack deployment runs](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-runs) |
129+
| `client.stack_deployment_steps` | `StackDeploymentSteps` | `list`, `read`, `advance`, `list_diagnostics`, `download_artifact` | [stack_deployment_step.py](../../examples/stack_deployment_step.py) | [Stack deployment steps](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-steps) |
130+
| `client.stack_states` | `StackStates` | `list`, `read`, `download_description` | [stack_state.py](../../examples/stack_state.py) | [Stack states](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-states) |
131+
| `client.stack_diagnostics` | `StackDiagnostics` | `read`, `acknowledge` | [stack_diagnostic.py](../../examples/stack_diagnostic.py) | [Stack diagnostics](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-diagnostics) |
132+
115133
## TFE admin (site-admin only)
116134

117135
These endpoints require TFE site-admin permission and return `404` on

docs/api/stacks.md

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
# Stacks
2+
3+
HCP Terraform Stacks let you manage multiple Terraform components as a single
4+
unit, with coordinated deployments across multiple environments. The pytfe SDK
5+
covers the full lifecycle: creating stacks, preparing configurations,
6+
orchestrating deployment groups and runs, inspecting deployment steps, reading
7+
stack states, and handling diagnostics.
8+
9+
Upstream docs:
10+
11+
- Stacks: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stacks
12+
- Stack configurations: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-configurations
13+
- Stack deployments: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployments
14+
- Stack deployment groups: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-groups
15+
- Stack deployment runs: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-runs
16+
- Stack deployment steps: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-deployment-steps
17+
- Stack states: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-states
18+
- Stack diagnostics: https://developer.hashicorp.com/terraform/cloud-docs/api-docs/stacks/stack-diagnostics
19+
20+
Examples:
21+
22+
- [stack.py](../../examples/stack.py)
23+
- [stack_configuration.py](../../examples/stack_configuration.py)
24+
- [stack_deployment.py](../../examples/stack_deployment.py)
25+
- [stack_deployment_group.py](../../examples/stack_deployment_group.py)
26+
- [stack_deployment_run.py](../../examples/stack_deployment_run.py)
27+
- [stack_deployment_step.py](../../examples/stack_deployment_step.py)
28+
- [stack_state.py](../../examples/stack_state.py)
29+
- [stack_configuration_summary.py](../../examples/stack_configuration_summary.py)
30+
- [stack_deployment_group_summary.py](../../examples/stack_deployment_group_summary.py)
31+
- [stack_diagnostic.py](../../examples/stack_diagnostic.py)
32+
33+
See the end-to-end scenario at [stack-deployment.md](../scenarios/stack-deployment.md).
34+
35+
---
36+
37+
## Stacks (`client.stacks`)
38+
39+
| Method | Purpose |
40+
|---|---|
41+
| `client.stacks.create(options)` | Create a stack in a project. |
42+
| `client.stacks.update(stack_id, options)` | Update a stack's name, description, or VCS settings. |
43+
| `client.stacks.list(organization, options)` | Iterate stacks in an organization. |
44+
| `client.stacks.read(stack_id)` | Read a single stack. |
45+
| `client.stacks.delete(stack_id)` | Delete a stack. |
46+
| `client.stacks.force_delete(stack_id)` | Force-delete a stack that cannot be deleted normally. |
47+
48+
```python
49+
from pytfe import TFEClient
50+
from pytfe.models import Project, StackCreateOptions, StackListOptions, VCSRepo
51+
52+
client = TFEClient()
53+
54+
# Create
55+
stack = client.stacks.create(
56+
StackCreateOptions(
57+
name="k8s-stack",
58+
project=Project(id="prj-abc123"),
59+
vcs_repo=VCSRepo(
60+
identifier="my-org/k8s-stack",
61+
branch="main",
62+
oauth_token_id="ot-abc123",
63+
),
64+
)
65+
)
66+
print(stack.id, stack.name)
67+
68+
# List
69+
for stack in client.stacks.list("my-org", StackListOptions(page_size=20)):
70+
print(stack.id, stack.name, stack.deployment_names)
71+
72+
# Read / update / delete
73+
stack = client.stacks.read("st-abc123")
74+
client.stacks.delete("st-abc123")
75+
```
76+
77+
---
78+
79+
## Stack configurations (`client.stack_configurations`)
80+
81+
A stack configuration is a versioned snapshot of the stack's source,
82+
created whenever a VCS commit triggers preparation. Its `status` progresses
83+
from `pending` through `converging` to `converged` (or `errored` if
84+
preparation fails). Check `client.stack_diagnostics` for details when a
85+
configuration errors.
86+
87+
| Method | Purpose |
88+
|---|---|
89+
| `client.stack_configurations.create(stack_id, options)` | Create (trigger preparation of) a new configuration. |
90+
| `client.stack_configurations.list(stack_id, options=None)` | Iterate configurations for a stack, newest first. |
91+
| `client.stack_configurations.read(configuration_id, options=None)` | Read a configuration, optionally with included relationships. |
92+
93+
```python
94+
from pytfe.models import (
95+
StackConfigurationCreateOptions,
96+
StackConfigurationIncludeOps,
97+
StackConfigurationReadOptions,
98+
StackConfigurationSource,
99+
)
100+
101+
# Trigger preparation from the latest VCS commit
102+
config = client.stack_configurations.create(
103+
"st-abc123",
104+
StackConfigurationCreateOptions(source=StackConfigurationSource.FETCH),
105+
)
106+
print(config.id, config.status)
107+
108+
# Read with diagnostics included
109+
config = client.stack_configurations.read(
110+
"stc-abc123",
111+
StackConfigurationReadOptions(
112+
include=[StackConfigurationIncludeOps.STACK_DIAGNOSTICS]
113+
),
114+
)
115+
116+
# Iterate configurations for a stack
117+
for config in client.stack_configurations.list("st-abc123"):
118+
print(config.id, config.status, config.sequence_number)
119+
```
120+
121+
---
122+
123+
## Stack configuration summaries (`client.stack_configuration_summaries`)
124+
125+
Lightweight rollup of status and deployment counts per configuration — useful
126+
for dashboards without fetching every configuration individually. Each summary
127+
also carries `group_status_summary` and `run_status_summary` objects with
128+
aggregated counts across all deployment groups and runs.
129+
130+
| Method | Purpose |
131+
|---|---|
132+
| `client.stack_configuration_summaries.list(stack_id, options=None)` | Iterate configuration summaries for a stack, newest first. |
133+
134+
```python
135+
from pytfe.models import StackConfigurationSummaryListOptions
136+
137+
for summary in client.stack_configuration_summaries.list("st-abc123"):
138+
print(summary.id, f"seq={summary.sequence_number}", summary.status)
139+
if summary.group_status_summary:
140+
g = summary.group_status_summary
141+
print(f" groups: succeeded={g.succeeded} failed={g.failed}")
142+
if summary.run_status_summary:
143+
r = summary.run_status_summary
144+
print(f" runs: succeeded={r.succeeded} failed={r.failed}")
145+
```
146+
147+
---
148+
149+
## Stack deployments (`client.stack_deployments`)
150+
151+
A stack deployment represents one named environment (e.g. `dev`, `staging`,
152+
`prod`) that receives configuration changes. Deployments are defined in the
153+
stack's source and tracked here for status and history.
154+
155+
| Method | Purpose |
156+
|---|---|
157+
| `client.stack_deployments.list(stack_id, options=None)` | Iterate deployments for a stack. |
158+
159+
```python
160+
for deployment in client.stack_deployments.list("st-abc123"):
161+
print(deployment.id, deployment.name)
162+
```
163+
164+
---
165+
166+
## Stack deployment groups (`client.stack_deployment_groups`)
167+
168+
A deployment group coordinates the plan and apply runs for one deployment
169+
within a configuration. Use `approve_all_plans` to advance pending plan steps,
170+
or `rerun` to retry specific failed deployments.
171+
172+
| Method | Purpose |
173+
|---|---|
174+
| `client.stack_deployment_groups.list(configuration_id, options=None)` | Iterate deployment groups for a configuration. |
175+
| `client.stack_deployment_groups.read(group_id)` | Read a deployment group. |
176+
| `client.stack_deployment_groups.read_by_name(configuration_id, name)` | Read a deployment group by its deployment name. |
177+
| `client.stack_deployment_groups.approve_all_plans(group_id)` | Approve all pending plan steps in the group. |
178+
| `client.stack_deployment_groups.rerun(group_id, options)` | Rerun specific failed deployments in the group. |
179+
180+
```python
181+
from pytfe.models import StackDeploymentGroupRerunOptions
182+
183+
# List all groups for a configuration
184+
for group in client.stack_deployment_groups.list("stc-abc123"):
185+
print(group.id, group.status)
186+
187+
# Read by deployment name
188+
dev_group = client.stack_deployment_groups.read_by_name("stc-abc123", "dev")
189+
190+
# Approve all pending plans
191+
client.stack_deployment_groups.approve_all_plans("sdg-abc123")
192+
193+
# Rerun failed deployments
194+
client.stack_deployment_groups.rerun(
195+
"sdg-abc123",
196+
StackDeploymentGroupRerunOptions(deployments=["dev", "staging"]),
197+
)
198+
```
199+
200+
---
201+
202+
## Stack deployment group summaries (`client.stack_deployment_group_summaries`)
203+
204+
Per-group rollup of run counts within a configuration — one record per
205+
deployment group, with `status_counts` broken down by run status.
206+
207+
| Method | Purpose |
208+
|---|---|
209+
| `client.stack_deployment_group_summaries.list(configuration_id, options=None)` | Iterate group summaries for a configuration. |
210+
211+
```python
212+
for summary in client.stack_deployment_group_summaries.list("stc-abc123"):
213+
print(summary.name, summary.status)
214+
if summary.status_counts:
215+
c = summary.status_counts
216+
print(
217+
f" pending={c.pending} deploying={c.deploying} "
218+
f"succeeded={c.succeeded} failed={c.failed}"
219+
)
220+
```
221+
222+
---
223+
224+
## Stack deployment runs (`client.stack_deployment_runs`)
225+
226+
A deployment run is the individual plan + apply execution within a deployment
227+
group. Each run progresses through statuses such as `pre-deploying`,
228+
`deploying`, `pending-operator`, `succeeded`, or `failed`.
229+
230+
| Method | Purpose |
231+
|---|---|
232+
| `client.stack_deployment_runs.list(group_id, options=None)` | Iterate runs for a deployment group. |
233+
| `client.stack_deployment_runs.read(run_id, options=None)` | Read a run, optionally with included relationships. |
234+
| `client.stack_deployment_runs.approve_all_plans(run_id)` | Approve all pending plan steps in the run. |
235+
| `client.stack_deployment_runs.cancel(run_id)` | Cancel an in-progress run. |
236+
237+
```python
238+
from pytfe.models import StackDeploymentRunIncludeOpt, StackDeploymentRunReadOptions
239+
240+
# List runs in a deployment group
241+
for run in client.stack_deployment_runs.list("sdg-abc123"):
242+
print(run.id, run.status)
243+
244+
# Read with relationships
245+
run = client.stack_deployment_runs.read(
246+
"sdr-abc123",
247+
StackDeploymentRunReadOptions(
248+
include=[StackDeploymentRunIncludeOpt.STACK_DEPLOYMENT_GROUP]
249+
),
250+
)
251+
252+
# Cancel
253+
client.stack_deployment_runs.cancel("sdr-abc123")
254+
```
255+
256+
---
257+
258+
## Stack deployment steps (`client.stack_deployment_steps`)
259+
260+
Steps are the granular plan and apply operations within a run. A step in
261+
`pending-operator` status requires an explicit `advance()` call before the
262+
deployment can proceed — this is the operator approval gate.
263+
264+
| Method | Purpose |
265+
|---|---|
266+
| `client.stack_deployment_steps.list(run_id, options=None)` | Iterate steps for a run. |
267+
| `client.stack_deployment_steps.read(step_id, options=None)` | Read a step, optionally with included relationships. |
268+
| `client.stack_deployment_steps.advance(step_id)` | Approve a `pending-operator` step to allow it to proceed. |
269+
| `client.stack_deployment_steps.list_diagnostics(step_id, options=None)` | Iterate diagnostics attached to a step. |
270+
| `client.stack_deployment_steps.download_artifact(step_id, artifact_type)` | Download a step artifact as raw bytes. |
271+
272+
Artifact types: `PLAN_DESCRIPTION`, `APPLY_DESCRIPTION`, `PLAN_DEBUG_LOG`,
273+
`APPLY_DEBUG_LOG`.
274+
275+
```python
276+
from pytfe.models import StackDeploymentStepArtifactType
277+
278+
for step in client.stack_deployment_steps.list("sdr-abc123"):
279+
print(step.id, step.operation_type, step.status)
280+
281+
# Advance a step waiting for operator approval
282+
client.stack_deployment_steps.advance("sds-abc123")
283+
284+
# Download the plan description
285+
plan_bytes = client.stack_deployment_steps.download_artifact(
286+
"sds-abc123",
287+
StackDeploymentStepArtifactType.PLAN_DESCRIPTION,
288+
)
289+
print(plan_bytes.decode())
290+
291+
# List diagnostics for a failed step
292+
for diag in client.stack_deployment_steps.list_diagnostics("sds-abc123"):
293+
print(diag.id, diag.severity, diag.summary)
294+
```
295+
296+
---
297+
298+
## Stack states (`client.stack_states`)
299+
300+
A stack state captures the Terraform state snapshot for one deployment at a
301+
point in time. The `is_current` flag identifies the live state for each
302+
deployment. Each state carries a `components` list describing which stack
303+
components contributed to the snapshot.
304+
305+
| Method | Purpose |
306+
|---|---|
307+
| `client.stack_states.list(stack_id, options=None)` | Iterate all state snapshots for a stack across all deployments. |
308+
| `client.stack_states.read(state_id)` | Read a single state snapshot. |
309+
| `client.stack_states.download_description(state_id)` | Download the raw state description bytes. |
310+
311+
```python
312+
from pytfe.models import StackStateListOptions
313+
314+
# Current state per deployment
315+
for state in client.stack_states.list("st-abc123"):
316+
if state.is_current:
317+
print(
318+
state.id,
319+
f"deployment={state.deployment}",
320+
f"resources={state.resource_instance_count}",
321+
)
322+
for comp in state.components:
323+
print(f" component={comp.address}")
324+
325+
# Download raw state description (treat as sensitive)
326+
raw = client.stack_states.download_description("sts-abc123")
327+
```
328+
329+
The description bytes are a JSON blob containing resource instance details.
330+
Treat them as sensitive — they may contain provider credentials or other
331+
secret material.
332+
333+
---
334+
335+
## Stack diagnostics (`client.stack_diagnostics`)
336+
337+
Diagnostics are error or warning records attached to a configuration or a
338+
deployment step. They surface problems such as provider checksum mismatches,
339+
deprecated filename extensions, or validation failures. Acknowledging a
340+
diagnostic marks it as reviewed.
341+
342+
Diagnostic IDs use the `std-` prefix.
343+
344+
| Method | Purpose |
345+
|---|---|
346+
| `client.stack_diagnostics.read(diagnostic_id)` | Read a stack diagnostic. |
347+
| `client.stack_diagnostics.acknowledge(diagnostic_id)` | Acknowledge a diagnostic (mark as reviewed). |
348+
349+
```python
350+
diag = client.stack_diagnostics.read("std-abc123")
351+
print(diag.severity, diag.summary)
352+
print(diag.detail)
353+
354+
# diags is populated when the server rolls up multiple sub-diagnostics
355+
if diag.diags:
356+
for nested in diag.diags:
357+
print(" ", nested.get("severity"), nested.get("summary"))
358+
359+
if not diag.acknowledged:
360+
client.stack_diagnostics.acknowledge("std-abc123")
361+
```

0 commit comments

Comments
 (0)