wiring

package
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package wiring adapts the scale-set client to what the control plane and the node consume.

It exists because internal/scaleset returns its OWN types: the alternative is that package importing internal/server purely to name a two-field struct, which points the dependency the wrong way for a package whose whole job is to keep a preview API at arm's length.

It is a package rather than a few funcs in main because the end-to-end test assembles billet the same way the CLI does, and a hand-copied adapter defeats that. The copy in the test had already drifted — it dereferenced a scale set the client returns as nil for "no such set", which the original checks for — and a test that exercises different wiring than production is testing the wrong program.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildTargets added in v0.10.0

func BuildTargets(targets []Target) ([]server.Target, map[string]nodeplane.JITSource, error)

BuildTargets assembles the two views of a target set the control plane consumes: the server's, which reconciles and polls each tier's scale set through its target's provisioner, and the node plane's, which mints registrations through the same target's client.

ONE ASSEMBLY FOR BOTH, keyed by the target's config name on each side, so a tier resolves to the same credential whichever half of the control plane is asking — and so internal/e2e assembles a multi-target deployment the way the CLI does rather than by hand.

REFUSED RATHER THAN SILENTLY SPLIT. The server keeps a slice and resolves the first entry of a name, the plane keeps a map and would hold the last, so two entries under one name would reconcile a tier through one App and mint its registrations through another. Config refuses duplicate names at load; this refuses them at the seam every caller passes through, and refuses a client whose own target is not the one the config names.

Types

type JITSource

type JITSource struct {
	Client *scaleset.Client
	Pool   poolRunnerStore
}

JITSource adapts the client to what the node needs to mint registrations.

func (JITSource) Describe

func (j JITSource) Describe(ctx context.Context, name, group string) (*node.Set, []string, error)

Describe resolves a tier's scale set, reporting a nil set when there is none.

The nil check is the whole reason this is shared code. Describe returns (nil, nil, nil) for a scale set that does not exist — a perfectly reasonable contract, and one that segfaults the moment a caller assumes an error would have been returned instead.

func (JITSource) EnsureRunnerRemoved

func (j JITSource) EnsureRunnerRemoved(ctx context.Context, leaseID string) error

EnsureRunnerRemoved resolves a restart-surviving registration from the control-plane journal before recovered compute is touched.

func (JITSource) JITConfig

func (j JITSource) JITConfig(
	ctx context.Context, scaleSetID int, runnerName, workFolder string,
) (node.Registration, error)

JITConfig mints a single-use runner registration.

func (JITSource) RecoverRunner

func (j JITSource) RecoverRunner(ctx context.Context, leaseID, tier string,
	requestID int64, runnerName string,
) (node.RunnerRecovery, error)

RecoverRunner preserves a legacy quarantined registration while it is busy, or removes it while idle before the node tears its compute down.

func (JITSource) RemoveRunner

func (j JITSource) RemoveRunner(
	ctx context.Context, _ string, runnerID int64, runnerName string,
) error

RemoveRunner removes a failed local launch's GitHub registration.

func (JITSource) ValidateTrustedRunnerGroup

func (j JITSource) ValidateTrustedRunnerGroup(ctx context.Context, _ string, group string,
	workflows []string,
) error

ValidateTrustedRunnerGroup verifies policy immediately before local minting. The tier is what a router over several targets selects a client by; one client serves every tier it is given.

type NodeJIT

type NodeJIT struct{ Client *scaleset.Client }

NodeJIT is the same source, shaped for the node wire.

TWO SHAPES FOR ONE THING, and the duplication is deliberate. internal/nodeplane declares its own JITSet and JITRegistration so the transport does not import the runtime it serves — they sit on opposite sides of a process boundary, and coupling them would defeat the point of having one. The cost is this adapter; the benefit is that neither side moves because the other was edited.

func (NodeJIT) Describe

func (n NodeJIT) Describe(
	ctx context.Context, name, group string,
) (*nodeplane.JITSet, []string, error)

Describe finds a scale set for the wire.

The nil-set-means-absent contract is preserved rather than flattened: the node treats absence as a reason to stop, and a zero-valued set would have it launch against scale set 0.

func (NodeJIT) JITConfig

func (n NodeJIT) JITConfig(
	ctx context.Context, scaleSetID int, runnerName, workFolder string,
) (nodeplane.JITRegistration, error)

JITConfig mints a registration for a remote node.

func (NodeJIT) RecoverRunner

func (n NodeJIT) RecoverRunner(
	ctx context.Context, runnerName string,
) (nodeplane.JITRunnerRecovery, error)

RecoverRunner resolves the exact legacy registration for a remote node.

func (NodeJIT) RemoveRunner

func (n NodeJIT) RemoveRunner(ctx context.Context, runnerID int64, runnerName string) error

RemoveRunner removes a remote node's failed-launch registration.

func (NodeJIT) ValidateTrustedRunnerGroup

func (n NodeJIT) ValidateTrustedRunnerGroup(ctx context.Context, group string,
	workflows []string,
) error

ValidateTrustedRunnerGroup verifies policy immediately before remote minting.

type NodeWire

