withcache 0.13.1__tar.gz → 0.13.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {withcache-0.13.1 → withcache-0.13.2}/PKG-INFO +1 -1
- {withcache-0.13.1 → withcache-0.13.2}/shim/build.zig.zon +1 -1
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/__init__.py +1 -1
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_api.py +14 -3
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/client.py +4 -1
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/server.py +21 -8
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_catalog_api.py +16 -0
- {withcache-0.13.1 → withcache-0.13.2}/.gitignore +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/LICENSE +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/README.md +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/deploy/Containerfile +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/deploy/compose.local-build.yml +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/deploy/compose.yml +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/deploy/envvars.example +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/hatch_build.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/pyproject.toml +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/shim/build.zig +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/shim/shim.zig +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_app.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_events_log.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_settings_store.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_shim.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_table_state.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/_layout.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/_table_macros.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/catalog.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/dashboard.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/events.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/login.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/misses.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/_templates/ui/settings.html +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/curlwithcache.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/oras.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/static/bootstrap-icons.min.css +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/static/bootstrap.min.css +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/static/fonts/bootstrap-icons.woff +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/static/fonts/bootstrap-icons.woff2 +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/static/htmx.min.js +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/src/withcache/wgetwithcache.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_differential.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_admin_forms.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_blob.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_events.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_scaffold.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_settings_persistence.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_ui_pages.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_fastapi_uvicorn_smoke.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_oras.py +0 -0
- {withcache-0.13.1 → withcache-0.13.2}/tests/test_withcache.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: withcache
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.2
|
|
4
4
|
Summary: Operator-curated, URL-keyed artifact cache for a small lab (CUDA/ROCm/DOCA/firmware)
|
|
5
5
|
Project-URL: Homepage, https://github.com/safl/withcache
|
|
6
6
|
Author-email: "Simon A. F. Lund" <safl@safl.dk>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
.name = .withcache_shim,
|
|
3
3
|
// Zig requires a literal here; keep it in lockstep with the project's
|
|
4
4
|
// single source (src/withcache/__init__.py) via `make bump` / `make version-check`.
|
|
5
|
-
.version = "0.13.
|
|
5
|
+
.version = "0.13.2",
|
|
6
6
|
.fingerprint = 0xd7d96c5ed212ccaa,
|
|
7
7
|
.minimum_zig_version = "0.16.0",
|
|
8
8
|
.paths = .{
|
|
@@ -22,6 +22,6 @@ inherit the framework floor.
|
|
|
22
22
|
from . import oras
|
|
23
23
|
from .client import blob_url, cache_base, is_cached, serve_url
|
|
24
24
|
|
|
25
|
-
__version__ = "0.13.
|
|
25
|
+
__version__ = "0.13.2"
|
|
26
26
|
|
|
27
27
|
__all__ = ["__version__", "blob_url", "cache_base", "is_cached", "oras", "serve_url"]
|
|
@@ -256,9 +256,19 @@ def register_api_routes(app: FastAPI) -> None:
|
|
|
256
256
|
"""Insert one catalog entry.
|
|
257
257
|
|
|
258
258
|
Body: ``{"name": "...", "src": "...", "format?", "arch?",
|
|
259
|
-
"sha256?", "size_bytes?", "resolved_src?", "description?"
|
|
260
|
-
Only ``src`` is required; every other
|
|
261
|
-
gets persisted through the
|
|
259
|
+
"sha256?", "size_bytes?", "resolved_src?", "description?",
|
|
260
|
+
"netboot_ref?"}``. Only ``src`` is required; every other
|
|
261
|
+
field is optional and gets persisted through the
|
|
262
|
+
``catalog.toml`` round-trip.
|
|
263
|
+
|
|
264
|
+
``netboot_ref`` names another catalog entry (by ``name``)
|
|
265
|
+
whose bytes are a nosi netboot bundle (vmlinuz + initrd +
|
|
266
|
+
manifest) that nbdmux extracts at warm time so bty can
|
|
267
|
+
ramboot the image using its own kernel. Present iff the
|
|
268
|
+
entry is a disk image that has a matching netboot bundle;
|
|
269
|
+
the bundle entry itself never carries a ``netboot_ref``.
|
|
270
|
+
Withcache does not validate that the referenced entry
|
|
271
|
+
exists -- the sibling may be added in either order.
|
|
262
272
|
|
|
263
273
|
409 when an entry with the same ``name`` already exists;
|
|
264
274
|
rejecting on duplicate name (not src) because the display
|
|
@@ -278,6 +288,7 @@ def register_api_routes(app: FastAPI) -> None:
|
|
|
278
288
|
"sha256",
|
|
279
289
|
"size_bytes",
|
|
280
290
|
"description",
|
|
291
|
+
"netboot_ref",
|
|
281
292
|
}
|
|
282
293
|
if not isinstance(body, dict):
|
|
283
294
|
raise HTTPException(status_code=400, detail="body must be a JSON object")
|
|
@@ -221,7 +221,10 @@ def add_catalog_entry(
|
|
|
221
221
|
|
|
222
222
|
``entry`` must carry at least ``name`` + ``src``. Optional
|
|
223
223
|
fields: ``format``, ``arch``, ``sha256``, ``size_bytes``,
|
|
224
|
-
``resolved_src``, ``description
|
|
224
|
+
``resolved_src``, ``description``, ``netboot_ref`` (name of
|
|
225
|
+
a sibling entry carrying the matching nosi netboot bundle;
|
|
226
|
+
consumed by nbdmux to serve vmlinuz + initrd alongside the
|
|
227
|
+
disk-image export).
|
|
225
228
|
|
|
226
229
|
Raises :class:`WithcacheError` on any HTTP failure (409 if the
|
|
227
230
|
entry name already exists; 401 if auth is enabled and no valid
|
|
@@ -147,18 +147,31 @@ def _serialise_catalog(entries: list[dict[str, Any]]) -> bytes:
|
|
|
147
147
|
row can't smuggle arbitrary TOML through.
|
|
148
148
|
|
|
149
149
|
Scalar keys emitted: ``name``, ``src``, ``resolved_src``,
|
|
150
|
-
``format``, ``arch``, ``sha256``, ``description
|
|
151
|
-
``size_bytes``. ``resolved_src`` is
|
|
152
|
-
(for ``oras://`` refs; equal to
|
|
153
|
-
bty needs it to render iPXE flash
|
|
154
|
-
URL directly. ``description`` is
|
|
155
|
-
the /ui/images page has something
|
|
156
|
-
display.
|
|
150
|
+
``format``, ``arch``, ``sha256``, ``description``,
|
|
151
|
+
``netboot_ref``. Integer: ``size_bytes``. ``resolved_src`` is
|
|
152
|
+
the canonical fetch URL (for ``oras://`` refs; equal to
|
|
153
|
+
``src`` for plain HTTPS); bty needs it to render iPXE flash
|
|
154
|
+
chains against the byte URL directly. ``description`` is
|
|
155
|
+
operator-supplied prose so the /ui/images page has something
|
|
156
|
+
better than the URL to display. ``netboot_ref`` names a
|
|
157
|
+
sibling catalog entry carrying the matching nosi netboot
|
|
158
|
+
bundle (kernel + initrd) so nbdmux can pair the disk image
|
|
159
|
+
with its own kernel at warm time; see the ``add_catalog_entry``
|
|
160
|
+
docstring in ``_api.py`` for the pairing story.
|
|
157
161
|
"""
|
|
158
162
|
out: list[str] = ["version = 1", ""]
|
|
159
163
|
for e in entries:
|
|
160
164
|
out.append("[[images]]")
|
|
161
|
-
for key in (
|
|
165
|
+
for key in (
|
|
166
|
+
"name",
|
|
167
|
+
"src",
|
|
168
|
+
"resolved_src",
|
|
169
|
+
"format",
|
|
170
|
+
"arch",
|
|
171
|
+
"sha256",
|
|
172
|
+
"description",
|
|
173
|
+
"netboot_ref",
|
|
174
|
+
):
|
|
162
175
|
val = e.get(key)
|
|
163
176
|
if val is None or val == "":
|
|
164
177
|
continue
|
|
@@ -167,12 +167,28 @@ class AddCatalogEntryTests(_CatalogApiBase):
|
|
|
167
167
|
"sha256": "b" * 64,
|
|
168
168
|
"size_bytes": 2048,
|
|
169
169
|
"description": "Debian sysdev",
|
|
170
|
+
"netboot_ref": "debian-netboot",
|
|
170
171
|
},
|
|
171
172
|
)
|
|
172
173
|
self.assertEqual(r.status_code, 201, r.text)
|
|
173
174
|
stored = self.catalog.entries[0]
|
|
174
175
|
self.assertEqual(stored["description"], "Debian sysdev")
|
|
175
176
|
self.assertEqual(stored["resolved_src"], "https://example/debian.img.gz")
|
|
177
|
+
self.assertEqual(stored["netboot_ref"], "debian-netboot")
|
|
178
|
+
|
|
179
|
+
def test_netboot_ref_persists_through_toml_round_trip(self) -> None:
|
|
180
|
+
"""netboot_ref must survive the catalog.toml write-then-reload."""
|
|
181
|
+
self.client.post(
|
|
182
|
+
"/catalog/entries",
|
|
183
|
+
json={
|
|
184
|
+
"name": "debian",
|
|
185
|
+
"src": "https://example/debian.img.gz",
|
|
186
|
+
"netboot_ref": "debian-netboot",
|
|
187
|
+
},
|
|
188
|
+
)
|
|
189
|
+
toml_path = os.path.join(self._tmpdir, "catalog.toml")
|
|
190
|
+
content = open(toml_path, encoding="utf-8").read()
|
|
191
|
+
self.assertIn('netboot_ref = "debian-netboot"', content)
|
|
176
192
|
|
|
177
193
|
def test_add_persists_to_disk(self) -> None:
|
|
178
194
|
self.client.post(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|