Help us shape the future of Go! Take the 2026 Go Developer Survey

devfixture

package
v0.0.0-...-abb7a11 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: Apache-2.0 Imports: 41 Imported by: 0

Documentation

Overview

Package devfixture seeds and resets the deterministic development fixture (REQ-065) through the formal public Connect service seams. It never touches the database directly during seeding — every entity is created via the orchestrator, auth, webhook, and trust services — so the runner works against any deployment that exposes those APIs.

The seed is organized as nine committed phases (identity, routing, accounts, trust, bundle, values, enrollment, install, verify). Progress is persisted atomically to data/dev-seed-progress.json; a re-run verifies canonical consistency (entity existence + stable logical keys, never server-generated mutable fields) of already-committed phases and resumes from the first non-committed phase. When every phase is committed the run reports "fixture up-to-date" and issues no write RPCs (AC-065-03).

Reset (dev-reset-data) rebuilds the databases SDK-only: it rolls every migration down to the baseline and back up to the latest schema, then re-seeds all nine phases. On failure the progress file is marked "partial": true (the shell layer owns pg_restore recovery).

Index

Constants

View Source
const (
	DefaultFixtureVersion = "v2"
	DefaultDataDir        = "data"
	DefaultChartDir       = "deploy/fixtures/chart"
	DefaultTrustEnv       = "staging" // orchestrator --target-env in the dev kustomize
	DefaultInstallTimeout = 15 * time.Minute
	DefaultInstallPoll    = 3 * time.Second
	// AC-065-28 defaults (DEV_TIMEOUT_OPERATOR / DEV_TIMEOUT_SEED_RETRIES):
	// operator-online wait and phase-write retry count with 1s/2s/4s backoff.
	DefaultOperatorOnlineTimeout = 180 * time.Second
	DefaultSeedRetries           = 3
)

Defaults for seed runtime knobs.

Variables

View Source
var ErrFixtureConflict = errors.New("fixture_conflict")

ErrFixtureConflict reports canonical drift of an already-committed phase: an entity is missing or its stable logical key no longer matches the seed contract.

Functions

This section is empty.

Types

type BindingClient

BindingClient is the org-customer binding seam (identity phase).

type BundleClient

BundleClient is the orchestrator bundle service seam (verify phase).

type BundleRef

type BundleRef struct {
	ID     string `json:"id"`
	Digest string `json:"digest"`
}

BundleRef is the manifest entry for the seeded release bundle.

type ClusterRef

type ClusterRef struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

ClusterRef is the manifest entry for one seeded cluster.

type Config

type Config struct {
	Mode Mode

	OrchestratorURL string
	WebhookURL      string
	AuthURL         string
	// WebhookAPIKey is the CI ingress key the fixture presents to
	// WebhookService/SubmitReleaseBundle (REQ-011 §562, TASK-102). The webhook
	// ingress is authenticated, so a missing key fails the seed with a clear
	// error instead of an opaque 401.
	WebhookAPIKey string

	DataDir string

	AdminUser        string
	AdminPassword    string // optional override; falls back to credentials file
	DeployerUser     string
	DeployerPassword string // optional override; falls back to credentials file
	ReaderPassword   string // optional override; generated in local mode
	// E2ERunnerPassword is the e2e-runner (release_admin) password
	// (REQ-066 下游义务, 批次4 D1/D3); optional override, generated in local
	// mode, env-injected as E2E_RUNNER_PASSWORD in ci mode.
	E2ERunnerPassword string

	TrustEnvironment    string
	TrustRootPrivateKey string // CI mode: PEM-encoded Ed25519 private key

	FixtureVersion string
	ChartDir       string

	InstallTimeout    time.Duration
	InstallPollPeriod time.Duration

	// OperatorOnlineTimeout bounds the operator-session-online wait during
	// verify (AC-065-18/28); SeedRetries bounds phase-write retries with
	// 1s/2s/4s exponential backoff (AC-065-19/28). Zero falls back to the
	// package defaults.
	OperatorOnlineTimeout time.Duration
	SeedRetries           int

	// StopAfterPhase ends the run cleanly once the named phase has been
	// committed (no error, no partial marker). The lifecycle module uses
	// `enrollment` to split the seed: it generates the tokens first,
	// deploys/injects them into the customer agent clusters, then re-runs
	// devseed to resume from the install phase (progress/resume contract).
	StopAfterPhase string

	Logger *slog.Logger
	Now    func() time.Time // test hook; defaults to time.Now

	// DatabaseDSN opens the PostgreSQL schema for Reset. ReleaseNotifierDSN
	// is optional and skipped when empty.
	DatabaseDSN        string
	ReleaseNotifierDSN string

	// MigrationsFactory opens the schema-migration seam used by Reset.
	// Tests inject a fake; production uses NewPostgresMigrations.
	MigrationsFactory func(dsn string) (Migrations, error)
}

