namespaces

package
v1.39.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: BSD-3-Clause Imports: 9 Imported by: 0

Documentation

Overview

Package namespaces owns the namespace control-plane state and exposes a typed domain API for callers that need direct existence checks. Lookups return the RAFT subcommand namespace type.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrBadRequest signals a malformed RAFT command payload or an invalid
	// argument so the apply path can classify it distinctly from
	// legitimate-but-rejected operations.
	ErrBadRequest = errors.New("bad request")

	// ErrAlreadyExists is returned by Create when a namespace with the given
	// name is already present. Callers that need a distinct status for
	// duplicates (e.g. an HTTP handler mapping to 409) should check with
	// errors.Is rather than string-matching the error message.
	ErrAlreadyExists = errors.New("namespace already exists")

	// ErrNotFound is returned by ChangeState and RemoveEntity when the
	// target namespace does not exist. Callers that need a distinct status
	// for missing entries (e.g. an HTTP handler mapping to 404) should
	// check with errors.Is.
	ErrNotFound = errors.New("namespace not found")

	// ErrNamespaceDeleting is returned when a create-like operation targets
	// a namespace that exists but is currently being torn down. Distinct
	// from ErrAlreadyExists so REST can render a different conflict message.
	ErrNamespaceDeleting = errors.New("namespace is being deleted")

	// ErrNamespaceGone is returned by apply-time checks when a namespace
	// the caller validated earlier no longer exists.
	ErrNamespaceGone = errors.New("namespace no longer exists")

	// ErrNamespaceNotEmpty is returned by RemoveEntity at the apply layer
	// when the namespace still owns classes, aliases, or DB users.
	ErrNamespaceNotEmpty = errors.New("namespace still has owned resources")

	// ErrInvalidState is a defense-in-depth sentinel for operations called
	// on a namespace whose current state forbids them (e.g. RemoveEntity on
	// an active namespace).
	ErrInvalidState = errors.New("namespace is in an invalid state for this operation")

	// ErrInvalidStateTransition is returned by ChangeState when the target
	// state is unreachable from the namespace's current state.
	ErrInvalidStateTransition = errors.New("invalid namespace state transition")

	// ErrNamespaceSuspended is returned when an operation targets a suspended
	// namespace.
	ErrNamespaceSuspended = errors.New("namespace is suspended")

	// ErrCollectionSuspended is returned when an operation targets a suspended
	// collection.
	ErrCollectionSuspended = errors.New("collection is suspended")

	// ErrNamespaceResuming is returned when an operation targets a namespace
	// that is resuming.
	ErrNamespaceResuming = errors.New("namespace is resuming")

	// ErrStateChangedConcurrently is returned by ChangeState when the stored
	// StateChangeIndex no longer matches the one the caller read before
	// proposing, meaning another state change applied in between. Callers
	// re-read and decide again rather than retrying blindly.
	ErrStateChangedConcurrently = errors.New("namespace state changed concurrently")
)

Functions

func PublicMessage added in v1.38.6

func PublicMessage(err error) (msg string, ok bool)

PublicMessage returns the user-facing text for a namespace lifecycle sentinel. Every caller outside the namespace-management API must render this instead of err: it names neither the namespace nor the concept. ok is false for errors that are not lifecycle sentinels, so callers keep the detail of a genuine internal failure.

func RequireActive added in v1.38.6

func RequireActive(e Exister, name string) error

RequireActive returns nil for an empty name or an active namespace, and the error for the namespace's actual state otherwise. Pass "" only for an entity that belongs to no namespace, never for one whose namespace is unknown.

func ValidateName

func ValidateName(name string) error

ValidateName enforces the package's naming contract. It is the single source of truth for namespace name validation and is called both from the REST handler (for fast 422 rejection without a RAFT round-trip) and from the apply path (as a defense-in-depth check).

Types

type Controller

type Controller struct {
	// contains filtered or unexported fields
}

Controller owns the namespace control-plane state.

Concurrency contract: hashicorp RAFT invokes Snapshot from a goroutine that may run concurrently with Apply, so the RLock inside Snapshot is load-bearing, not cosmetic. Applies are serialized by RAFT (write-lock semantics); queries take the read-lock. Do not remove the Snapshot RLock in a future refactor.

func NewController

func NewController(logger logrus.FieldLogger) *Controller

NewController returns an empty, ready-to-use controller.

func (*Controller) ChangeState

func (c *Controller) ChangeState(name string, target cmd.NamespaceState, sc StateChange) error

ChangeState transitions a namespace into target and records sc.AppliedIndex as the index of that flip. Same-state transitions are idempotent and leave the recorded index alone.

A nonzero sc.ExpectedIndex makes the flip conditional: refused with ErrStateChangedConcurrently unless the stored StateChangeIndex still matches, which stops a re-proposed command from undoing a later flip. It is checked after the same-state short-circuit, so re-applying a committed command still returns nil.

Returns ErrBadRequest when target is unknown or sc.AppliedIndex is 0, ErrNotFound for a missing namespace, and ErrInvalidStateTransition for a forbidden transition.

