Scenarios — python-heatclient — branch stable/2026.2
Branch
stable/2026.2@88120f11830d(5.3.0-2-g88120f1) — repository https://opendev.org/openstack/python-heatclient — analysed on 2026-11-01
Each diagram follows requests [observed] on the local stub with hand-written answers. Scenario IDs refer to _rewrite/scenarios_stable-2026.2.json. The stub is not Heat, and what Heat does between requests comes from the Heat reverse-spec.
1. stack create --wait (G01, G02, G03, G04)
sequenceDiagram
participant U as User
participant C as openstack
participant F as Local files
participant K as Keystone
participant H as Heat API
U->>C: stack create x -t template.yaml --wait
C->>F: urlopen file://…/template.yaml, get_file, -e files
alt file missing
C->>H: GET /absent.yaml with token
H-->>C: 404
C-->>U: urlopen error, exit 1
end
C->>K: POST /v3/auth/tokens
K-->>C: 201, token and catalog
C->>H: POST /stacks {stack_name, template, files, environment…}
alt 4xx or 5xx
H-->>C: fault body
C-->>U: ERROR: error.message, exit 1
end
H-->>C: 201 {"stack": {"id": …}}
loop until a stack event with a final status
C->>H: GET /stacks/x/events?marker=…&sort_dir=asc
H-->>C: 200 {"events": […]}
C-->>U: event log lines
Note over C: sleep --poll, 5 s by default. After 2 empty rounds: GET /stacks/x?resolve_outputs=False
end
alt CREATE_FAILED
C-->>U: Stack x CREATE_FAILED, exit 1
else CREATE_COMPLETE
C->>H: GET /stacks/{id}?resolve_outputs=False
H-->>C: 302 Location /stacks/x/{id}
C->>H: GET /stacks/x/{id}
H-->>C: 200 {"stack": …}
C-->>U: table of 7 fields, exit 0
endDiagnostics: --debug shows each request. A template error appears before any request. An error on POST /stacks comes from Heat's validation. A wait stuck with no event points to the engine, not the client: use stack failures list once failed. Interrupting does not stop the creation.
2. stack update --wait and the name lookup (G05, G06, G07)
sequenceDiagram
participant C as openstack
participant H as Heat API
C->>H: GET /stacks/x/events?limit=1&sort_dir=desc
H-->>C: last event, its id is the marker
C->>H: PUT /stacks/x {template…}
H-->>C: 302 Location /stacks/x/{id}
C->>H: PUT /stacks/x/{id} {template…}
alt conflict
H-->>C: 409 ActionInProgress
C-->>C: ERROR: …, exit 1
end
H-->>C: 202
C->>H: GET /stacks/x, then 302
C->>H: GET /stacks/x/{id}
H-->>C: stack_name, used for polling
loop until UPDATE_COMPLETE or UPDATE_FAILED
C->>H: GET /stacks/x/events?marker=…&sort_dir=asc
end
C->>H: GET /stacks/x?resolve_outputs=False, then 302, then GET /stacks/x/{id}Variants: --existing uses PATCH, with template: null if -t is absent. --dry-run first resolves the name with GET /stacks/x (redirect off), then PUT /stacks/x/{id}/preview, and prints resource_changes.
Diagnostics: Location not returned with redirect means the lookup did not answer a redirect; a proxy or a non-Heat service is likely. Without --wait, the table shows the status at that instant, often still the previous one.
3. stack delete --wait (G08, G09, D09)
sequenceDiagram
participant C as openstack
participant H as Heat API
loop each stack on the command line
C->>H: GET /stacks/x/events?limit=1&sort_dir=desc
C->>H: DELETE /stacks/x
H-->>C: 302 Location /stacks/x/{id}
C->>H: DELETE /stacks/x/{id}
alt 404
H-->>C: 404
Note over C: prints Stack not found: x, count it
else 403
H-->>C: 403
Note over C: prints Forbidden: x, count it
else accepted
H-->>C: 204
end
end
loop each accepted stack
C->>H: GET /stacks/x/events?marker=…&sort_dir=asc
alt 404 on events
H-->>C: 404
Note over C: the stack is gone, success
else DELETE_FAILED stack event
H-->>C: 200
Note over C: prints the status, count it
else empty twice, then GET /stacks/x answers 404
H-->>C: 404
Note over C: uncaught HTTPNotFound, exit 1, although the stack is gone
end
end
Note over C: count > 0 gives Unable to delete N of the M stacks, exit 1Diagnostics: per-stack lines are on stdout, the summary on stderr. A failed stack leaves its reason in stack show. There is no prompt when stdin is not a terminal.
4. Hook: pause, inspect, release (G17, G18, D02, D03)
sequenceDiagram
participant U as User
participant C as openstack
participant H as Heat API
U->>C: stack create x -t t.yaml --pre-create r1
C->>H: POST /stacks, environment.resource_registry.resources.r1.hooks = pre-create
U->>C: stack hook poll x
C->>H: GET /stacks/x, then 302, then GET /stacks/x/{id}
H-->>C: stack_status CREATE_IN_PROGRESS gives hook type pre-create
C->>H: GET /stacks/x/events?sort_dir=asc
H-->>C: all events
Note over C: keep events after the last "Stack CREATE started", then resources with "CREATE paused until Hook pre-create is cleared" and no later "Hook pre-create is cleared"
C-->>U: pending resources
U->>C: stack hook clear x r1
C->>H: GET /stacks/x…, status gives the hook type
C->>H: GET /stacks/x/resources
C->>H: GET /stacks/x, redirect off
C->>H: POST /stacks/x/{id}/resources/r1/signal {"unset_hook": "pre-create"}Diagnostics: stack hook poll needs the stack name. With an ID, or if the start event is gone, it prints list index out of range. Stack status … not IN_PROGRESS means no hook can be pending. A clear on a wrong name exits 0 and does nothing: check with stack hook poll again.
5. Software deployment (G20, D01, L02)
sequenceDiagram
participant U as User
participant C as openstack
participant H as Heat API
participant S as Swift
C->>H: GET /software_configs/{id}, if --config
alt default TEMP_URL_SIGNAL with openstack
Note over C: AttributeError get_token, exit 1, nothing sent
else TEMP_URL_SIGNAL with the heat shell
C->>S: PUT container, HEAD account, PUT object
Note over C: input deploy_signal_id = TempURL
C->>H: POST /software_configs
C->>H: POST /software_deployments
else NO_SIGNAL
C->>H: POST /software_configs: derived config, inputs + deploy_*
H-->>C: {"software_config": {"id": "derived"}}
C->>H: POST /software_deployments {config_id, server_id, action, status: IN_PROGRESS}
H-->>C: {"software_deployment": …}
C-->>U: YAML of the deployment
endDiagnostics: the server's agent does the work and reports through Heat; follow with software deployment show and software deployment output show. Under --long, named outputs stay truncated: use --all --long.
Source: reverse-spec-python-heatclient/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.