pub struct AllocationStatus {
pub phase: AllocationPhase,
pub phase_since: Option<DateTime<Utc>>,
pub bound_pool: Option<AllocationRef>,
pub assigned_process: Option<AllocationRef>,
pub allocated_at: Option<DateTime<Utc>>,
pub expires_at: Option<DateTime<Utc>>,
pub message: Option<String>,
pub conditions: Vec<AllocationCondition>,
}Expand description
EphemeralAllocation.status — observed allocation state.
Fields§
§phase: AllocationPhaseCurrent lifecycle phase.
phase_since: Option<DateTime<Utc>>When the phase last changed.
bound_pool: Option<AllocationRef>Pool that owns the matched member. Set as soon as routing resolves; not cleared on release (audit trail).
assigned_process: Option<AllocationRef>The Process backing this allocation, if Bound.
allocated_at: Option<DateTime<Utc>>When the allocation was matched to a Process.
expires_at: Option<DateTime<Utc>>Wall-clock expiry derived from spec.ttl + allocated_at.
The pool reconciler force-returns the member at this point.
message: Option<String>Operator-visible message.
conditions: Vec<AllocationCondition>Standard Conditions.
The empty case is skipped at serialization so a merge-patch
body built from a caller-supplied AllocationStatus whose
conditions slot has not been touched does NOT emit
"conditions": [] on the wire — under RFC-7396 JSON Merge
Patch (the shape Patch::Merge sends) an empty array
REPLACES the persisted list rather than merges into it, so a
controller round-trip that reused a scratch AllocationStatus
as a patch body would silently clobber whatever conditions the
prior status carried. Peer to phase_since /
bound_pool / assigned_process / allocated_at /
expires_at above, each already skip-serialized on its
Default-equivalent variant.
Implementations§
Source§impl AllocationStatus
impl AllocationStatus
Sourcepub fn transition(
phase: AllocationPhase,
message: impl Into<String>,
now: DateTime<Utc>,
) -> Self
pub fn transition( phase: AllocationPhase, message: impl Into<String>, now: DateTime<Utc>, ) -> Self
Substrate composer for a phase-transition AllocationStatus
seed: stamps the THREE always-present slots (phase +
phase_since = Some(now) + message = Some(<supplied>)) and
defaults every other slot (bound_pool / assigned_process /
allocated_at / expires_at = None, conditions = vec![]).
Caller-branches attach the extra slots via struct-update
syntax onto the seed.
Pre-lift the 4-slot phase-transition seed
json!({
"status": {
"phase": <AllocationPhase-variant>,
"phaseSince": Utc::now(),
"message": "<transition-reason>",
…optional caller-attached slots…
}
})was hand-authored at FOUR sites past the ★★ PRIME-DIRECTIVE
≥ 2 duplication threshold in
tatara-pool-reconciler::controller_allocation::reconcile_inner,
each restating the SAME phase + phase_since + message invariant
triplet on a different AllocationPhase variant:
AllocationDecision::NoMatchingPool— the “no Pool selector matched this Requestor” fallthrough (AllocationPhase::NoMatchingPool).AllocationDecision::Wait— the “pool matched; no Free member available” queued path (AllocationPhase::Queued) with abound_pooladdition.AllocationDecision::Bind— the “bound to pool member” allocation path (AllocationPhase::Bound) withbound_pool+assigned_process+allocated_at+expires_atadditions.AllocationDecision::Release— the “released; pool reconciler will return the member” release path (AllocationPhase::Released) withbound_pool+assigned_processadditions.
All four hand-authored the SAME phaseSince: Utc::now() stamp
alongside the phase transition, and all four spelled the
invariant triplet as bare JSON keys inside a json!({...})
literal — a fragile shape where any drift in the underlying
AllocationStatus field naming (a rename from phaseSince
to phase_since at the serde surface, a promotion of message
to a structured envelope) silently stops the JSON keys from
mapping to the typed struct’s fields and the K8s API server
merges an ill-shaped patch. Post-lift the four callers build a
typed AllocationStatus via AllocationStatus::transition,
attach any branch-specific slots via struct-update syntax, and
wrap the result in json!({ "status": s }) — the serde
rename_all = "camelCase" derive on AllocationStatus owns
the wire-shape composition, so a field rename lands at ONE
site (the derive) and every emit site inherits the upgrade
mechanically.
Cross-CRD peer to crate::pool::PoolStatus::observed on the
same <CRD>Status substrate-composer axis — both primitives
stamp phase_since = Some(now) from a caller-supplied now
timestamp so the composer stays clock-injectable rather than
implicitly reading wall time, and both close every optional slot
with its Default-equivalent variant so a future slot
addition on either status shape plugs into the composer at ONE
site and every downstream emit site inherits the new slot
mechanically.
Cross-CRD peer to the tatara-reconciler::patch::phase_status_msg
primitive on the (CRD × phase-transition-with-message) axis —
both primitives own the three-slot phase + phase_since + message invariant on their respective CRDs’ status subresource,
and both accept impl Into<String> for the message so the
callsite carries &'static str literal reasons and
format!(...)-owned strings without widening the signature.
Theory anchor: THEORY.md §VI.1 (generation over composition —
the 4-slot phase-transition status-seed incantation recurred at
four hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
duplication trigger, and is lifted to ONE owner here).
THEORY.md §II.1 invariant 5 (composition preserves proofs —
the pins bind the three always-present slots + the
Default-defaulted rest + byte-identical parity with the
pre-lift json!({...}) triplet through serde round-trip, so a
regression that drifted any surface at
tests::allocation_status_transition_* rather than as silent
operator-visible skew between the four allocation-decision
patch sites).
Sourcepub fn bound_transition(
phase: AllocationPhase,
message: impl Into<String>,
now: DateTime<Utc>,
bound_pool: AllocationRef,
assigned_process: AllocationRef,
) -> Self
pub fn bound_transition( phase: AllocationPhase, message: impl Into<String>, now: DateTime<Utc>, bound_pool: AllocationRef, assigned_process: AllocationRef, ) -> Self
Substrate composer for a phase-transition AllocationStatus
seed whose bound_pool + assigned_process axis-pair is
stamped alongside the base Self::transition triplet
(phase + phase_since = Some(now) + message = Some(<supplied>)). Every other slot lands at its
Default-equivalent variant so a caller-branch that attaches
an optional slot via struct-update syntax (a Bind arm’s
allocated_at / expires_at addenda, say) does not silently
inherit a pre-populated non-None value.
Pre-lift the bound_pool: Some(pool) + assigned_process: Some(AllocationRef::new(name, ns)) pair rode struct-update
syntax onto Self::transition at TWO sites past the ★★
PRIME-DIRECTIVE ≥ 2 duplication threshold in
tatara-pool-reconciler::controller_allocation::reconcile_inner
— the AllocationDecision::Bind arm (AllocationPhase::Bound
with two extra allocated_at / expires_at addenda) and the
AllocationDecision::Release arm (AllocationPhase::Released
with no addenda). Both restated the SAME pair-of-Some-slot
invariant against the SAME struct-update seed and funneled the
resulting body through the SAME patch_status call on
Api<EphemeralAllocation>. Post-lift both callers reach the
pair through ONE substrate composer; a future normalization on
the bound-set axis (a symmetry gate that the assigned_process’s
namespace matches the bound_pool’s namespace, a canonicalization
that closes the pair against a stale audit record, a
backwards-compatibility rename of either slot at the serde
surface) lands at ONE substrate site rather than at each
callsite in the two-arm allocation reconciler.
Composes atop Self::transition so any future evolution to
the base three-slot invariant triplet (a phase_since rename,
a message promotion to a structured envelope, a fourth
always-stamped diagnostic slot) reaches this composer through
ONE substrate site and both consumers inherit the upgrade
mechanically. Sibling composition discipline to
crate::pool::PoolStatus::observed’s state_count_fanout +
Utc::now() fold — the compound composer names its axis + calls
the substrate primitive on the invariant it wraps rather than
restating the wrapped shape inline.
Theory anchor: THEORY.md §VI.1 (generation over composition —
the bound_pool + assigned_process pair recurred at two hand-
authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
trigger, and is lifted to ONE owner here). THEORY.md §II.1
invariant 5 (composition preserves proofs — the pins bind the
pair + the composed base triplet + byte-identical parity with
the pre-lift struct-update shape through serde round-trip, so a
regression that drifted any surface at
tests::allocation_status_bound_transition_* rather than as
silent operator-visible skew between the two Bind / Release
patch sites).
Trait Implementations§
Source§impl Clone for AllocationStatus
impl Clone for AllocationStatus
Source§fn clone(&self) -> AllocationStatus
fn clone(&self) -> AllocationStatus
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AllocationStatus
impl Debug for AllocationStatus
Source§impl Default for AllocationStatus
impl Default for AllocationStatus
Source§fn default() -> AllocationStatus
fn default() -> AllocationStatus
Source§impl<'de> Deserialize<'de> for AllocationStatus
impl<'de> Deserialize<'de> for AllocationStatus
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for AllocationStatus
impl JsonSchema for AllocationStatus
Source§fn schema_name() -> String
fn schema_name() -> String
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn is_referenceable() -> bool
fn is_referenceable() -> bool
$ref keyword. Read moreAuto Trait Implementations§
impl Freeze for AllocationStatus
impl RefUnwindSafe for AllocationStatus
impl Send for AllocationStatus
impl Sync for AllocationStatus
impl Unpin for AllocationStatus
impl UnsafeUnpin for AllocationStatus
impl UnwindSafe for AllocationStatus
Blanket Implementations§
impl<T> AppData for Twhere
T: OptionalSend + OptionalSync + 'static + OptionalSerde,
impl<T> AppDataResponse for Twhere
T: OptionalSend + OptionalSync + 'static + OptionalSerde,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> OptionalSend for T
impl<T> OptionalSync for T
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);