A module can be given a bucket: the provisioner that makes a secret true
Phase 1.1 of the work breakdown. The finding that shaped it came before any code: **the control plane special-cases nothing.** provides, requires, contributes and grants are entirely name-agnostic, so asking for a bucket needed no change to the mesh at all — only a provider that answers. What was missing was the last step, where something on the machine turns a delivered secret into a key that works. Named `s3-bucket` by ADR 0027's test: a consumer's code is written against the S3 API, and swapping one store for another does not break it, so the coupling is to the protocol rather than the product — which is what the substrate design already said about AMQP, S3 and OCI. Proven on a real store, 7 assertions: a generated secret becomes a working key; rotation makes the new one work and the old one stop; a consumer that goes away loses its key; a key nobody here made is left alone; a manifest naming a credential that was never written is refused; an unusable bucket name is refused naming the consumer that asked. **And the one a database does not need.** One PostgreSQL server holds separate databases and the product enforces the boundary; one object store holds every bucket behind one endpoint, so a consumer being unable to reach another's is a policy somebody wrote. A policy granting arn:aws:s3:::* would pass every other test in the file, so the unit tests assert what the policy does NOT say. It drives the vendor's command line rather than an SDK: the admin API encrypts its request bodies, which is why a separate admin library exists, and pulling that in would add a system-metrics dependency tree to a repository with none in order to create a user.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# The bucket provisioner, as a module ships one.
|
||||
#
|
||||
# Built here so a machine can be given it by the mesh rather than by somebody putting a binary on
|
||||
# it.
|
||||
#
|
||||
# **Not FROM scratch, unlike the postgres one, and the difference is the point.** This drives the
|
||||
# store's own command line, so that client has to be in the image — a provisioner is allowed to
|
||||
# know how to operate the thing it provisions.
|
||||
#
|
||||
# The client is copied from the vendor's own image rather than installed from a distribution:
|
||||
# `apk add mc` on Alpine installs Midnight Commander, which is a different program with the same
|
||||
# name, and the failure would be a provisioner that starts cleanly and cannot do anything.
|
||||
FROM golang:1.25-alpine AS build
|
||||
WORKDIR /src
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 go build -trimpath -ldflags '-s -w' \
|
||||
-o /mesh-provision-objectstore ./examples/objectstore-provisioner
|
||||
|
||||
# Pinned like everything else the mesh runs (novox/hq ADR 0006): a tag moves and a digest does not.
|
||||
FROM minio/mc:latest AS client
|
||||
|
||||
FROM alpine:3.21
|
||||
RUN apk add --no-cache ca-certificates
|
||||
COPY --from=client /usr/bin/mc /usr/bin/mc
|
||||
COPY --from=build /mesh-provision-objectstore /mesh-provision-objectstore
|
||||
# Watching by default, because that is what makes it a module: an ordinary long-running service
|
||||
# the host supervises, rather than something invoked after every declaration.
|
||||
ENTRYPOINT ["/mesh-provision-objectstore", "--watch"]
|
||||
Reference in New Issue
Block a user