Skip to content

docs: make free-cloud detection canonical in get_free_clouds - #77

Merged
sadsfae merged 1 commit into
developmentfrom
76-canonical-free-clouds
Oct 11, 2026
Merged

sadsfae merged 1 commit into
developmentfrom
76-canonical-free-clouds

Conversation

@sadsfae

@sadsfae sadsfae commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Implements #76.

Related: quadsproject/quads-client#193, quadsproject/quads-client#194.

What it does:

  • Documents QuadsApi.get_free_clouds() as the canonical free-cloud API in a napoleon docstring: a cloud is free when it has no active assignment (which also excludes future-scheduled clouds, since their assignments are active), the spare pool is excluded server-side via the server's spare_pool_name config, and the raw response is a JSON list of cloud dicts with id, name and last_redefined (RFC 1123 GMT).
  • Pins the response contract in tests: the happy-path fixture now matches the real server payload shape (bare list, not a wrapped dict) and asserts full passthrough including last_redefined; the empty case is corrected from {"clouds": []} to []; adds test_get_free_clouds_not_found (404 -> APINotFound, mirroring the move-status pattern) for servers older than 2.1 that lack /clouds/free/.
  • Adds a "Finding Free Clouds" section to docs/usage.rst with the reservation-lock hint recipe (last_redefined plus client-side cloud_reservation_lock hours; the lock window is not server-exposed).
  • Version bump to 0.1.18 (setup.py, __init__.py, rpm spec, CHANGELOG), mirroring the in-branch convention from [publish] fix: handle edge case for old QUADS servers. #74.

Notes:

  • Zero runtime change: the method is a raw passthrough, so reservation-lock info (last_redefined) already flows to clients; only the contract was unpinned and undocumented.
  • get_free_clouds has existed since the first quads-lib release (0.1.0); /clouds/free/ exists on QUADS servers since v2.1.0 (commit b63e2f1). Only 1.x and 2.0.x servers 404, which surfaces as APINotFound per the pattern added in 61f5ddf.
  • Semantics follow the server's deliberate choice in quads commit 06fd44f (closes [BUG] [SSM] Cloud auto assignment without schedules quads#577): assignment state is the criterion, not schedule windows. The known terminate_assignment edge (active=False with surviving future schedules re-freeing a cloud) is a server-side gap tracked in quads, not here.
  • For quads-client: PR #194 review guidance (CLI cmd_find_free_cloud and GUI _get_free_clouds becoming thin api.get_free_clouds() wrappers) can land on top of this; no client-side v2.0.x fallback is needed given the APINotFound behavior above.
  • Release flow: version is bumped to 0.1.18 here; when merging to latest, the merge/publish commit needs the [publish] marker per publish.yml to actually ship to PyPI.

Note

Server endpoints GET /clouds/free/, /schedules/current and /schedules/future have no check_access decorator (not admin-gated server-side); that is tracked in the quads server repo and out of scope here.

Document get_free_clouds as the canonical free-cloud API: server-side
semantics (no active assignment, future-scheduled clouds excluded via
their active assignment, spare pool excluded via server config), the
response contract including the last_redefined reservation-lock field,
and APINotFound on servers older than 2.1 lacking /clouds/free/. Pin
the contract in tests (full payload passthrough, 404 handling) and add
a usage docs section with the reservation-lock hint recipe. Version
bump to 0.1.18.

   fixes: #76
@codecov

codecov Bot commented Oct 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/quads_lib/__init__.py 100.00% <100.00%> (ø)
src/quads_lib/quads.py 99.67% <ø> (ø)
tests/test_quads.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ttlogan ttlogan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed it as a fresh look. No findings.

Verified independently:

  • get_free_clouds is a raw passthrough. The @returns("List[Cloud]") decorator only sets func._returns; it does not wrap or transform the return value, so this is genuinely zero runtime change.
  • The new test_get_free_clouds_not_found mirrors the move-status pattern and matches _make_request exactly: 404 with a non-JSON body raises APINotFound("Resource not found").
  • The empty-case fix (from {"clouds": []} to []) and the happy-path fixture (bare list with id/name/last_redefined, full passthrough asserted) pin the real server payload shape.
  • get_free_clouds has no callers in this repo, so nothing here breaks; the client-side consumers are in quads-client.
  • Version bump is consistent across setup.py, init.py, the rpm spec and CHANGELOG. Docs check is green and the reST underline matches the section title.

All green, nothing blocking.

@sadsfae
sadsfae merged commit 7f6226c into development Oct 11, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants