70 lines
3.7 KiB
Markdown
70 lines
3.7 KiB
Markdown
---
|
|
status: resolved
|
|
opened: 2026-09-14
|
|
located-in: [mesh-controller internal/builder (upstream artifacts)]
|
|
fixed-by: ADR 0096; mesh-controller multiple-fixes (the builder copies the index and its manifests between registries over the registry API); proven by a test against a fake upstream serving an index over two platforms
|
|
amended-design: 03-DESIGN/01-to-be/18-building-a-module.md
|
|
---
|
|
|
|
# 046 — An upstream image cannot be mirrored into the mesh's own registry
|
|
|
|
## Symptom
|
|
|
|
A module may declare that one of its artifacts is an image published elsewhere, to be copied into
|
|
the mesh's own registry so machines fetch it by a digest this mesh assigned rather than by a name
|
|
somebody else controls. Asking for such a module fails:
|
|
|
|
```
|
|
docker push <registry>/<module>/<artifact>: exit status 1
|
|
image with reference …:latest was found but does not provide any platform
|
|
```
|
|
|
|
Nothing reaches the registry — its log has no entry for the attempt at all.
|
|
|
|
## Why this matters
|
|
|
|
**It is the only way a third-party image becomes the mesh's own.** Everything else a module can do
|
|
with an image names it where it lives, so every machine fetches it from the internet, separately,
|
|
for ever, and by whatever that name points at on the day it asks. Mirroring is what makes an image
|
|
a thing the mesh holds and can speak about — and it is the shape most of a migration would want,
|
|
because the services being moved are overwhelmingly third-party.
|
|
|
|
Today exactly one module uses it, so nothing is broken that was working. That is also why it went
|
|
unnoticed.
|
|
|
|
## What was established
|
|
|
|
Each of these was tried and observed, not assumed:
|
|
|
|
- The image named is an **index over several architectures**, which is what a published image
|
|
ordinarily is and what a module sensibly writes down.
|
|
- Fetching it leaves *the index* in the runtime's store. Asking about it reports a resolved
|
|
operating system and architecture while still holding the index, so inspecting it looks fine.
|
|
- **Asking for a platform at fetch time does not help.** The store still holds the index.
|
|
- **Resolving the index first does not help either.** The runtime will name the one manifest for
|
|
this architecture, and fetching *that digest specifically* still leaves something the registry
|
|
refuses, with the same message.
|
|
- **Nor does naming the platform at push time.** The message changes to `does not provide the
|
|
specified platform (linux/amd64)` — for the platform that was just fetched by its own digest.
|
|
- The tooling that exists to copy images between registries without any of this is not present on
|
|
the machine, and the runtime's own suggestion — push one platform — is the thing that fails.
|
|
|
|
A speculative fix along those lines was written, tested, and **reverted**: it did not make the
|
|
mirror work, and leaving machinery that resolves indexes without achieving what it was added for
|
|
would be complexity plus a comment claiming something untrue.
|
|
|
|
## How it would be checked
|
|
|
|
A module declaring an upstream artifact is asked for, and the mesh's registry serves what it named
|
|
under the module's own repository. Today that check fails at the push, which is where it should
|
|
be checked from: the registry either serves it or it does not.
|
|
|
|
## Open questions
|
|
|
|
- Is copying between registries the right shape here, rather than going through a machine's image
|
|
store at all? A copy never needs a platform, because it moves what is there.
|
|
- Should the mesh mirror an index or a platform? Every machine on one mesh being the same
|
|
architecture is an assumption that holds today and is not stated anywhere.
|
|
- Is this the runtime's newer image store specifically? Worth knowing before working around it,
|
|
because a workaround for a behaviour that is itself a bug is a thing nobody removes later.
|