Config carries every knob for the seed runner. Zero values fall back to defaults; secrets left empty are resolved from data/dev-credentials.env (local mode, reuse-or-generate) or fail in CI mode.

type CustomerRef

type CustomerRef struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

CustomerRef is the manifest entry for one seeded customer.

type DefinitionRef

type DefinitionRef struct {
	ID               string `json:"id"`
	ValuesRevisionID string `json:"values_revision_id"`
	BundleID         string `json:"bundle_id"`
}

DefinitionRef is the manifest entry for one seeded release definition.

type Manifest

type Manifest struct {
	FixtureVersion string                   `json:"fixture_version"`
	GeneratedAt    string                   `json:"generated_at"`
	Customers      map[string]CustomerRef   `json:"customers"`
	Clusters       map[string]ClusterRef    `json:"clusters"`
	Routes         map[string]RouteRef      `json:"routes"`
	Operators      map[string]OperatorRef   `json:"operators"`
	Definitions    map[string]DefinitionRef `json:"definitions"`
	Bundle         BundleRef                `json:"bundle"`
}

Manifest is the runtime identity manifest written to data/dev-fixture.json (REQ-065): stable logical keys mapping to the server-generated identifiers that later stages (REQ-066) reference.

func Reset

func Reset(ctx context.Context, cfg Config) (*Manifest, error)

Reset rebuilds the databases and re-seeds every phase, ignoring the fixture version check (force rebuild). On failure the progress file is marked "partial": true with its phases structure preserved; the caller's shell layer owns pg_restore recovery.

func Run

func Run(ctx context.Context, cfg Config) (*Manifest, error)

Run seeds the full fixture idempotently and returns the runtime manifest. When every phase is already committed, Run issues no write RPC, logs "fixture up-to-date" (AC-065-03), and returns the existing manifest.

type Migrations

type Migrations interface {
	// DownAll rolls every applied migration down to the baseline.
	DownAll(ctx context.Context) error
	// Up applies all pending migrations.
	Up(ctx context.Context) error
	// Close releases the database handle.
	Close() error
}

Migrations is the schema-migration seam used by Reset. Production uses postgresMigrations; tests inject a fake to exercise the reset state machine without a live PostgreSQL instance.

func NewPostgresMigrations

func NewPostgresMigrations(dsn string) (Migrations, error)

NewPostgresMigrations opens the PostgreSQL database at dsn and returns the migration seam backed by internal/postgres RunMigrations/RunMigrationsDown over the embedded migration FS (SDK-only — no pg_dump/pg_restore/kubectl here; the shell layer owns those).

type Mode

type Mode string

Mode selects the credential/secret handling profile (REQ-065).

const (
	// ModeLocal writes credentials and the dev trust root key to disk.
	ModeLocal Mode = "local"
	// ModeCI injects credentials and the trust root key from the environment
	// and never writes secret material to disk.
	ModeCI Mode = "ci"
)

type OperatorRef

type OperatorRef struct {
	ID         string `json:"id"`
	ClusterKey string `json:"cluster_key"`
}

OperatorRef is the manifest entry for one seeded cluster's operator agent.

The operator id is minted by the orchestrator when the agent enrolls, so it cannot be derived from a logical key; the manifest publishes the id observed ONLINE during the enrollment wait. The REQ-066 control-plane stage needs it because GetActiveOperatorSession selects a session by operator id (AC-066-17).

