Reverse-specification of python-designateclient — branch stable/2026.2
Branch
stable/2026.2@9231eef90192(7.0.0+ 2 maintenance commits; package version 7.0.1.dev2) — repository https://opendev.org/openstack/python-designateclient — analysed on 2026-11-01
- Scope: the whole repository: OSC plugin, Python API, tests and the unused functional tests. The change history (step 7) was not requested, so there is no file 06.
- Dependencies read at fixed versions, from the shared venv: osc-lib 4.7.0, cliff 4.16.0, python-openstackclient 10.3.1, keystoneauth1 5.17.0, openstacksdk 4.20.0. They are cited with the prefixes
osc-lib:,cliff:,openstackclient:,keystoneauth1:andopenstacksdk:. - Also read, never started:
designatestable/2026.2@e3dd774db145,neutronstable/2026.2@eef1a0f7ee36,heatstable/2026.2@5872396e548c, with the prefixesdesignate:,neutron:andheat:. - References are
file:linefrom the repository root. [observed] means seen by running the realopenstackshell against a local stub on 127.0.0.1. [inferred] means not followed to the end. - Observed behaviour against a stub says nothing about a real service. The stub answers what it is told to. No Designate, Keystone, lab or cloud was contacted.
Files of this specification
| File | Content |
|---|---|
| 01-cli-commands_stable-2026.2.md | shared mechanics, functional description by family, Python API, and the 60 commands with their arguments, requests and what they read in the response |
| 02-errors_stable-2026.2.md | exit codes, exception classes, status translation, client-side errors, 18 defects |
| 03-interactions_stable-2026.2.md | Keystone, discovery, Designate requests and headers, local file, Python API users |
| 04-scenarios_stable-2026.2.md | 5 scenarios with sequence diagrams and diagnostics |
| 05-async-processing_stable-2026.2.md | no background processing; the only loop is pagination |
| 07-rewrite-pack_stable-2026.2.md | client contract: what the client requires from a DNS service, test vectors, proof and limits |
| _verification_stable-2026.2.md | output of the reference checker |
Overview
The package has two layers. designateclient.v2.client.Client is a Python library with one controller per resource, on top of a keystoneauth adapter that translates HTTP statuses into exceptions. designateclient.v2.cli holds 60 command classes for openstack, loaded from entry points. Each invocation is one short-lived openstack process that authenticates, discovers the DNS endpoint, sends one to three requests, prints a table and exits. There is no database, bus, cache, server or daemon, and **no separate designate shell** on this branch.
Architecture
flowchart LR user[User or script] -->|argv, env, zone file| osc[openstack process] osc -->|entry points| cli[designateclient.v2.cli] cli --> client[designateclient.v2.client.Client] neutron[neutron external DNS driver] -->|Python API| client heat[heat designate resources] -->|Python API| client client --> adapter[DesignateAdapter on keystoneauth1] adapter -->|HTTPS, token| ks[Keystone] adapter -->|HTTPS REST /v2, X-Auth-Token| dns[Designate API]
Processes
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
openstack (python-openstackclient) | pyproject.toml:39 → designateclient/osc/plugin.py:33 | runs one command | argv, environment, one local file for zone import create; listens on nothing |
No legacy shell: pyproject.toml declares no script. designateclient/functionaltests/client.py:372 wraps the openstack binary for tests that need a live cloud.
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| Keystone | HTTPS REST | keystoneauth1, through OSC | --os-auth-url, clouds.yaml, OS_* | token, catalog, project ID |
| Designate API | HTTPS REST | keystoneauth1 LegacyJsonAdapter | catalog entry of type dns | every command |
| osprofiler | HTTP headers | optional, imported if present | none | trace headers (designateclient/v2/client.py:92); not exercised |
Key figures
| Item | Count |
|---|---|
| Commands | 60 in openstack.dns.v2, 265 arguments: 14 lists, 34 single objects, 12 with no output |
| Controllers in the Python API | 15; 2 are used by no command (pools, nameservers) |
| Operations used on Designate | 61 method and route pairs, 59 seen in the probes, 2 more in the defect scenarios; all 61 exist in the Designate routes (static comparison) |
| Commands that reached a real route on the stub | 60 of 60 in all three modes |
| Requests recorded | 60 in 404 mode, 60 in {} mode, 61 in fixture mode; exit 0 for 60 of 60 in fixture mode |
| Defect scenarios on the stub | 103 |
| Exception classes | 11, in designateclient/exceptions.py |
| Unit tests | 111 of 111 pass, twice, giving 97 vectors (87 API, 10 command); 5 of 60 command classes have a command vector |
Points of attention
Details and sources are in 02 § 4.
- Untranslated 4xx is success [observed]: 405, 406, 415, 429 and any other unlisted 4xx exit 0. A
Commandprints nothing, and aShowOneprints the fault as if it were the resource (designateclient/v2/client.py:107). Scripts cannot detect the failure. - **
ptr record set --no-descriptionand--no-ttldo nothing [observed]**, and exit 0 (designateclient/v2/cli/reverse.py:114). - **
--ttl 0is dropped byzone setandrecordset set[observed]**, whilezone createandptr record setsend it (designateclient/v2/cli/zones.py:234). - Implicit all-projects on quotas [observed]:
dns quota setandresetwithout--project-idsendX-Auth-All-Projects: True(designateclient/v2/cli/quotas.py:102). A token with no project givesPATCH /quotas/None. - **Sticky headers in one process [observed through
run_subcommand]**:--sudo-project-idand--hard-deletecarry over to later commands in the interactive shell (designateclient/v2/cli/common.py:86). This matters for a destructive flag. One-shot runs are not affected. - **
recordset list --actionsends a filter that Designate refuses** [request observed; refusal read in Designate, not run]. - Pagination has no limit [observed]: a repeated or
nulllinks.nextloops forever (designateclient/v2/utils.py:70). - Discovery matters [observed]: a catalog URL without
/v2whose root answers 404 makes the client send/dns/zones, without the version. A rewrite must serve the version document, or register the URL with/v2. - Response keys are hard requirements [observed]: a missing key gives a bare
'zones'or'masters', exit 1; an empty object on aShowOnegives an unpacking error; an empty 202 on a delete gives a crash after the change was accepted. - Unit tests catch none of this: the 10 command tests mock the client, and the 87 API tests use
requests-mockwith friendly bodies.
Not found: the OSC defect of a command.Command returning a value. None of the 12 classes does (02 § 1).
Blind spots / [inferred]
- No real Designate was contacted. Every statement about what a service accepts is either read in the Designate clone, and marked so, or unknown. Function and field checks in
reverse-spec-designatewere not re-verified. - Fixture mode bodies are hand-written from the Designate adapters. They prove the formatters work on these bodies, not on real ones.
- The functional tests (
designateclient/functionaltests/) need a cloud and a Tempest configuration (designateclient/functionaltests/config.py:21), so they were not run. - The interactive shell was not run, because it reads a terminal. Defect 8 calls
run_subcommand, the same method the loop calls. - osprofiler is installed in the venv, but no trace was enabled, so its headers (
designateclient/v2/client.py:92) were not exercised. - **Connection failures and
--timeout** were not reproduced. - **TLS,
clouds.yamland non-password auth** are OSC and keystoneauth matters, not analysed here; the probes used password auth only. - Output formatters (
-f json,-c, and so on) come from cliff and were not specified per command. - **
doc/** was not compared with the code in detail. - In-process runs: the probes reset the client cache between commands to mimic separate processes, but they share a Python process. Global state outside that cache was not isolated.
Source: reverse-spec-python-designateclient/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.