fix: align API handlers with the OpenAPI spec

Closes #782 (closed).

Five handler bugs found while aligning engine/api/swagger-spec/dblab_openapi.yaml with the handlers, plus the follow-ups a review of the fix turned up.

1. Not-found and bad-request errors returned 500

api.SendError type-asserted the value form of models.Error, but models.New returns a pointer, so every cloning error went out as 500 INTERNAL_ERROR. SendError now matches *models.Error with errors.As, the Send*Error helpers build the same pointer form, and createClone drops its private pointer match in favour of the central mapping.

With the codes visible, "clone is not started yet" (reset, upgrade) is changed from NOT_FOUND to BAD_REQUEST: the clone exists.

2. Percent-encoded snapshot ids were rejected

The router used UseEncodedPath(), so pool%2Fbranch%2Fmain%40snap reached the handlers escaped and failed snapshotIDRegexp. Swagger UI's "Try it out" was broken for /snapshot/{id} and /branch/snapshot/{id}. UseEncodedPath() is removed; it was added in e47d380e to keep slashes out of clone ids, which cloneIDRegexp in the validator already does. Path variables now arrive decoded in every handler.

3. POST /snapshot returned the pool manager's struct

The handler wrote a resources.Snapshot (used/logicalReferenced), so the Go client decoded sizes as 0. It now returns a models.Snapshot built from the pool manager entry via a new models.NewSnapshot, which also replaces two inline copies of the same mapping in cloning and provision. The response is deliberately not read back from the cloning cache: that cache skips empty pools, so a lookup there could answer 400 for a snapshot that was just created. The handler also sorts a copy of the list instead of the manager's internal slice.

4. "deleteAt": "" scheduled deletion at 0001-01-01

LocalTime.UnmarshalJSON leaves a zero time on an empty string, and the retention sweeper treated it as due. applyProtectionUpdate now rejects a zero deleteAt with 400, covering both PATCH /snapshot/{id} and PATCH /branch/{branchName}.

5. A branch named snapshot had no reachable log

/branch/snapshot/{id:.*} was registered before /branch/{branchName}/log. The log route is registered first. Router construction is split into newRouter so route order is unit-tested.

Spec

The two # TODO: fix it in engine 404 blocks (PATCH /clone/{id}, POST /clone/{id}/reset) are enabled, and DELETE /clone/{id} and reset gain the 400 responses they now return for protected or upgrading clones.

Edited by Artyom Kartasov

Merge request reports

Loading
Loading