type OrchestratorClient

type OrchestratorClient interface {
	// identity
	ListCustomers(context.Context, *connect.Request[orchestratorv1.ListCustomersRequest]) (*connect.Response[orchestratorv1.ListCustomersResponse], error)
	CreateCustomer(context.Context, *connect.Request[orchestratorv1.CreateCustomerRequest]) (*connect.Response[orchestratorv1.CreateCustomerResponse], error)
	GetCluster(context.Context, *connect.Request[orchestratorv1.GetClusterRequest]) (*connect.Response[orchestratorv1.GetClusterResponse], error)
	CreateCluster(context.Context, *connect.Request[orchestratorv1.CreateClusterRequest]) (*connect.Response[orchestratorv1.CreateClusterResponse], error)
	// routing
	ConfigureClusterRoute(context.Context, *connect.Request[orchestratorv1.ConfigureClusterRouteRequest]) (*connect.Response[orchestratorv1.ConfigureClusterRouteResponse], error)
	GetClusterRoutes(context.Context, *connect.Request[orchestratorv1.GetClusterRoutesRequest]) (*connect.Response[orchestratorv1.GetClusterRoutesResponse], error)
	// values
	ListReleaseDefinitions(context.Context, *connect.Request[orchestratorv1.ListReleaseDefinitionsRequest]) (*connect.Response[orchestratorv1.ListReleaseDefinitionsResponse], error)
	CreateReleaseDefinition(context.Context, *connect.Request[orchestratorv1.CreateReleaseDefinitionRequest]) (*connect.Response[orchestratorv1.CreateReleaseDefinitionResponse], error)
	CreateValuesRevision(context.Context, *connect.Request[orchestratorv1.CreateValuesRevisionRequest]) (*connect.Response[orchestratorv1.CreateValuesRevisionResponse], error)
	ListValuesRevisions(context.Context, *connect.Request[orchestratorv1.ListValuesRevisionsRequest]) (*connect.Response[orchestratorv1.ListValuesRevisionsResponse], error)
	SubmitValuesRevision(context.Context, *connect.Request[orchestratorv1.SubmitValuesRevisionRequest]) (*connect.Response[orchestratorv1.ValuesRevisionDecisionResponse], error)
	ApproveValuesRevision(context.Context, *connect.Request[orchestratorv1.ApproveValuesRevisionRequest]) (*connect.Response[orchestratorv1.ValuesRevisionDecisionResponse], error)
	// enrollment
	CreateEnrollmentToken(context.Context, *connect.Request[orchestratorv1.CreateEnrollmentTokenRequest]) (*connect.Response[orchestratorv1.CreateEnrollmentTokenResponse], error)
	// operator session online check (AC-065-18)
	ListOperators(context.Context, *connect.Request[orchestratorv1.ListOperatorsRequest]) (*connect.Response[orchestratorv1.ListOperatorsResponse], error)
	// install
	CreateOperation(context.Context, *connect.Request[orchestratorv1.CreateOperationRequest]) (*connect.Response[orchestratorv1.CreateOperationResponse], error)
	GetOperation(context.Context, *connect.Request[orchestratorv1.GetOperationRequest]) (*connect.Response[orchestratorv1.GetOperationResponse], error)
}

OrchestratorClient is the orchestrator seam covering every entity the seed creates. Methods are grouped by phase in the code comments.

type RouteRef

type RouteRef struct {
	ID         string `json:"id"`
	ClusterKey string `json:"cluster_key"`
}

RouteRef is the manifest entry for one seeded artifact route.

Routes are cluster-scoped: the public ClusterRoute surface carries no release-definition identity, so a route is never attributed to a definition. The manifest publishes them because the REQ-066 identity expectation asserts a route count (AC-066-29) and no other input source exposes one.

type TrustClient

TrustClient is the trust service seam (trust phase).

type WebhookClient

WebhookClient is the webhook service seam (bundle phase).

Jump to

Keyboard shortcuts

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