feat(runtime)!: put everything Onebox places on a host under onebox - #206
Merged
Merged
Conversation
Containers Onebox runs from its own images now share the onebox-* namespace with the host proxy and carry no replica ordinal, since none of them has replicas: managed services are onebox-<service> and restore drills onebox-<service>-restore. Workload containers keep <app>-<component>-<replica>. Volumes, Compose projects and networks keep the application because they hold its data. Reserve the application name onebox and the service names proxy and discovery, which would otherwise derive names inside that namespace or the host proxy's own container names. Replace comments that justified naming by two applications sharing a host, which Onebox does not allow. Closes #205 BREAKING CHANGE: managed service containers are renamed from <app>-<service>-1 to onebox-<service>, and restore drill containers from <app>-<service>-restore-1 to onebox-<service>-restore. The next deploy recreates each managed service container; data volumes are unchanged.
Host-scoped resources Onebox runs now share one prefix: the ingress network is onebox-ingress, alongside onebox-proxy, onebox-discovery and managed service containers. Application names may no longer begin with onebox-, which replaces the single onebox-proxy reservation and keeps an application's derived names out of that namespace. Document that derived names do not carry the environment, and that the host owner record is what separates staging from production. Reword the proxy lock-order comment that implied several applications per host. BREAKING CHANGE: the default proxy network changes from ob-ingress to onebox-ingress, and application names beginning with onebox- are refused. The next proxy apply creates onebox-ingress and the next deploy moves routed workloads onto it; routing is interrupted in between. The old ob-ingress network is left in place and can be removed with `docker network rm ob-ingress` once nothing is attached.
Volumes, service Compose projects, the service network and restore-drill resources move from ob_<app>_... to onebox_<app>_..., so every name Onebox derives outside the author's workload containers begins with onebox. The derived-name length check now measures the real derived names. There is no migration and no fallback. Add a guide that lists the renamed resources, what the next deploy does to a host that still holds ob_ volumes, and the manual steps to copy the data across before deploying. BREAKING CHANGE: volumes are renamed from ob_<app>_... to onebox_<app>_..., and Onebox does not migrate them. Deploying to an existing host without following guides/upgrade-to-onebox-names starts unprotected services on new, empty volumes, and refuses protected PostgreSQL services because their recorded data volume is missing. The old volumes stay on the host untouched.
Volumes, service Compose projects, the service network and restore-drill resources no longer carry the application: onebox_postgres_data, onebox_web_uploads, onebox_postgres, onebox_services. A host has one application, the ob.app label records which, and ob destroy releases the host only after removing these resources, so the application in the name distinguished nothing. Reserve the service name services, whose Compose project would derive the service network's name. BREAKING CHANGE: volumes are renamed from ob_<app>_<component>_<volume> to onebox_<component>_<volume>, the service network from ob_<app> to onebox_services, and service projects from ob_<app>_<service> to onebox_<service>. There is no migration; guides/upgrade-to-onebox-names gives the manual steps.
Finish putting everything Onebox places on a host in the onebox namespace, without the application's name: - State lives in <basePath>/app, and the default basePath is /var/lib/onebox. The host journal keeps its own directory. - Scheduled job units are onebox-job-<job>; backup units are onebox-backup-<environment>-<service>-<operation>. - Proxy routers and services are onebox_<workload>[_r<n>]; custom Traefik objects may not begin with onebox_. - Ownership and runtime labels move from ob.* to onebox.*, and the compose_ob_label error code becomes compose_onebox_label. - The ob- application-name rule and the ob reservation are gone; nothing derives an ob- name any more. Remove every compatibility path: the pre-2026.8.6 unit and credential spellings and their migration, unit ownership recovered from unit bodies, unlabelled networks adopted from Compose labels or service state, host owner records without an environment, the v1alpha1 secret checkpoint, the short-option schedule lock rendezvous, the old discovery container name, and unlabelled compose-run job containers. An engine built without an environment now takes the one its resolved project was resolved for. The legacy backup repository layout stays readable: removing it would make existing backups unrestorable. BREAKING CHANGE: state moves from /var/lib/ob/<app> to /var/lib/onebox/app, labels from ob.* to onebox.*, units from ob-<app>-* and ob-backup-<app>-* to onebox-job-* and onebox-backup-*, and owner records must name an environment. There is no migration; guides/upgrade-to-onebox-names gives the manual steps.
- Reserve the service name ingress, whose container would take the ingress network's onebox-ingress name. - Refuse to claim a host without an environment, which would write an owner record no command can read. - Strip only onebox- networks on eject; ob- is an author's name again. - Give the host journal its own directory instead of treating the application name _host as a sentinel in AppDir. - Name the onebox. label namespace in the compose_onebox_label message. - Remove distinctNames and ownedNames' unused parameters. In the upgrade guide, remove old units under both spellings of a hyphenated application name, give copied volumes the Compose project and volume labels so ob destroy --volumes still finds them, and remove only the old networks that exist.
A Compose file that runs its own proxy beside the workloads makes Compose create <app>_default before Onebox does, labelled with the application's project but not with onebox.app, and Docker cannot add a label to it afterwards. Removing that evidence as legacy made bootstrap refuse every such host, including fresh ones: the Docker end-to-end suite failed with "network obe2e_default exists without Onebox ownership". Accept the Compose project label again, for the application network only, in both the engine and preflight. It proves nothing for the service network or any other name.
Only the command, the project file and the artifacts an operator passes between commands keep the ob prefix. Every other name Onebox creates now begins with onebox: the onebox-run journal identifier, the onebox-wal-g wrapper, .onebox-schedule.lease, .onebox-secret-generations, .onebox-decrypted-* and .onebox-external-* files, /tmp/onebox-drain, onebox.snapshot.yml, .onebox-tmp and .onebox-bak, fence and lock-loss markers, and local temporary directories. Document the rule and its separators in the naming reference, and add a test that fails when a string literal introduces any other ob-, ob_ or ob. name. BREAKING CHANGE: host-side files, markers and the journal identifier are renamed without migration; guides/upgrade-to-onebox-names lists them. Workload containers from an earlier release watch /tmp/ob-drain, so they must be replaced as the guide describes.
- Schedule and backup reconciliation read each unit's owner from its Description and never remove or overwrite another application's unit. One owner record per basePath means a second application can share a host, and a name alone was trusted to be ours. - Backup units drop the environment: onebox-backup-<service>-<op>. - Scheduled runs label their container onebox.execution.job, so the durable runner can reclaim one a crash left behind. - Journal functions take a directory. The host journal is read, written and pruned in the same place, and deploy prunes it. - One rule decides that Compose created the application network, shared by the engine and preflight. - The namespace guard catches bare ob- prefixes and scans e2e, whose destroy probes and durable fixture now use the current names.
The host owner record lived under basePath, so an application with a different basePath got its own record and could claim a host another application already owned. Every name this branch stopped qualifying with the application relied on one application per host, and each shared namespace needed its own patch. Host state — the owner record, host lock, host journal and proxy — now lives at /var/lib/onebox/_host whatever basePath says. That restores the invariant everywhere, so reconciliation no longer parses unit Descriptions for ownership; that check also failed open when a unit file could not be read. ONEBOX_TEST_HOST_STATE_DIR relocates host state for test suites that cannot write /var/lib, or that run several fixture applications against one machine. It is not a supported setting. Also: - The host journal is pruned after proxy apply, the only place that writes it, rather than on every deploy. Names.HostJournalDir is its one spelling. - The derived-name length check measures every name All derives, with escaped hyphens, ordinals and restore suffixes. - matchesRuntimePrefix and Names.BackupTimer are gone.
- The state directory is <basePath>/app, a generic name under a path the operator chose. Bootstrap marks it with .onebox-app and refuses to adopt a non-empty one without the marker; destroy deletes nothing without it, so an unrelated /srv/app survives basePath: /srv. - Preflight checks that the fixed host state directory is writable, not just basePath. - The host journal is pruned after every proxy check, which is what writes it, and pruning is best-effort: it never fails an applied proxy. - ob warns whenever ONEBOX_TEST_HOST_STATE_DIR is set, and says when a relative value is ignored. - Drop environment fallbacks that engine.New now makes dead.
- Every lock acquisition claims the state directory and its marker, not only bootstrap, so no command writes lock, fence, journal or release files into a directory Onebox has not marked. - Bootstrap refuses a foreign owner before touching anything, and claims the state directory before the host, so refusing a directory Onebox did not create leaves the host unclaimed. - A destroy that keeps anything keeps the marker, so the later `ob destroy --volumes` can still prove the directory and finish. - An unreadable existing directory counts as not empty. - The host journal ages out by name, in one rm, whatever its files hold, so a torn record no longer stops pruning. - The engine uses app.HostOwnerRecord rather than a second copy of it. - The broken-link remedy no longer points at base_path.
- The .onebox-app marker is written only when missing, through a temporary file and a rename, so an interrupted write never leaves the ownership proof empty and the host locked out. - Bootstrap reads the owner once, refuses a conflict, checks the state directory without changing it, claims the host, and only then lets the lock create the directory: a refused bootstrap leaves nothing behind. - One ownerConflict comparison serves bootstrap, the locked claim and RequireHostOwner. - replicas is capped at 100, in the loader and the schema, so a typo can no longer make loading a project build millions of names. - The test host state override is set explicitly with app.SetTestHostStateDir; only the ob command reads its environment variable, and warns when it does. - Host journal pruning is one remote command. - Stale /var/lib/ob/<app> comments are corrected, and the unreachable _host application-name reservation is removed.
Write .onebox-app before creating releases/, through a per-claim staging file, so an interrupted first claim never strands a non-empty unmarked directory and two concurrent claims cannot race on one staging path. Also write the marker in the Linux-only pinned-schedule lock test, which builds its state directory by hand.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #205.
What changes
Everything Onebox places on a host is named
onebox, and nothing it runs for the author carries the application's name. A host has one application, theonebox.applabel records which, andob destroyreleases the host only after removing Onebox's resources./var/lib/ob/shop/var/lib/onebox/app/var/lib/ob/_host/var/lib/onebox/_hostob.app,ob.workload, …onebox.app,onebox.workload, …shop-postgres-1onebox-postgresshop-postgres-restore-1onebox-postgres-restoreob_shop_postgres_dataonebox_postgres_dataob_shop_postgresonebox_postgresob_shoponebox_servicesob-ingressonebox-ingressob-shop-nightlyonebox-job-nightlyob-backup-shop-production-…onebox-backup-production-…shop_web_r0onebox_web_r0shop-web-1,shop_defaultKept on purpose: the S3 backup prefix (
<prefix>/shop_postgres, since a bucket may be shared) and the database name inside PostgreSQL.The rule going forward
obis kept only for the command, the project file and the artifacts an operator passes between commands (ob-plan.json,ob-approval.json, …). Every other name begins withonebox, including theonebox-runjournal identifier,onebox-wal-g,.onebox-*files,/tmp/onebox-drain,onebox.snapshot.ymland internal markers. The separator shows the kind of name:onebox-for named things,onebox_for joined names,onebox.for labels.The naming reference documents the rule.
internal/app/namespace_test.gofails the build when a string literal introduces any otherob-,ob_orob.name.Reservations
oneboxandonebox-*. Theob-rule and theobreservation are gone, because nothing derives anob-name any more.proxy,discovery,services.onebox_.Compatibility code removed
The legacy backup repository layout stays readable, because removing it would make existing backups unrestorable.
Other fixes
Upgrade: no migration, no fallback
See the new guide Upgrade to onebox names. Without it, commands see an unowned host, deploys are refused because
shop-web-1andshop_defaultcarry the old label, unprotected services would start empty, and old timers keep firing. The guide covers:ob bootstrapandob deploy.Releases from before the upgrade must not be rolled back to.
The unit suites and the Docker end-to-end suite pass locally. The server end-to-end suites were not run.