Interactions — python-barbicanclient — branch stable/2026.2
Branch
stable/2026.2@8162006e8677— repository https://opendev.org/openstack/python-barbicanclient — analysed on 2026-11-01
All observed frames come from the local stub. They show what the client sends. Responses shown are what the stub was told to answer, not what a real Barbican answers. The barbican: references say what the service source does; no service was run.
No database, message bus, cache, RPC, subprocess or socket other than HTTP. The inventory found 25 keystoneauth occurrences in 5 files, 0 RPC and 0 triggers.
1. Keystone
Handled entirely by keystoneauth. Under OSC the session comes from osc-lib:osc_lib/clientmanager.py:195. Under barbican it is built by barbicanclient/barbican.py:132.
| Step | Request | When | Observed |
|---|---|---|---|
| discovery | GET /identity | once per process | [observed] |
| token | POST /identity/v3/auth/tokens | once per process; again after a 401 | [observed] |
2. Barbican: endpoint and microversion
Selection of the endpoint:
| Caller | Rule | Source |
|---|---|---|
openstack | catalog, service type key-manager, region and interface of the CLI, no way to override the endpoint | barbicanclient/osc_plugin.py:28, barbicanclient/client.py:208 |
barbican | --endpoint / BARBICAN_ENDPOINT if set, else catalog with --service-type, --service-name, --interface, --region-name | barbicanclient/barbican.py:227 |
| Python API | endpoint= if given, else catalog | barbicanclient/v1/client.py:114 |
With endpoint=, requests go to <endpoint>/<version>/ (barbicanclient/client.py:39). version defaults to v1 (barbicanclient/client.py:30).
**osc_plugin.make_client reads instance._region_name**, a private attribute of the OSC client manager (openstackclient:openstackclient/common/clientmanager.py:80). It passes no version and no microversion, so --os-key-manager-api-version only selects the command group: another value gives a warning, then 'secret list' is not an openstack command, exit 2 (openstackclient:openstackclient/shell.py:135) [observed].
Negotiation, in order, in one process [observed]:
| # | Request | Headers | Purpose | Source |
|---|---|---|---|---|
| 1 | GET <catalog URL> | Accept: application/json, no token, no version header | keystoneauth discovery, for version=v1 | barbicanclient/v1/client.py:115 |
| 2 | GET <catalog URL>/v1 | Accept: application/json, token, OpenStack-API-Version: key-manager 1.1 | range of microversions | barbicanclient/v1/client.py:129 |
With endpoint=, step 1 does not happen and step 2 targets the endpoint as given, without /v1 [observed in legacy-no-auth].
Reading the answer (barbicanclient/v1/client.py:135):
- The first entry of the version list is used. A
statusequal toSTABLE, ignoring case, means 1.0 only. - Any other status needs
min_versionandmax_version. - The client takes the highest of 1.2, 1.1, 1.0 inside the range (
barbicanclient/v1/client.py:30,barbicanclient/v1/client.py:97). - The result becomes
default_microversionof the adapter (barbicanclient/v1/client.py:62), and every later request carriesOpenStack-API-Version: key-manager <version>(keystoneauth1:keystoneauth1/adapter.py:284,keystoneauth1:keystoneauth1/session.py:683).
The service gives stable without min and max when the requested version is 1.0 or absent, and CURRENT with both otherwise (barbican:barbican/api/controllers/versions.py:94, barbican:barbican/api/controllers/versions.py:156, barbican:barbican/api/controllers/versions.py:182). The list of versions at the root is answered with 300 (barbican:barbican/api/controllers/versions.py:206). The maximum is 1.2 (barbican:barbican/api/controllers/versions.py:30).
What each microversion changes in the client:
| Microversion | Effect | Source |
|---|---|---|
| 1.0 | consumer commands stop with Server does not support secret consumers. Minimum key-manager microversion required: 1.1 before any request [observed] | barbicanclient/v1/secrets.py:683 |
| below 1.2 | secret delete first reads the secret, refuses if it has consumers unless --force, and sends no force parameter [observed] | barbicanclient/v1/secrets.py:610 |
| 1.2 | secret delete sends DELETE, with ?force=1 if --force, and maps the error text to SecretHasConsumers [observed] | barbicanclient/v1/secrets.py:600 |
3. Barbican: operations
The full table with headers, service handler and unit test counts is api-surface. The specifics that a re-implementation can miss:
| Topic | Rule | Source |
|---|---|---|
| Trailing slash | POST always ends in /: POST /secrets/, /orders/, /containers/, /secrets/{id}/consumers/. GET, PUT, DELETE do not | barbicanclient/client.py:109 |
| Accept | GET sends application/json, except the payload | barbicanclient/client.py:100 |
| Payload read | Accept carries the content type: the value of -t, default text/plain on the CLI. The body is raw | barbicanclient/v1/secrets.py:319, barbicanclient/barbican_cli/v1/secrets.py:62 |
| Payload update | PUT /secrets/{id} with content-type: text/plain for str, application/octet-stream for bytes, raw body. The CLI always sends text | barbicanclient/v1/secrets.py:536 |
| Consumer removal | DELETE with a JSON body | barbicanclient/v1/secrets.py:745 |
| Secret id | only the last path segment of the URI is used, parsed as a UUID. The host in the URI is ignored [observed with a closed local port, never contacted] | barbicanclient/base.py:45 |
| List parameters | limit, offset always; name, alg, mode, bits, secret_type for secrets; name, type for containers; name for CAs. bits only if above 0 [observed] | barbicanclient/v1/secrets.py:656, barbicanclient/v1/containers.py:720, barbicanclient/v1/cas.py:232 |
| Paging | one page per command: the CLI never follows next, and --limit defaults to 10 | barbicanclient/barbican_cli/v1/secrets.py:116 |
| Date format sent | --expiration is parsed locally, and goes out as 2030-01-01T00:00:00+00:00 [observed] | barbicanclient/v1/secrets.py:445, keystoneauth1:keystoneauth1/session.py:145 |
| Project header | X-Project-Id only with project_id=, i.e. no-auth use | barbicanclient/client.py:47 |
| Errors | raise_exc=False, then own translation; see 02 | barbicanclient/client.py:92 |
Sample frames [observed]
GET /key-manager/v1 HTTP/1.1
Accept: application/json
OpenStack-API-Version: key-manager 1.1
X-Auth-Token: <token>
POST /key-manager/v1/secrets/ HTTP/1.1
Accept: */*
Content-Type: application/json
OpenStack-API-Version: key-manager 1.2
X-Auth-Token: <token>
{"name": "n", "algorithm": "aes", "mode": "cbc", "bit_length": 256, "secret_type": "opaque", "payload": "cA==", "payload_content_type": "application/octet-stream", "payload_content_encoding": "base64"}
GET /key-manager/v1/secrets/11111111-2222-4333-8444-555555555555/payload HTTP/1.1
Accept: text/plain
OpenStack-API-Version: key-manager 1.2
X-Auth-Token: <token>
PUT /key-manager/v1/secrets/11111111-2222-4333-8444-555555555555/acl HTTP/1.1
Accept: */*
Content-Type: application/json
OpenStack-API-Version: key-manager 1.2
X-Auth-Token: <token>
{"read": {"project-access": true, "users": ["u1", "u2"]}}
POST /key-manager/v1/orders/ HTTP/1.1
Accept: */*
Content-Type: application/json
OpenStack-API-Version: key-manager 1.2
X-Auth-Token: <token>
{"type": "key", "meta": {"name": "n", "algorithm": "aes", "bit_length": 256, "expiration": "2030-01-01T00:00:00+00:00", "payload_content_type": "application/octet-stream", "mode": "cbc"}}
DELETE /key-manager/v1/secrets/11111111-2222-4333-8444-555555555555/consumers HTTP/1.1
Accept: */*
Content-Type: application/json
OpenStack-API-Version: key-manager 1.2
X-Auth-Token: <token>
{"service": "x", "resource_type": "x", "resource_id": "x"}
More are in wire-probe-shape.
4. Other
| Item | Direction | Rule | Source |
|---|---|---|---|
secret store --file | read | read whole in binary; refused by argparse together with --payload | barbicanclient/barbican_cli/v1/secrets.py:193 |
secret get --file | write | refused if the file exists, after the payload was fetched [observed]; written in binary, with the process umask [inferred] | barbicanclient/barbican_cli/v1/secrets.py:80 |
| Environment | read | OS_KEY_MANAGER_API_VERSION for OSC; OS_* and BARBICAN_* for barbican | barbicanclient/osc_plugin.py:37, barbicanclient/barbican.py:247 |
| Terminal, binaries | none | no prompt, getpass, subprocess or stdin in non-test code, so the probes excluded no command | barbicanclient/barbican_cli/v1/secrets.py:16 |
etc/barbicanclient.conf:1 is a sample file that no code reads [inferred: oslo_config is imported only by functionaltests/common/config.py:18].
Source: reverse-spec-python-barbicanclient/03-interactions_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.