Everything up to now stopped at composing a declaration. That proves the control plane and the host agree, and proves nothing about whether the thing described works — which is how five modules sat pinned to images that did not exist while parsing and resolving perfectly. The forge is the right one to run first. It needs a database from another module, a password it did not choose, and a connection string it could not have written itself: the address and port come from what the database serves, the user name from what the mesh decided both ends would call it. If any of that is wrong it cannot start, and nothing else in this suite would notice. The test checks the chain in the order it has to happen — the login exists, the database it owns exists, the forge answers, and its log does not say authentication failed. That last one matters: a forge that started and could not reach its database would still answer on its port. Rewriting image references is now shared rather than copied from the bundle, which had the same problem first. A digest is not knowable until something is built, and when it is, it belongs to whichever registry served it — so the text says which image and the scenario says which copy. Matching is on the repository, with a test that a repository ending in another one is not half-replaced. Also makes the planning test put the machine back. Tests here share one mesh, so the five modules it assigned were inherited by whatever ran next; harmless while nothing pushed, and not harmless now.
50 lines
2.1 KiB
YAML
50 lines
2.1 KiB
YAML
# Two machines, one mesh.
|
|
#
|
|
# The first raises everything from the bundle its host carries and joins the mesh it made. The
|
|
# second is an ordinary node: it has a host and nothing else, and a person carries it a token.
|
|
#
|
|
# This is the first scenario where the mesh is a mesh. Everything before it proved a machine could
|
|
# talk to a control plane on its own loopback, which proves less than it looks.
|
|
scenario: two-nodes
|
|
|
|
segments:
|
|
hosting:
|
|
kind: public
|
|
cidr: [192.0.2.0/24]
|
|
|
|
machines:
|
|
anchor:
|
|
at: { segment: hosting, address: [192.0.2.10] }
|
|
inbound: allow
|
|
laptop:
|
|
at: { segment: hosting, address: [192.0.2.20] }
|
|
inbound: allow
|
|
|
|
images:
|
|
- postgres:17-alpine
|
|
- cloudamqp/lavinmq:latest
|
|
- mesh-control:development
|
|
# So a module can mirror one into a registry of the mesh's own. The scenario's registry serves
|
|
# what the mesh's registry is built from — the same chicken-and-egg the bootstrap has, resolved
|
|
# the same way.
|
|
- registry:2
|
|
# A real third-party workload, for adopting one the way the conversion will. Its database is
|
|
# the substrate's postgres image rather than its own: what is under test is the mesh delivering
|
|
# a module, not which postgres it delivers.
|
|
- ghcr.io/umami-software/umami:postgresql-latest
|
|
# And the builder, because it is a module the mesh assigns rather than a program somebody
|
|
# starts by hand — which is the only way its credential can be one the mesh delivered.
|
|
- mesh-builder:development
|
|
# And the provisioner, which is what makes a sealed credential true on a machine — the mesh
|
|
# discarded the plaintext and cannot tell a database to start accepting it.
|
|
- mesh-provision-postgres:development
|
|
# And the proxy, which is what turns a route grant into traffic actually arriving.
|
|
- mesh-route-proxy:development
|
|
# And a forge, so one of the real module descriptions can be started rather than only planned.
|
|
# It is the first of them to run: it needs a database from another module, a credential it did
|
|
# not choose, and a connection string it could not have written itself.
|
|
- gitea/gitea:1.22
|
|
|
|
place:
|
|
all: [host, runtime]
|