type NodeWire struct {
	// Handler is the node wire's routes, with every option this deployment's
	// authority and policy imply already installed.
	Handler http.Handler
	// Bootstrap is the two routes a machine that has never enrolled needs, on a
	// handler of its own because they cannot require the certificate everything
	// else does — served on their own listener and budget. Nil on a loopback
	// wire, which has no certificates and so nothing to enroll into.
	Bootstrap http.Handler
	// TLS is the server side of the wire: what the control plane PRESENTS, and
	// which authorities a client certificate may come from. Nil on a loopback
	// wire, which has no certificates at all because the trust boundary there is
	// the machine.
	TLS *tls.Config

	// THE THREE BELOW ARE FOR THE SECOND LISTENER, and they come from this same
	// read for the reason the read exists. The two routes a machine with no
	// certificate needs are served on an address of their own, and what THAT
	// listener presents and what it hands an enrolling machine to trust have to
	// describe the same moment as this one — a `billet ca retire` landing between
	// two reads would admit a node against an authority the control plane has
	// stopped presenting. All three are zero on a loopback wire, which has no
	// certificates and so nothing to enroll into.
	//
	// Serving is the certificate BOTH listeners present, and IssuingExpiry below
	// is what the authority behind them expires. The handlers already carry the
	// rest of that read.
	Serving wirecert.Bundle
	// Rotating reports an overlap, and RotationAge how long ago it started, so
	// the caller can say so.
	Rotating    bool
	RotationAge time.Duration
	// IssuingExpiry is when the authority that signs node certificates stops
	// working, and Hosts what its certificate was minted for. Reported at
	// startup, because a CA is a slow cliff.
	IssuingExpiry time.Time
}

NodeWire is the assembled node wire: what the listener serves and the handler behind it.

THE HANDLER RATHER THAN THE OPTIONS THAT BUILD IT, and that is the second version of this type. Returning options left the caller to install them, which is a step no test could see — remove the append in cmd/billet and every test here stayed green, which is the same untested seam one level up from where it was found. The only way a test covers a handoff is to be handed the same finished thing production is.

func BuildNodeWire

func BuildNodeWire(req NodeWireRequest) (NodeWire, error)

BuildNodeWire assembles the authenticated node wire from a deployment's authority.

HERE RATHER THAN IN cmd/billet, AND THAT IS THE WHOLE POINT OF THE FILE. This was eleven lines inside serveNodeWire, which lives in a package excluded from coverage and takes six collaborators to stand up — so nothing asserted the SEAM, only the pieces either side of it. A mutant replacing the trust bundle with the issuing authority alone survived the entire suite, and during a rotation that refuses every node holding a certificate from the previous authority, which is the whole fleet until it has renewed.

The three answers it has to get right, each of which was reachable only from here:

  • What the server PRESENTS is signed by the authority the fleet still trusts — the PREVIOUS one during an overlap. Presenting the new one makes the control plane unverifiable to every node that has not renewed, over the wire it would need in order to renew.
  • What the server ACCEPTS is every authority in the bundle, so a node holding either generation is recognised while the overlap runs.
  • What renewal SIGNS with is the ISSUING authority — the new one — because renewal is the only way the new authority reaches the fleet at all.

In wiring rather than wirecert because nodeplane imports wirecert, so the dependency only points this way.

type NodeWireRequest

type NodeWireRequest struct {
	// StateDir and Deployment locate and name the authority.
	StateDir, Deployment string
	// Hosts are the names a node may dial this control plane by. Empty on a
	// loopback wire.
	Hosts []string
	// Loopback says the wire has no certificates at all: two processes on one
	// machine, where the trust boundary is the machine. Config validation refuses
	// node.tls against such a server for the same reason.
	Loopback bool

	// The collaborators the routes need.
	Log    *slog.Logger
	Plane  *nodeplane.Plane
	Leases nodeplane.LeaseStore
	// JIT serves every tier when TargetJIT is empty; TargetJIT is one source per
	// GitHub target, keyed by the target's config name, which is what
	// BuildTargets hands back.
	JIT         nodeplane.JITSource
	TargetJIT   map[string]nodeplane.JITSource
	Revocations nodeplane.Revocations
	Enrollments nodeplane.Enrollments
	CachePolicy nodeplane.CachePolicy
}

NodeWireRequest is what a deployment brings to its own node wire.

type Provisioner

type Provisioner struct{ Client *scaleset.Client }

Provisioner adapts the client to the control plane's scale-set needs.

func (Provisioner) EnsureScaleSet

func (p Provisioner) EnsureScaleSet(
	ctx context.Context, name, group string, labels []string,
) (*server.ScaleSet, error)

EnsureScaleSet makes a tier's scale set exist.

func (Provisioner) RemoveRunner

func (p Provisioner) RemoveRunner(ctx context.Context, runnerID int64, runnerName string) error

RemoveRunner removes routing before the control plane tears compute down.

func (Provisioner) Session

func (p Provisioner) Session(ctx context.Context, scaleSetID int, owner string) (server.Session, error)

Session opens a long-poll session on one scale set.

func (Provisioner) ValidateTrustedRunnerGroup

func (p Provisioner) ValidateTrustedRunnerGroup(ctx context.Context, group string,
	workflows []string,
) error

ValidateTrustedRunnerGroup verifies a trusted tier's workflow boundary.

type Target added in v0.10.0

type Target struct {
	Config config.GitHubTarget
	Client *scaleset.Client
}

Target is one GitHub target with the client that holds its credential.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL