Expand description
The socket: HTTP/1.1, hand-rolled, because one of the behaviours is not a status code.
Behaviour 2 is that GET /1.3/price fails at the transport level —
connection reset, nothing written — and monetize’s start-time credential
probe reported “the credential in UPCLOUD_TOKEN could not be verified” for
what was a dropped socket. A framework that hands back a Response cannot
express “write nothing and close”, and a mock that answered 503 there would
never have provoked the misreport. So the server is a TcpListener, a request
parser and a response writer: about two hundred lines, and every one of the
twenty-two behaviours is reachable from it.
Keep-alive is supported (the real plugin’s reqwest client pools
connections, and a mock that closed every socket would hide a pooling bug).
Bodies are read by Content-Length; Transfer-Encoding: chunked requests
are refused by name, because the real API does not send them and a silent
mis-parse is worse than a refusal.
§The surface
| method | path | notes |
|---|---|---|
| GET | /1.3/price | behaviour 2 lives here |
| GET | /1.3/account | what a credential probe reads |
| GET | /1.3/server | ?label=k=v, repeatable; thin rows (behaviour 4) |
| GET | /1.3/server/{uuid} | the only place attachments and IPs exist; 404 SERVER_NOT_FOUND for a uuid the LIST carries (36, by name) |
| POST | /1.3/server | 98–105 s in maintenance (behaviour 6); 412 out_of_stock in a sold-out zone (37) |
| PUT | /1.3/server/{uuid} | plan · boot_order · labels · remote_access (behaviours 9, 14, 17) |
| DELETE | /1.3/server/{uuid} | ?storages=1&backups=keep; needs stopped (11); slow (7) |
| POST | /1.3/server/{uuid}/start | 412 out_of_stock (behaviour 3) |
| POST | /1.3/server/{uuid}/stop | soft/hard; timeout is a STRING |
| POST | /1.3/server/{uuid}/restart | |
| POST | /1.3/server/{uuid}/storage/attach | |
| POST | /1.3/server/{uuid}/storage/detach | refused on a started server (16); can answer 200 and leave the device attached (38, by name) |
| POST | /1.3/server/{uuid}/cdrom/eject | works on a started server (16) |
| POST | /1.3/server/{uuid}/cdrom/load | a medium into an EMPTY tray; 409 CDROM_DEVICE_IN_USE otherwise (L110, documented, not measured) |
| GET | /1.3/server/{uuid}/firewall_rule | 403 ERROR_AUTHENTICATION_FAILED for a deleted server (1); the SAME 403 for a live one under a credential without the firewall permission (35, by name) |
| GET | /1.3/storage | includes public templates |
| GET | /1.3/storage/private | the account’s own |
| GET | /1.3/storage/{uuid} | |
| POST | /1.3/storage | |
| PUT | /1.3/storage/{uuid} | a shrink is refused by name (22) |
| POST | /1.3/storage/{uuid}/resize | takes a Resize Backup FIRST and hands it back as resize_backup (34) |
| DELETE | /1.3/storage/{uuid} | |
| POST | /1.3/storage/{uuid}/import | direct upload |
§The terraform door
private-holger-ops reaches the same account through UpCloudLtd/upcloud
5.44 rather than through the plugin, and asks for four things the plugin
never asks for. They are listed apart because they are INFERRED from the
provider’s own calls rather than measured against the account — see
crate::tf.
| method | path | notes |
|---|---|---|
| GET | /1.3/plan | read before EVERY server create; an unknown plan is refused there |
| GET | /1.3/storage/public · /template · /favorite | how an OS template is resolved BY TITLE |
| PUT · POST | /1.3/server/{uuid}/firewall_rule | the rule SET, written whole (PUT) or appended to (POST) |
| DELETE | /1.3/server/{uuid}/firewall_rule/{position} | one rule by position |
POST /1.3/server takes the same door’s richer body: the machine’s network
interfaces, its boot order, its firewall flag, its timezone and every device
— the template to clone AND the volumes to attach.
Everything else answers 404 MOCK_UPCLOUD_NOT_IMPLEMENTED naming the path.
§The mock’s own door
/mock/… is not an UpCloud path and cannot collide with one: /mock/estate
(everything, for a test’s assertions), /mock/fault/{name}/arm|disarm,
/mock/relay (behaviour 12: reshuffle the addresses), /mock/seed.
Structs§
- Heard
- One credential’s traffic, as the mock heard it (behaviour 63).
- Mock
- The whole mock: one estate behind one lock. A real UpCloud account is one
serialized thing too — two
POST /1.3/storagecalls do not interleave — so the lock is not a simplification, it is the provider’s own concurrency.