Documentation
¶
Overview ¶
Package upgrade replaces the running Pando with a newer release (R-355 – R-361): checked, backed up, swapped by a helper, and put back on its own when the new version does not come up.
Index ¶
- Constants
- func MovingTag(ref, version string) (tag string, reason string)
- func OutcomePath(workDir string) string
- func WriteOutcome(path string, o Attempt) error
- type Attempt
- type Database
- type Plan
- type Request
- type Service
- func (s *Service) Last(context.Context) (*Attempt, error)
- func (s *Service) PlanFor(ctx context.Context, version string) (Plan, error)
- func (s *Service) Run(ctx context.Context)
- func (s *Service) Start(ctx context.Context, p authz.Principal, req Request) (Attempt, error)
- func (s *Service) Tick(ctx context.Context)
- type Swap
Constants ¶
const ( StateRunning = "running" StateSucceeded = "succeeded" StateRolledBack = "rolled_back" StateFailed = "failed" )
What an upgrade came to, written where every version of Pando reads it.
The helper outlives the Pando that started it and is gone before the next one starts, so neither can tell the other anything directly: the outcome is a file in Pando's data directory, written by whichever of them knows, and read by the Pando that starts next — new or restored — which records it in the audit log (R-356).
const ( DefaultReadyTimeout = 5 * time.Minute DefaultSoak = 24 * time.Hour )
Defaults for R-359's [P] values.
const DatabaseURLEnv = "UPGRADE_DATABASE_URL"
DatabaseURLEnv carries the owner's database URL to the helper. Not a PANDO_ variable, which the helper would read as configuration.
const LoopInterval = 5 * time.Minute
LoopInterval is how often the loop looks. A maintenance window is whole hours, so five minutes finds every one.
const Repository = update.Image
Repository is the published image, as a deployment names it.
Variables ¶
This section is empty.
Functions ¶
func MovingTag ¶
MovingTag reports how a deployment's image reference names Pando: the moving tag, if it is one, and whether it covers version (R-355). A reason is returned when it does not, written for the person who will change it.
trypando/pando:latest any release trypando/pando:0.3 0.3's patches trypando/pando:1 1.x trypando/pando:0.3.1 no: an exact version trypando/pando@sha256… no: a digest
func OutcomePath ¶
OutcomePath is where the outcome lives under Pando's data directory.
func WriteOutcome ¶
WriteOutcome replaces the outcome atomically, so a reader never sees half.
Types ¶
type Attempt ¶
type Attempt struct {
ID string `json:"id"`
From string `json:"from"`
To string `json:"to"`
Image string `json:"image"`
Tag string `json:"tag,omitempty"`
StartedAt time.Time `json:"started_at"`
StartedBy string `json:"started_by"`
Automatic bool `json:"automatic"`
BackupID string `json:"backup_id,omitempty"`
SkipBackup bool `json:"skip_backup"`
State string `json:"state"`
FinishedAt time.Time `json:"finished_at,omitzero"`
Reason string `json:"reason,omitempty"`
Logs string `json:"logs,omitempty"`
SnapshotAt time.Time `json:"snapshot_at,omitzero"`
SnapshotGone bool `json:"snapshot_gone"`
// Recorded is set once a Pando has written the outcome to the audit log.
Recorded bool `json:"recorded"`
}
Attempt is one upgrade, as far as it got.
func ReadOutcome ¶
ReadOutcome reads the last upgrade's outcome; nil when there has been none.
func RunHelper ¶
func RunHelper(ctx context.Context, path string, swap Swap, db Database, readyTimeout time.Duration, clk clock.Clock) Attempt
RunHelper replaces Pando (R-359) and records how it went at path. It puts the previous version back on its own at every step after which the new one might have touched anything — and says so plainly when it cannot.
type Plan ¶
type Plan struct {
Current string `json:"current"`
Target string `json:"target"`
Possible bool `json:"possible"`
// Reasons say why it is not possible, each with what to change (R-105).
Reasons []string `json:"reasons"`
Image string `json:"image,omitempty"`
Tag string `json:"tag,omitempty"`
// Breaking are the versions in between that may break what works now
// (R-360), with their notes. Non-empty means the target version must be
// typed to confirm.
Breaking []update.Release `json:"breaking"`
// Unavailable while it lasts: every app, because the proxy is in Pando.
Note string `json:"note"`
}
Plan is what an upgrade to a version would do, or every reason it cannot.
type Request ¶
type Request struct {
Version string `json:"version"`
// ConfirmBreaking is the target version, typed, when Plan.Breaking is not
// empty (R-360).
ConfirmBreaking string `json:"confirm_breaking,omitempty"`
// Passphrase encrypts the full backup taken first (R-358).
Passphrase secret.Value `json:"passphrase"`
// SkipBackup says, explicitly, to go ahead without one.
SkipBackup bool `json:"skip_backup,omitempty"`
// Automatic is the schedule's (R-361): no backup, only the copy.
Automatic bool `json:"-"`
}
Request starts an upgrade.
type Service ¶
type Service struct {
Version string
Updates interface {
Status(ctx context.Context) (update.Status, error)
}
// Verify checks the target version's image signature and returns its
// digest (R-357).
Verify func(ctx context.Context, version string) (string, error)
// Runtime is the runtime Pando runs on, with its capabilities.
Runtime func(ctx context.Context) (api.RuntimeAdapter, error)
Policy func(ctx context.Context) (policy.Document, error)
// CanCopy checks the database account may take the rollback copy.
CanCopy func(ctx context.Context) error
// Backup takes and records a full backup, returning its ID (R-358).
Backup func(ctx context.Context, p authz.Principal, passphrase secret.Value) (string, error)
// Recipients are the people holding install.upgrade (R-362).
Recipients func(ctx context.Context) ([]string, error)
// DropSnapshot removes the rollback copy after the soak.
DropSnapshot func(ctx context.Context) error
Notify func(ctx context.Context, n api.Notification) error
Audit func(ctx context.Context, e audit.Event)
// Replicas counts the live Pando processes serving this install. An
// in-place upgrade is for one (issue #72).
Replicas func(ctx context.Context) (int, error)
// Hosts counts the cluster's hosts, this one included (R-414). An
// in-place upgrade is for an install on one (R-359, R-417).
Hosts func(ctx context.Context) (int, error)
DatabaseURL secret.Value
WorkDir string
Port string
ReadyTimeout time.Duration
Soak time.Duration
Clock clock.Clock
Logger *zap.Logger
}
Service is the in-place upgrade (R-355 – R-362).
func (*Service) Run ¶
Run does what an upgrade leaves to the Pando that comes after it, and what the schedule asks for, until ctx ends:
- records the last upgrade's outcome in the audit log, once (R-356);
- drops the rollback copy after the soak (R-359);
- tells install.upgrade holders about a new release, once per version (R-362);
- starts an automatic patch upgrade inside the window (R-361).
type Swap ¶
type Swap interface {
Stop(ctx context.Context) error
Recreate(ctx context.Context, image string) error
Ready(ctx context.Context, timeout time.Duration) error
// Version is the version the new container's image says it is, from its
// org.opencontainers.image.version label; empty when it has none.
Version(ctx context.Context) (string, error)
Logs(ctx context.Context) string
Discard(ctx context.Context)
Restore(ctx context.Context) error
Finish(ctx context.Context, image, tag string) error
}
Swap is the runtime's half of the helper: Pando's container, replaced.