func (*Controller) Count

func (c *Controller) Count() int

Count returns the number of known namespaces. Used by the startup invariant check.

func (*Controller) Create

func (c *Controller) Create(ns cmd.Namespace, index uint64) error

Create inserts a namespace in the cmd.NamespaceStateActive state, recording index — the RAFT log index of the create command — as its StateChangeIndex. The input's State and StateChangeIndex are ignored, so a caller cannot choose either. HomeNodes must contain exactly one non-empty entry — downstream placement and counters rely on that invariant. Returns ErrBadRequest for invalid names, HomeNodes, or a zero index, ErrAlreadyExists when the name maps to an active namespace, and ErrNamespaceDeleting when the name is currently being torn down.

func (*Controller) Get

func (c *Controller) Get(names ...string) []cmd.Namespace

Get returns the named namespaces. An empty Names slice returns all known namespaces; otherwise only the named ones that exist are returned (missing names are silently omitted).

func (*Controller) GetNamespace

func (c *Controller) GetNamespace(name string) (ns cmd.Namespace, ok bool)

GetNamespace returns a snapshot copy of the namespace by name. ok is false when the namespace does not exist.

func (*Controller) List

func (c *Controller) List() []cmd.Namespace

List returns a snapshot copy of all namespaces. Intended for callers that need to iterate without holding the lock.

func (*Controller) ListDeleting

func (c *Controller) ListDeleting() []string

ListDeleting returns the names of namespaces currently in the deleting state, sorted lexicographically.

func (*Controller) RemoveEntity

func (c *Controller) RemoveEntity(name string) error

RemoveEntity removes the namespace map entry. Callable only on a namespace already marked for deletion; an active namespace returns ErrInvalidState. Returns ErrNotFound when the namespace does not exist.

func (*Controller) Restore

func (c *Controller) Restore(snapshot []byte) error

Restore replaces the current state with the snapshot contents. A nil or empty snapshot leaves state empty (fresh bootstrap). Unknown JSON fields are tolerated. Entries with empty State are normalized to cmd.NamespaceStateActive; entries with an unknown State return an error so a future binary's snapshot is not silently mis-classified. Entries missing the single HomeNodes entry are also rejected — there is no migration path from a pre-HomeNodes snapshot.

func (*Controller) Snapshot

func (c *Controller) Snapshot() ([]byte, error)

Snapshot serializes the entire namespace map. See the Controller godoc for why the read lock is required even though Apply is single-threaded.

func (*Controller) Update

func (c *Controller) Update(ns cmd.Namespace) error

Update overwrites the stored HomeNodes for an existing namespace. HomeNodes must contain exactly one non-empty entry; Name, State and StateChangeIndex are immutable here. Returns ErrBadRequest for an invalid HomeNodes, ErrNotFound when the namespace does not exist, and ErrNamespaceDeleting when the namespace is being torn down.

type Exister

type Exister interface {
	GetNamespace(name string) (cmd.Namespace, bool)
}

Exister exposes read-only access to namespace state. Callers that need to know whether a namespace is usable go through RequireActive rather than comparing State themselves.

type MockExister

type MockExister struct {
	mock.Mock
}

MockExister is an autogenerated mock type for the Exister type

func NewMockExister

func NewMockExister(t interface {
	mock.TestingT
	Cleanup(func())
}) *MockExister

NewMockExister creates a new instance of MockExister. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. The first argument is typically a *testing.T value.

func (*MockExister) EXPECT

func (_m *MockExister) EXPECT() *MockExister_Expecter

func (*MockExister) GetNamespace

func (_m *MockExister) GetNamespace(name string) (api.Namespace, bool)

GetNamespace provides a mock function with given fields: name

type MockExister_Expecter

type MockExister_Expecter struct {
	// contains filtered or unexported fields
}

func (*MockExister_Expecter) GetNamespace

func (_e *MockExister_Expecter) GetNamespace(name interface{}) *MockExister_GetNamespace_Call

GetNamespace is a helper method to define mock.On call

  • name string

type MockExister_GetNamespace_Call

type MockExister_GetNamespace_Call struct {
	*mock.Call
}

MockExister_GetNamespace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetNamespace'

func (*MockExister_GetNamespace_Call) Return

func (*MockExister_GetNamespace_Call) Run

func (*MockExister_GetNamespace_Call) RunAndReturn

type StateChange added in v1.38.7

type StateChange struct {
	// AppliedIndex is this apply's RAFT log index. A successful flip stores
	// it as the namespace's new StateChangeIndex.
	AppliedIndex uint64
	// ExpectedIndex is the StateChangeIndex the flip requires the namespace
	// to still be at. 0 skips the check.
	ExpectedIndex uint64
}

StateChange carries the two RAFT indexes a state flip needs: one is written, the other is compared. Named fields rather than two uint64 parameters, which a caller could swap without the compiler noticing.

Jump to

Keyboard shortcuts

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