Documentation
¶
Overview ¶
Package lab runs the maintained acceptance modules against a workspace and a target.
The package is importable: a separate device lab, with its own drivers, target matrix, Apple credentials and private evidence, registers its own modules against these types and reuses this runner, result model and report rather than reimplementing them.
Design ¶
A workspace keeps local identities and configuration across runs. Start can embed the server runtime or launch dmserver processes, using the same server configuration in either case. Up supervises those processes in the foreground; other commands attach through an authenticated loopback control endpoint.
The catalogue is one ordered inventory of modules. A module declares the workspace modes whose server environment it needs, the target capabilities it uses and the lifecycle stage that orders it. Modes select the service environment: simulated workspaces provide local Apple-service fixtures, while live workspaces use the operator's Apple credentials and a real device. Targets, in package target, supply the device side. A run writes JSON, JUnit and a self-contained HTML report, distinguishing failures from unavailable prerequisites and inapplicable modules.
Doctor and the offline preflight report missing prerequisites without enrolling a device or changing its trust settings.
ADE modules separate read-only server-token/API evidence, explicitly opted-in designated assignment with private recovery fencing, and actual native enrollment proof. API and fixture passes cannot certify hardware. Per-platform results retain unexercised scope, and DDM exchange and cleanup have independent evidence. See docs/operations/ade-acceptance.md for private inputs and executable live steps.
Apps and Books checks independently collect read-only location evidence, exercise explicitly designated free-app licensing through SDK and reference paths with private original-state fencing, and inspect actual native app installation/version. Licensing callbacks, aggregate status, per-target readback and cleanup are separate requirements. An inspection never removes a preexisting app or claims restoration after external preparation. User licensing retains Apple's clientUserId independently of hardware serials. See docs/operations/apps-and-books-acceptance.md for private inputs and scope.
References ¶
Index ¶
- Constants
- Variables
- func Command(ctx context.Context, e *Environment, path string, cmd *mdm.Command, ...) ([]byte, error)
- func EnrollmentPreflight(w *Workspace, identity string) map[string]any
- func ExportTrust(w *Workspace, destination string) error
- func HTTP(ctx context.Context, c *http.Client, base, token, method, path string, ...) ([]byte, int, error)
- func Init(dir, mode, storage, listen, adapter string, hosts []string) error
- func Markdown() string
- func Profile(ctx context.Context, e *Environment, device, destination string) error
- func ProfileWithIdentity(ctx context.Context, e *Environment, device, identity, destination string) error
- func ReissueTLS(w *Workspace, hosts []string) error
- func Replace(ctx context.Context, e *Environment, device, identity string) (map[string]any, error)
- func Up(ctx context.Context, w *Workspace, binary string, out io.Writer) error
- func WriteHTML(dir string, results []Result) error
- func WriteReports(dir string, results []Result) error
- type Connection
- type Environment
- type Instance
- type Module
- type Options
- type Result
- type Session
- type Step
- type StepResult
- type Workspace
Constants ¶
const ( // ComposeFile is the lab stack, relative to the repository root. ComposeFile = "deploy/lab/compose.yaml" // EnvFile is the generated container environment, private to the workspace. EnvFile = "lab.env" )
Container layout. The workspace's mdm directory is the container's data volume, so identities, the database and any configured policy file keep one home on the host.
const ( StagePreflight = 0 StageProvision = 10 StageEnroll = 20 StageReadiness = 30 StageInventory = 40 StageConfiguration = 50 StageApps = 60 StageSecurity = 70 StageEvents = 80 StageReplacement = 85 StageDestructive = 90 StageUnenroll = 99 )
Lifecycle stages order modules for one target. Modules with equal stages keep catalogue order.
const ( StatusPassed = "passed" StatusFailed = "failed" StatusBlocked = "blocked" StatusUnsupported = "unsupported" )
Result statuses. Blocked and unsupported are distinct from failed: blocked means a prerequisite or an earlier gate was not met, unsupported means the module does not apply to the selected mode or target.
const ( ResultsFile = "results.json" JUnitFile = "junit.xml" HTMLFile = "report.html" )
Report file names written into a run directory.
const ( WorkspaceFile = "lab.json" LegacyWorkspaceFile = "bench.json" )
WorkspaceFile is the private workspace document. LegacyWorkspaceFile is the name used before the lab replaced the bench; Load still reads it so existing live workspaces keep their identities, database and storage-key names.
const ( AdapterProcess = "process" AdapterDocker = "docker" )
Server adapters.
const DefaultModuleTimeout = 2 * time.Minute
DefaultModuleTimeout bounds one module when Options.Timeout is zero.
const TagDestructive = "destructive"
TagDestructive marks modules that erase, lock or restart a device. They run only when Options.Destructive is set.
Variables ¶
var ErrBlocked = errors.New("scenario prerequisites unavailable")
Functions ¶
func Command ¶ added in v0.10.4
func Command(ctx context.Context, e *Environment, path string, cmd *mdm.Command, evidence string) ([]byte, error)
Command queues a fresh command, requires APNs acceptance, and waits for the exact enrollment's acknowledgment. Evidence includes request, push and reply. Wake acceptance and acknowledgment each wait up to 45 seconds, bounded by context.
func EnrollmentPreflight ¶
EnrollmentPreflight checks local prerequisites without installing profiles or changing trust. Service discovery and device delivery have separate scenarios.
func ExportTrust ¶
ExportTrust bootstraps private HTTPS trust before the Mac can fetch an HTTPS profile.
func HTTP ¶
func HTTP( ctx context.Context, c *http.Client, base, token, method, path string, body io.Reader, headers ...http.Header, ) ([]byte, int, error)
HTTP performs a bounded admin request. Errors contain status, never bodies or tokens.
func Init ¶
Init creates the persistent lab workspace with its selected mode, storage, listener and server adapter. hosts adds device-facing names to the generated HTTPS leaf.
func Profile ¶
func Profile(ctx context.Context, e *Environment, device, destination string) error
Profile requests the actual configured enrollment service and writes a new file.
func ProfileWithIdentity ¶
func ProfileWithIdentity( ctx context.Context, e *Environment, device, identity, destination string, ) error
ProfileWithIdentity exports the configured profile with the rights needed for inventory and controlled profile replacement. Empty identity uses server defaults.
func ReissueTLS ¶
ReissueTLS replaces the workspace HTTPS leaf with one covering loopback and hosts, signed by the retained workspace CA. Devices that already trust the CA keep working, so the trust profile does not have to be installed again.
func Up ¶
Up supervises processes in the foreground. A separate dmctl lab down uses the authenticated loopback control endpoint, never a possibly recycled PID.
func WriteReports ¶
WriteReports writes private JSON evidence, a JUnit projection and a self-contained HTML report. Non-passes never become successes merely because the selected execution mode lacks a device.
Types ¶
type Connection ¶ added in v0.10.4
type Connection struct {
URL, CAFile, TokenFile, EvidenceDirectory string
}
Connection attaches the harness to a managed deployment without creating another database or identity set. Paths refer to the host filesystem.
type Environment ¶
type Environment struct {
// InstallingUserID is the local user's GeneratedUID, supplied by the operator
// for live enrollment acceptance. It is not inferred from an arbitrary child.
InstallingUserID string
DEP *deptest.Server
ABM *axmtest.Server
Provider *webauthtest.Provider
Authority *testpki.CA
Instance
Client *http.Client
Token string
APNS *pushtest.Server
Workspace *Workspace
// contains filtered or unexported fields
}
Environment owns fixture services and the ordinary server runtime(s).
func Attach ¶
func Attach(w *Workspace) (*Environment, error)
Attach loads the recorded lab instance and its HTTP credentials from an existing workspace.
func AttachURL ¶
func AttachURL(w *Workspace, address string) (*Environment, error)
AttachURL connects to an existing live server using the workspace's trust and admin credential. It does not start a supervisor, replace state or migrate SQL.
func Connect ¶ added in v0.10.4
func Connect(ctx context.Context, cfg Connection) (*Environment, error)
Connect validates trust and credentials and verifies the managed principal. Close releases the HTTP transport; it never stops the attached server.
func Start ¶
Start uses the same configuration and runtime in both adapters. A nonempty binary launches dmserver; an empty binary embeds runtime.ServeListener for E2E tests.
func (*Environment) Close ¶
func (e *Environment) Close()
Close stops all runtimes before releasing fixture services.
type Instance ¶
type Instance struct {
Binary string `json:"Binary"`
URL string `json:"URL"`
ControlURL string `json:"ControlURL"`
ControlToken string `json:"ControlToken"`
Mode string `json:"Mode"`
}
Instance describes the running workspace. The control credential stays private.
Private lab documents use the same PascalCase convention as admin responses.
type Module ¶
type Module struct {
// Timeout is a protocol-specific default. An explicit Options.Timeout wins.
Timeout time.Duration `json:"-"`
Settings map[string]string `json:"Settings,omitempty"`
ID string `json:"ID"`
Name string `json:"Name"`
Theme string `json:"Theme"`
Stage int `json:"Stage"`
Regression string `json:"Regression"`
Modes []string `json:"Modes"`
Prerequisites []string `json:"Prerequisites"`
Requires []string `json:"Requires,omitempty"`
Tags []string `json:"Tags,omitempty"`
Gate bool `json:"Gate,omitempty"`
Applies func(target.Info) string `json:"-"`
Steps []Step `json:"-"`
}
Module is one maintained acceptance check. Implementations never depend on testing.T. Modes names the workspace modes whose server environment the module needs; Requires names target capabilities; Applies adds target-specific conditions. Regression names the detailed component test retained in server/e2e.
Catalogue JSON uses the administration PascalCase convention.
func Catalogue ¶
func Catalogue() []Module
Catalogue returns a fresh module inventory in stable ID order. Modules without an explicit Stage take their theme's lifecycle stage.
func Select ¶
Select resolves a comma-separated selector of module IDs, themes or all against the catalogue and rejects unknown selections.
func SelectFrom ¶ added in v0.10.4
SelectFrom resolves IDs and themes against an extended catalogue without changing the shared registry. all retains the caller's catalogue order.
func SelectMode ¶
SelectMode makes all select the modules applicable to mode; explicit IDs and themes still report unsupported modes rather than being silently ignored.
type Options ¶
type Options struct {
Adapter, Revision string
Timeout time.Duration
Destructive bool
Evidence string
}
Options configure a run. Timeout bounds each module; zero selects the module's protocol-specific timeout or DefaultModuleTimeout. Evidence is the run directory; each module writes beneath Evidence/evidence/<ID>.
type Result ¶
type Result struct {
ID string `json:"ID"`
Name string `json:"Name"`
Theme string `json:"Theme"`
Stage int `json:"Stage"`
Mode string `json:"Mode"`
Adapter string `json:"Adapter"`
Revision string `json:"Revision"`
Status string `json:"Status"`
Detail string `json:"Detail"`
Target target.Info `json:"Target"`
Steps []StepResult `json:"Steps,omitempty"`
Evidence []string `json:"Evidence,omitempty"`
Started time.Time `json:"Started"`
Duration time.Duration `json:"Duration"`
}
Result distinguishes unavailable prerequisites from an assertion failure.
Evidence JSON uses the administration PascalCase convention.
func ReadResults ¶
ReadResults loads the results.json written by WriteReports.
func Run ¶
Run executes one module against t and returns its status, steps, duration and evidence. It never returns an error: every outcome is a Result.
func RunAll ¶
func RunAll( ctx context.Context, e *Environment, t target.Target, modules []Module, opts Options, observe func(Result), ) []Result
RunAll runs modules against one target in lifecycle order. A gate module that does not pass blocks every later module. observe, when non-nil, receives each result as it completes. Run cancellation stops before the next module.
type Session ¶
Session is the context a step executes in. Evidence is the module's private evidence directory, or empty when the run keeps no evidence files.
type StepResult ¶
type StepResult struct {
Name string `json:"Name"`
Status string `json:"Status"`
Detail string `json:"Detail,omitempty"`
Duration time.Duration `json:"Duration"`
}
StepResult records one executed or skipped step.
type Workspace ¶
type Workspace struct {
Settings map[string]string `json:"Settings,omitempty"`
Version int `json:"Version"`
Mode string `json:"Mode"`
Storage string `json:"Storage"`
Listen string `json:"Listen"`
DSN string `json:"DSN,omitempty"`
// Adapter is how dmserver runs: AdapterProcess (default) or AdapterDocker.
Adapter string `json:"Adapter,omitempty"`
// Hosts are the DNS names and IP addresses in the HTTPS leaf beyond loopback. The
// first entry names the server in device-facing URLs.
Hosts []string `json:"Hosts,omitempty"`
// Bind is the host address the container adapter publishes its ports on. Empty
// publishes on loopback only.
Bind string `json:"Bind,omitempty"`
Directory string `json:"-"`
}
Workspace contains non-secret settings. Existing local identities stay in mdm/.
Preserve the private workspace document schema.
func (*Workspace) Doctor ¶
Doctor checks prerequisites without enrolling a device or altering trust.
func (*Workspace) PublicBase ¶
PublicBase returns the device-facing origin: the first configured host, or the loopback listener when no host is configured.
Source Files
¶
- attach.go
- authorization.go
- catalog.go
- doc.go
- docker.go
- enrollment.go
- enrollmentlink.go
- enterprise.go
- environment.go
- errors.go
- identity.go
- identity_scenarios.go
- live.go
- live_abm.go
- live_ade.go
- live_ade_assignment.go
- live_ade_collection.go
- live_ade_hardware.go
- live_appsbooks.go
- live_appsbooks_installation.go
- live_appsbooks_licensing.go
- live_blueprints.go
- live_ddm.go
- live_private.go
- lock_unix.go
- module.go
- process_unix.go
- report.go
- scenarios.go
- space_unix.go
- workspace.go