OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Clients

python-heatclient — Scenarios

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
  end

Diagnostics: --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 1

Diagnostics: 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
  end

Diagnostics: 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.