Documentation
¶
Overview ¶
Package deploy runs a described application on a target and says what it saw: the app contract, the driver contract every target kind implements, and the drivers themselves in the packages under this one. It keeps no records and knows nothing of AppTown; whoever calls it hands it a Placement and a Source and keeps the Observation that comes back. The records of what is deployed where, and their settlement, belong to internal/apptown/deployment, which calls this package.
Index ¶
- Constants
- Variables
- func ComposeLiteral(s string) string
- func ComposeRead(s string) string
- func ConfigHash(configJSON string) string
- func HostKey(id ids.ID) string
- func IntranetCompose(st IntranetStack) string
- func IsTerminal(err error) bool
- func NormalizeHostname(raw string) (string, error)
- func PreparedReleaseApp(c *appcontract.Plan, image string) (*appcontract.Plan, error)
- func RefuseNeedSecretCollisions(plan *appcontract.Plan, needNames []string, secrets ConsumerSecrets) error
- func Refused(err error) bool
- func Terminal(err error) error
- type Artifact
- type BucketData
- type Checkpoint
- type Connection
- type ConsumerSecrets
- type Controls
- type DockerIdentity
- type Driver
- type FleetObserver
- type Gate
- type HostLabel
- type Ingress
- type Inspector
- type IntranetNeed
- type IntranetStack
- type Inventorier
- type Left
- type Logf
- type ManagedData
- type NativeBackup
- type NeedBinding
- type NeedBindings
- type NeedFulfiller
- type NeedRecorder
- type Observation
- type Owned
- type Owner
- type Placement
- type Preflighter
- type PreviewSource
- type Renderer
- type Resource
- type ResourceFitter
- type ResourceHost
- type RetainedNote
- type RunningRecord
- type SelectedSource
- type ServiceSpec
- type SizePricer
- type Source
- type SourceTree
- type StorageBinding
- type StorageBindings
- type StorageCopy
- type StorageRestore
- type TakeDown
- type TakenDown
Constants ¶
const ( RecordRecorded = "recorded" // the records say it is there RecordUnrecorded = "unrecorded" // the provider has it, the records do not RecordMissing = "missing" // the records have it, the provider does not )
The three things a caller can say about a resource's record.
const ( GateEnvUpstream = "GATE_UPSTREAM" GateEnvSecret = "GATE_SECRET" GateEnvAppTown = "GATE_APPTOWN" GateEnvListen = "GATE_LISTEN" // GateEnvMarker carries Gate.Marker in the gate's environment; the gate // does not read it. GateEnvMarker = "APPTOWN_GATED_DEPLOYMENT" // GatePort is the port the gate listens on. GatePort = 8080 // GateProbeHeader carries the gate secret on AppTown's own checks. GateProbeHeader = "AppTown-Restore-Token" )
Gate environment, as the gate (cmd/apptown-gate) reads it.
const TagConfirmsOnly = "confirms-only"
TagConfirmsOnly marks a provider item reported only so a record can be confirmed: something AppTown did not name (an approved older volume) that is no orphan of AppTown's when nothing records it.
Variables ¶
var ErrNoInventory = errors.New("this kind of target doesn't report what it holds")
ErrNoInventory is a target whose kind has no inventory reader: what it holds is unknown, which is neither an error nor empty.
Functions ¶
func ComposeLiteral ¶
ComposeLiteral is s written so that Compose reads it back unchanged. Compose interpolates every value in a compose file: $NAME and ${NAME} are replaced from the environment of whoever runs Compose (on Portainer, variables AppTown never sets, so they read as empty), and $$ is a literal $. AppTown never relies on that: a value it writes (a secret, a contract's environment, a start script's shell variables) means what it says, as with docker run -e on a Docker host. So each $ is $$.
func ComposeRead ¶
ComposeRead is what Compose reads from a value AppTown wrote with ComposeLiteral: each $$ is one $.
func ConfigHash ¶
ConfigHash hashes a JSON document in its one canonical spelling, so a hash made over Go's sorted, compact form matches jsonb's spacing and key order. Anything that is not JSON hashes as is.
func HostKey ¶
HostKey is a deployment's key on a host or a provider: the last 12 hex digits of its id, the random tail of a UUIDv7. A unique index on deployments makes it unique within an AppTown (migration 162), so every name made from it is too.
func IntranetCompose ¶
func IntranetCompose(st IntranetStack) string
IntranetCompose renders the stack file. Label conventions follow the usual Portainer-with-Traefik stack layout: host-network Traefik discovers containers via the docker provider, so no shared network is declared; the wildcard cert domain is shared by every app router. Ordering is the one main uses: needs come up healthy, init steps run to completion, then the app — expressed as compose depends_on conditions so the platform enforces it, not a sleep.
func IsTerminal ¶
func NormalizeHostname ¶
NormalizeHostname returns an exact DNS reservation key. Internal single-label names and ASCII/punycode are supported; URL syntax, IP literals and wildcard reservations are not. DNS provisioning remains the caller's responsibility.
func PreparedReleaseApp ¶
func PreparedReleaseApp(c *appcontract.Plan, image string) (*appcontract.Plan, error)
func RefuseNeedSecretCollisions ¶
func RefuseNeedSecretCollisions(plan *appcontract.Plan, needNames []string, secrets ConsumerSecrets) error
RefuseNeedSecretCollisions keeps one authority for each consumer variable. Equal values do not establish common ownership: either source may rotate. The selected plan determines consumers; ordinary environment placeholders remain lower precedence and are not scoped secret declarations.
func Refused ¶
Refused reports whether a provider definitely refused a request: it answered and said no (a terminal rejection, or an answer that says the request itself was refused), so the effect did not happen. Anything else (a timeout, a lost connection, a server error) leaves whether the effect happened unknown, and a caller must say so rather than report a failure.
Types ¶
type Artifact ¶
type Artifact struct {
Kind string // compose | do-app-spec | docker-source | ...
Body []byte
Hash string
// Source is the selected software the artifact was rendered from, for
// drivers that build from source on the host (the built-in Docker
// host). Never serialized: the receipt carries Body and Hash, and a
// staged workspace belongs to one execution.
Source *Source
}
Artifact is a renderer's output: canonical bytes whose hash can sit in a receipt, carrying secret references and never values.
type BucketData ¶
type BucketData interface {
BucketConnection(ctx context.Context, bucket string) (Connection, error)
TearDownStorage(ctx context.Context, p Placement, td TakeDown) TakenDown
}
BucketData is what AppTown asks of a provider about a deployment's object storage bucket to protect its objects (design/subsystems/ deployment.md, "Protecting data off-host"): the connection the deployment's own key for that bucket gives, read at use time and never recorded, and the teardown of the bucket and its key as a step of its own, so a take-down can stop the app, copy the bucket as the app's key, and only then delete it.
type Checkpoint ¶
Checkpoint durably records provider identities before execution can proceed. Implementations reject stale ownership and conflicting identity updates.
type Connection ¶
type Connection struct {
Host string
Port int
Database string
User string
Password string
SSLMode string
}
Connection is how a copy job reaches one database as the app's user. The password goes into the job's environment and nowhere else.
type ConsumerSecrets ¶
ConsumerSecrets is the resolved secrets per consumer (secrets.md §6): a part's name, or "init-<name>".
type Controls ¶
Controls says what the target owns: when it controls liveness the health controller steps back; when it controls rollout AppTown waits on it rather than probing containers itself.
type DockerIdentity ¶
type DockerIdentity struct {
Deployment HostLabel `json:"deployment"`
Generation int64 `json:"generation"`
Artifact string `json:"artifact"`
}
DockerIdentity names what a Docker deployment's container was admitted for: the deployment, the generation and the artifact hash. The label keys are external resource identifiers; existing containers retain them.
func (DockerIdentity) Checkpoint ¶
func (id DockerIdentity) Checkpoint(name string) map[string]any
func (DockerIdentity) Labels ¶
func (id DockerIdentity) Labels() map[string]string
type Driver ¶
type Driver interface {
// Reconcile brings the deployment to the artifact as the given
// generation. The same idempotency key is the same attempt; checkpoint
// records the provider's identifiers on the attempt as soon as they
// exist, so recovery can use them.
Reconcile(ctx context.Context, p Placement, generation int64, art Artifact, key string, log Logf, checkpoint Checkpoint) (Observation, error)
// Resume picks up an attempt AppTown was interrupted in: given what
// was noted, find out what the target did and finish the attempt,
// active, failed, or honestly unknown.
Resume(ctx context.Context, p Placement, generation int64, noted map[string]any, log Logf) (Observation, error)
Observe(ctx context.Context, p Placement) (Observation, error)
// Teardown removes exactly the recorded generation's deployment and
// deletes what AppTown recorded creating for it (td.Owned): data
// only when td.BackedUp says a final backup covers it. It never
// deletes what is not on the list. An error means the serving thing
// (container, app, stack, bucket) may still stand; anything else it
// could not delete, and data it keeps, it reports as Left.
Teardown(ctx context.Context, p Placement, generation int64, td TakeDown) (TakenDown, error)
Controls() Controls
}
Driver is the desired-state contract every target kind implements (deployment.md §2.4). The drivers live in the packages under this one and implement it directly; AppTown registers them by kind.
type FleetObserver ¶
type FleetObserver interface {
ObserveAll(ctx context.Context, ps []Placement) ([]Observation, error)
}
FleetObserver is a target's inventory that can observe every listed deployment on the target with one look at the provider, rather than one per deployment. The answer is in the order of ps; an error is the whole look's, and no deployment's state is known from it.
type Gate ¶
type Gate struct {
// Image is the gate's image by digest, published for AppTown.
Image string
// Secret is this deployment's gate secret: the probe token and the
// gate's credential when it redeems a ticket. It is held only in
// memory while AppTown starts the deployment, and is delivered as the
// provider's encrypted secret to the gate alone. Empty when AppTown
// only observes or takes the deployment down, which needs no secret.
Secret string
// AppTown is AppTown's public origin, where the gate redeems tickets.
AppTown string
// Marker is this deployment's own random mark, recorded by AppTown
// before anything is made and rendered into the gate's environment. It
// is what proves an app found on the account by its name is this
// deployment's and not another's of the same name: a take-down deletes
// an app it did not record only when the app carries this mark.
Marker string
}
Gate is AppTown's access gate in front of a deployment. The gate is its only public component; the app's public part runs privately behind it, and nothing else of the app starts. A driver that cannot place a gate refuses a gated placement rather than expose the app.
A gated deployment's observation never asks the front door anonymously (the gate answers that with 404), and never copies the platform's component logs into AppTown's records: they can hold production rows. AppTown's own checks reach the app through the gate with the secret.
type HostLabel ¶
type HostLabel string
HostLabel is the name a deployment carries on its host (the apptown.deployment label, boot proofs): the old integer for a deployment made before the identity cutover, which its containers keep, and its UUID for one made after. It reads a proof written with either a number or a string.
func (*HostLabel) UnmarshalJSON ¶
type Ingress ¶
type Ingress struct {
Hosts []string `json:"hosts"`
URL string `json:"url"`
CertificateDomain string `json:"certificateDomain"`
}
Ingress is the admitted routing input for an artifact. It contains no credentials and is retained with the attempt instead of resolving mutable project or target settings when work is resumed.
type Inspector ¶
Inspector is a driver that can say whether a deployment's container is running as a fact, distinct from not being able to ask: absent is (false, nil); a host that cannot be reached is an error, and a rebuild stops rather than replace what it could not see.
type IntranetNeed ¶
type IntranetNeed struct {
Name string
Image string
Command []string
// Entrypoint replaces the image's entrypoint (a need's start script).
Entrypoint []string
Env map[string]string
Health string // a shell healthcheck (exit 0 = healthy); "" = none
Data string // the emulator's data directory; "" = ephemeral
// Resources is the most the need's service may use; nothing declared
// is no limit.
Resources appcontract.Resources
}
IntranetNeed is one fulfilled need as the stack runs it.
type IntranetStack ¶
type IntranetStack struct {
// Prefix and Base begin the stack's name, router and volume keys
// (portainer.StackNames): apptown- and dep-<key>.
Prefix string
Base string
Hosts []string
Domain string
Image string // the selected public release image
// Command is the app's command; empty runs the image's own.
Command []string
Port int
// Resources is the public part's; each non-public part carries its own.
Resources appcontract.Resources
Env map[string]string // the public part's prepared environment
// Integrations are the project's attached integrations' values for the
// public part, as a Docker host gives them: under its environment and
// secrets.
Integrations map[string]string
// BrowserEnv is a static public part's browser values, the JSON its
// file server answers at /_apptown/env.js ("{}" for none); "" for a
// server app, which is not given them.
BrowserEnv string
Secrets ConsumerSecrets
// PublicPart names the public part, the consumer the app service is.
PublicPart string
DataDir string
Origins string // APPTOWN_ORIGINS: the tiers a browser reaches the app at
// Release is the public part's release identity
// (appcontract.Contract.PublicRelease), APPTOWN_RELEASE, which its file
// server answers at ReleasePath; "" when the public part is not static.
Release string
// Trust is the installer with the extra certificates the app's own
// containers are given (internal/trust: APPTOWN_TRUST, which they run);
// "" for none.
Trust string
Needs []IntranetNeed
Init []appcontract.InitContainer
Parts []appcontract.Part // non-public app parts only
}
IntranetStack is everything the stack file says.
type Inventorier ¶
Inventorier is a driver that can say what its target holds.
type Left ¶
Left is one thing a teardown left at the target: what it is, in words the ledger shows ("image repository"), and the provider's identity of it. Handle carries "name" and, when known, "size"; "kind" names its inventory kind when it is not a database. Data marks what holds data; Why says why it was left (kept: no backup here; or the delete's error).
type ManagedData ¶
type ManagedData interface {
AppConnection(ctx context.Context, instance, database, user string) (Connection, error)
Databases(ctx context.Context, instance string) ([]string, error)
NewDatabase(ctx context.Context, instance, name, owner string) error
DropDatabase(ctx context.Context, instance, name string) error
Backups(ctx context.Context, instance string) ([]NativeBackup, error)
DeleteInstance(ctx context.Context, instance string) error
}
ManagedData is what AppTown asks of a provider's managed data instance (a database cluster) to protect the data in it: the app user's connection, read at use time and never recorded; a new, empty database, made by the provider and never adopted by name; its removal; the provider's own backups, read for recency only; and the instance's deletion. The instance's admin credential stays inside the provider module.
type NativeBackup ¶
NativeBackup is one of the provider's own backups of an instance.
type NeedBinding ¶
type NeedBinding struct {
Env map[string]string // variables the app reads (DATABASE_URL, PG*)
// Secret are variables the app reads whose values are credentials (an
// object store's key secret): delivered as the target's secrets, never
// in a receipt.
Secret map[string]string
Native map[string]any // target-native reference (an App Platform database component)
}
type NeedBindings ¶
type NeedBindings map[string]NeedBinding
NeedBindings is what reconcile hands the renderer: per need, the connection the app should be given, as the target expresses it.
type NeedFulfiller ¶
type NeedFulfiller interface {
FulfilNeed(ctx context.Context, p Placement, need string, params map[string]string, log Logf) (NeedBinding, map[string]any, error)
}
NeedFulfiller is a driver that provisions the contract's needs on its target (App Platform: a managed database) and reports the binding and the provider's handle.
type NeedRecorder ¶
type NeedRecorder interface {
// Recorded is the need's recorded handle (its identity once
// established, else what an earlier fulfilment asked for under
// "requested"); nil when nothing is recorded.
Recorded(ctx context.Context, placementID ids.ID, need string) (map[string]any, error)
RecordIntent(ctx context.Context, placementID ids.ID, need string, requested map[string]any) error
RecordIdentity(ctx context.Context, placementID ids.ID, need string, requested map[string]any, id, name string) error
}
NeedRecorder is where a driver that provisions a need on its target records what it asked for and what it got, by the placement's id.
type Observation ¶
type Observation struct {
// RuntimeToken is an ephemeral probe incarnation (container ID and start
// time, or provider deployment ID). It is never restored from a receipt.
RuntimeToken string `json:"-"`
// ReadinessPolicy comes from the admitted artifact, never a saved observation.
ReadinessPolicy *appcontract.HealthPolicy `json:"-"`
// HealthObservedAt and ArtifactHash identify a fresh exact-release health
// witness. Zero/empty means the provider has supplied no such evidence.
HealthObservedAt time.Time `json:"healthObservedAt,omitempty"`
ArtifactHash string `json:"artifactHash,omitempty"`
ImageDigest string `json:"imageDigest,omitempty"` // Actual image when execution built it from admitted source.
Generation int64 `json:"generation"`
Rollout string `json:"rollout"` // pending | rolling | active | failed | absent
Health string `json:"health"` // healthy | unhealthy | unknown
URL string `json:"url"`
Handle any `json:"handle,omitempty"`
Orphans []string `json:"orphans,omitempty"`
// Running is the provider's own name for what runs, read from the same
// answer as the rest: App Platform's active deployment id, a Portainer
// stack's app image. Empty when the provider named none (nothing
// deployed yet, or the app is gone). After a restore it says whether the
// deployment still runs what AppTown recorded.
Running string `json:"running,omitempty"`
}
Observation records what a provider sees for a deployment generation.
type Owned ¶
type Owned struct {
Kind string `json:"kind"`
ID string `json:"id"`
Name string `json:"name,omitempty"`
Data bool `json:"data,omitempty"`
Need string `json:"need,omitempty"`
}
Owned is one thing AppTown created for a deployment at its target, recorded when the provider confirmed the creation. Only these are ever deleted at take-down: a matching name, label or mount is not evidence AppTown made something. Kind is the provider's word for it (container, network, volume, image, app, stack, bucket); ID is the provider's identity of it, Name a readable one when that differs. Data marks what holds data; Need names the need it serves, if any.
type Owner ¶
Owner records, for one deployment, each thing AppTown creates at its target, as soon as the provider confirms it. A driver that cannot record a creation stops: what is not recorded is never deleted.
type Placement ¶
type Placement struct {
ID ids.ID // the deployment's record identity: need records; opaque to the driver
Label HostLabel // the deployment's name on its host: container labels, boot proofs
Name string // the deployment's name (main, cloud, preview-12)
Generation int64 // the generation last observed
URL string // where it was last reached
Handle map[string]any // the provider's own identifiers
Container string // the built-in host's container, when it has one
HostPort int // the built-in host's port, when it has one
// Gate, when set, puts the deployment behind AppTown's access gate
// (design/subsystems/deployment.md, "Restored copies"): it holds production data
// that only people AppTown admits may reach.
Gate *Gate
}
Placement is a standing deployment as a driver sees it: what it is called and what the provider last said about it. AppTown keeps a record of a deployment; a driver is handed this. Whose it is, the driver never asks: its collaborators were built knowing.
type Preflighter ¶
type Preflighter interface {
Preflight(ctx context.Context, p Placement, src Source, secrets ConsumerSecrets, log Logf) error
}
Preflighter is a driver that can refuse a release before any effect, from a read of the target's own limits (App Platform: whether its container registry has room for the project's repository) or from what the release would send it (App Platform: a value it would rewrite). It changes nothing; a refusal fails the release before its needs are fulfilled or its artifact rendered. A limit it cannot read is not a refusal: the effect that needs the room is still the authority.
type PreviewSource ¶
type PreviewSource struct {
Worktree string
History SelectedSource
Snapshots string
}
PreviewSource keeps the current worktree when it exists, including its edits. Otherwise History is materialized under Snapshots, in a folder of the commit's own: preparing another commit never changes a tree a running preview serves (Retain removes the others once none does). Neither source reads database contract snapshots or borrows files from the repository's current checkout.
func (PreviewSource) Prepare ¶
func (s PreviewSource) Prepare(ctx context.Context) (SourceTree, error)
func (PreviewSource) Retain ¶
func (s PreviewSource) Retain(tree SourceTree) error
Retain removes every snapshot but tree's, once tree is what the preview serves and no container mounts the others.
type Renderer ¶
type Renderer interface {
Render(ctx context.Context, p Placement, src Source, bindings NeedBindings, secrets ConsumerSecrets, log Logf) (Artifact, error)
}
Renderer is a driver that renders the target's artifact from the selected source (App Platform: the app spec with pushed images).
type Resource ¶
type Resource struct {
// ObservedDaemonID belongs to this exact Docker or Portainer inventory snapshot, including cached observations.
ObservedDaemonID string `json:"-"`
Kind string `json:"kind"` // app | database | registry | container | volume | network | image | stack | bucket
Name string `json:"name"`
ID string `json:"id,omitempty"`
Status string `json:"status,omitempty"`
Region string `json:"region,omitempty"`
Size string `json:"size,omitempty"`
Version string `json:"version,omitempty"` // engine + version for a database
URL string `json:"url,omitempty"`
Detail string `json:"detail,omitempty"`
Tags []string `json:"tags,omitempty"`
// What the caller knows about it.
Record string `json:"record"` // RecordRecorded | RecordUnrecorded | RecordMissing
Owner string `json:"owner,omitempty"` // AppTown.owner label: which stack made it
Stack string `json:"stack,omitempty"` // the compose project label: which stack it belongs to
Hosts []ResourceHost `json:"hosts,omitempty"` // the deployments running on / using it
Retained *RetainedNote `json:"retained,omitempty"` // left behind by a torn-down deployment
}
Resource is one thing at a target, in the same words whatever the provider. A driver reports what it sees; the caller lays its records over it.
type ResourceFitter ¶
type ResourceFitter interface {
FitResources(ctx context.Context, c *appcontract.Contract) (map[string]string, error)
}
ResourceFitter is a driver whose target rounds a part's declared resources to sizes of its own (App Platform's instance sizes). Asked before any need is fulfilled or artifact rendered, it answers what each part will run on, in words ("apps-s-1vcpu-1gb (1G, 1 CPU)"), or an error that stops the release before any effect: a declaration no size covers is terminal; sizes that cannot be read are not. A driver that holds a declaration exactly answers no sizes, and may still refuse one larger than its host can give (a Docker host).
type ResourceHost ¶
type ResourceHost struct {
ProjectID ids.ID `json:"projectId,omitzero"`
DeploymentID ids.ID `json:"deploymentId,omitzero"`
Project string `json:"project"`
Deployment string `json:"deployment"`
Generation int64 `json:"generation,omitempty"`
Need string `json:"need,omitempty"` // for a database: which need it fulfils
}
ResourceHost is a deployment that runs on or uses a resource.
type RetainedNote ¶
type RetainedNote struct {
ID ids.ID `json:"id"`
Project string `json:"project"`
Deployment string `json:"deployment"`
RetainedBy string `json:"retainedBy"`
RetainedAt stamp.Time `json:"retainedAt"`
// Reason, when the note comes from a label rather than the retained
// ledger: why the deployment no longer records the resource.
Reason string `json:"reason,omitempty"`
}
RetainedNote says a resource was left behind by a torn-down deployment.
type RunningRecord ¶
type RunningRecord interface {
RecordedRunning(p Placement, released string) string
AdoptRunning(running string) map[string]any
}
RunningRecord is a driver whose provider names what runs (Observation.Running), so that after AppTown was restored its record can be held to the provider's answer. RecordedRunning is what the record says runs, in the same terms: from the placement, or else released, what the newest released release recorded (its external reference). AdoptRunning is what the placement's handle becomes once running is taken as the record (nil: nothing).
type SelectedSource ¶
type SelectedSource struct{ Repository, Revision string }
SelectedSource is an explicit repository revision, never an inferred HEAD.
func (SelectedSource) Resolve ¶
func (s SelectedSource) Resolve(ctx context.Context) (string, error)
func (SelectedSource) Snapshot ¶
func (s SelectedSource) Snapshot(ctx context.Context, destination string) (SourceTree, error)
Snapshot publishes a selected tree at a caller-owned cache path. The caller serializes use of that path (preview boot ownership does so). Resolve before consulting the marker: invalid or absent selections cannot revive old bytes.
func (SelectedSource) Stage ¶
func (s SelectedSource) Stage(ctx context.Context, parent string) (SourceTree, func(), error)
Stage extracts selected bytes, without the repository's uncommitted changes. Parent is optional; publishing by rename requires the same filesystem. Cleanup is always callable, including on error.
type ServiceSpec ¶
type ServiceSpec struct {
Name string `json:"name"`
Image string `json:"image"`
Env map[string]string `json:"env"`
// Command overrides the image's default (a dependency emulator like MinIO
// needs `server /data`). Sidecars from a contract leave it empty.
Command []string `json:"command,omitempty"`
// Entrypoint replaces the image's entrypoint, when set: a need's start
// script (the s3 emulator's makes its bucket and account first). Docker
// takes one executable for it; the rest go before Command (RunArgs).
Entrypoint []string `json:"entrypoint,omitempty"`
// ConfigAtStart says the service keeps none of what it is started with
// in its data: everything it is configured with is set again at every
// start. A standing one whose image, entrypoint, command or environment
// changed is remade on its own volume, whatever its data class, as a
// lifted size limit is.
ConfigAtStart bool `json:"configAtStart,omitempty"`
// KeepsImage says the service's data is in its image's own format: a
// standing one whose image moved is not remade under ConfigAtStart but
// refused unless its data is synthetic, as any data service is. A
// Postgres of another major version cannot read the old files.
KeepsImage bool `json:"keepsImage,omitempty"`
// Health is a shell healthcheck command (exit 0 = healthy). When set, the
// runtime applies it as docker --health-cmd and can gate startup on it.
Health string `json:"health,omitempty"`
// AppPart says the service is one of the app's own parts, not a need's:
// it is given the extra certificates the app's containers trust
// (internal/trust); a database or cache beside it calls out to nothing.
AppPart bool `json:"appPart,omitempty"`
// Public/host-port handling is caller-driven; these mark a non-public app
// part started on the stack (Port for its PORT env, not a host mapping).
Port int `json:"port,omitempty"`
// Resources is the most a non-public app part or a need's service may
// use; nothing declared is no limit.
Resources appcontract.Resources `json:"resources,omitzero"`
// Data is where a need's emulator keeps its data (its catalogue kind's
// local data path), empty for a sidecar or an app part. A throwaway
// start mounts a disposable volume there: an emulator whose image does
// not make that folder itself (S3's) exits at once without it.
Data string `json:"data,omitempty"`
// Credentials are the values AppTown generated for this service (a
// deployment's or a preview's need credentials), in its Env and in what
// the app is given: a boot redacts them from every failure it returns
// (docker.Host.Boot). Carried with a prepared boot to where it runs.
Credentials []string `json:"credentials,omitempty"`
}
ServiceSpec is a container run beside an app: a sidecar for a step, a need's emulator, a service a contract declares: started on the step's network before the step runs, reachable by Name, torn down after.
func (ServiceSpec) EntrypointFlag ¶
func (s ServiceSpec) EntrypointFlag() []string
EntrypointFlag is the docker run flag that sets the service's entrypoint, or nothing when it keeps its image's.
func (ServiceSpec) RunArgs ¶
func (s ServiceSpec) RunArgs() []string
RunArgs are what follow the image on docker run: the rest of the entrypoint, then the command.
type SizePricer ¶
SizePricer is a target that bills per instance size: its listed monthly price of each size, by slug, the start of each size words a fitter answers (ResourceFitter). An estimate is made from it, and called one.
type Source ¶
type Source struct {
// Ingress is selected at admission, never recomputed from current names.
Ingress *Ingress
// Services is a replay of supplied sidecars after applying the generation
// record; nil uses the original artifact inputs. It never changes Body/Hash.
Services []ServiceSpec
Workspace string // a staged, self-contained checkout of Revision
Revision string // the committed tree the source is
Slug string // the application's slug, for naming on hosts
Contract *appcontract.Contract
Images map[string]string // part -> image id, or image by digest, when the parts were built earlier
Init map[string]string // init step -> image id, likewise
// Published: Images and Init are images by digest in a registry, built
// for Platform; false is image IDs that live only on the host that
// built them.
Published bool
Platform string
}
Source is the selected software a deploy runs from: a bundle cut earlier, or a committed tree the caller staged. The caller owns the workspace's lifetime.
type SourceTree ¶
type SourceTree struct{ Directory, Revision string }
SourceTree carries the directory and the resolved identity of its bytes. A live worktree may have uncommitted edits and no committed revision yet.
func StageCommit ¶
func StageCommit(ctx context.Context, repo, commit, parent string) (SourceTree, func(), error)
StageCommit is Stage for a commit Resolve has already named in repo: the same extraction, without asking git to resolve it a second time.
type StorageBinding ¶
type StorageBinding struct {
Need string `json:"need"`
Volume string `json:"volume"`
DataPath string `json:"dataPath"`
DeclaredImage string `json:"declaredImage"`
ImageID string `json:"imageID"`
RepoDigest string `json:"repoDigest,omitempty"`
VolumeCreated time.Time `json:"volumeCreated"`
VolumeDriver string `json:"volumeDriver"`
Origin string `json:"origin"`
}
StorageBinding is observed evidence of the engine that may open one volume. It does not grant ownership of the volume or permission to delete it.
type StorageBindings ¶
type StorageBindings interface {
Get(context.Context, string, string) (StorageBinding, bool, error)
Establish(context.Context, StorageBinding) error
Retire(context.Context, string, string) error
}
StorageBindings records evidence before an engine can write. Establish is idempotent for identical evidence and refuses to replace an existing binding. Retire follows confirmed volume deletion; it never authorizes deletion.
type StorageCopy ¶
StorageCopy identifies a verified backup item admitted for an engine restore. A physical copy requires immutable engine evidence captured at export time.
type StorageRestore ¶
type StorageRestore interface {
Image(need, declared string, source *StorageBinding) (image string, exact bool, err error)
Restore(context.Context, *StorageBinding, StorageBinding) error
}
StorageRestore is supplied only by an admitted whole-instance logical restore. It replaces source certification with this boot's newly created target and preserves both in the owner's audit transaction.
type TakeDown ¶
type TakeDown struct {
Owned []Owned
BackedUp bool
LastUser bool
// Synthetic says the deployment's data is synthetic and nothing will
// restore it (an eval copy's): Data entries are deleted with no final
// backup. It still deletes only what Owned names.
Synthetic bool
}
TakeDown is what a teardown may delete. Owned is the deployment's list. BackedUp says a complete final backup covers every Data entry; without it, data is kept and reported Left. LastUser says no other deployment of the project shares what the project holds on this account (App Platform: the project's image repository).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package appcontract owns AppTown's native .apptown/app.yaml declaration, parsing, validation, and preparation of independent execution inputs.
|
Package appcontract owns AppTown's native .apptown/app.yaml declaration, parsing, validation, and preparation of independent execution inputs. |
|
Package digitalocean is the DigitalOcean App Platform target driver (design/subsystems/deployment.md §12A): the renderer, the reconciler, the managed-database need module and the account inventory, with every collaborator injected.
|
Package digitalocean is the DigitalOcean App Platform target driver (design/subsystems/deployment.md §12A): the renderer, the reconciler, the managed-database need module and the account inventory, with every collaborator injected. |
|
dofake
Package dofake supplies the DigitalOcean HTTP API fixture shared by driver tests and assembled AppTown deployment tests.
|
Package dofake supplies the DigitalOcean HTTP API fixture shared by driver tests and assembled AppTown deployment tests. |
|
Package docker is the container runtime AppTown drives: which daemon a command talks to (AppTown's own, or an attached host's over SSH), the command itself, and the small questions asked of a daemon (is a container running, what is an image's digest, where is a port reachable).
|
Package docker is the container runtime AppTown drives: which daemon a command talks to (AppTown's own, or an attached host's over SSH), the command itself, and the small questions asked of a daemon (is a container running, what is an image's digest, where is a port reachable). |
|
dockerfake
Package dockerfake models the small Docker daemon contract used by tests.
|
Package dockerfake models the small Docker daemon contract used by tests. |
|
dockertest
Package dockertest runs the docker CLI against this machine's own daemon for tests that set up, inspect or clean up containers, images and networks the code under test does not.
|
Package dockertest runs the docker CLI against this machine's own daemon for tests that set up, inspect or clean up containers, images and networks the code under test does not. |
|
Package portainer is the Portainer target driver (design/subsystems/ deployment.md §8.2): the intranet rail given its name.
|
Package portainer is the Portainer target driver (design/subsystems/ deployment.md §8.2): the intranet rail given its name. |
|
portainerfake
Package portainerfake projects external provider facts for tests using real AppTown deployment owners.
|
Package portainerfake projects external provider facts for tests using real AppTown deployment owners. |
|
portainertest
Package portainertest reads what a Portainer stack serves, for tests that check a release rendered the admitted hosts and certificate input.
|
Package portainertest reads what a Portainer stack serves, for tests that check a release rendered the admitted hosts and certificate input. |
|
Package s3bucket is the s3-bucket target: a static-only app published to a bucket of an S3-compatible store (DigitalOcean Spaces first) and served from the bucket's website address (design/subsystems/deploy-targets.md, "Bucket websites").
|
Package s3bucket is the s3-bucket target: a static-only app published to a bucket of an S3-compatible store (DigitalOcean Spaces first) and served from the bucket's website address (design/subsystems/deploy-targets.md, "Bucket websites"). |
|
s3fake
Package s3fake is an in-memory S3-compatible store for the s3bucket driver's tests and assembled AppTown tests: the API, path-style, and each bucket's website address.
|
Package s3fake is an in-memory S3-compatible store for the s3bucket driver's tests and assembled AppTown tests: the API, path-style, and each bucket's website address. |
|
Package staticsite is a static release as files a host serves as they are (design/subsystems/deploy-targets.md, "Bucket websites"): the site's files from its release image, plus the two files AppTown's file server would otherwise compute, and the witness that a public address serves exactly this publication.
|
Package staticsite is a static release as files a host serves as they are (design/subsystems/deploy-targets.md, "Bucket websites"): the site's files from its release image, plus the two files AppTown's file server would otherwise compute, and the witness that a public address serves exactly this publication. |