pub struct MoverSpec {
pub resources: Option<ResourceRequirements>,
pub cache: Option<CacheDefaults>,
pub security_context: Option<SecurityContext>,
pub pod_security_context: Option<PodSecurityContext>,
pub privileged_mode: Option<bool>,
pub inherit_security_context_from: Option<InheritSecurityContextFrom>,
pub ttl_seconds_after_finished: Option<i64>,
}Expand description
Per-recipe mover overrides (resources, cache, security context).
Fields§
§resources: Option<ResourceRequirements>Resource requests/limits for the mover container.
cache: Option<CacheDefaults>Override the repository’s CacheDefaults for this recipe’s movers.
security_context: Option<SecurityContext>Container security context for the mover; merged field-wise over the hardened base,
moverDefaults, and any inherited context — this is the highest layer, so every field
set here wins. Combines with inheritSecurityContextFrom: fields you set override the
workload’s, fields you omit are inherited, and this context stands in alone when
inheritance cannot resolve a pod.
pod_security_context: Option<PodSecurityContext>Pod security context for the mover (notably fsGroup for group-writable restore
volumes). Same layering as securityContext: highest layer, merged field-wise, and
combinable with inheritSecurityContextFrom.
privileged_mode: Option<bool>Opt-in, namespace-gated privileged mode. Never changes the UID. When the mover runs
as root (runAsUser: 0), adds the capabilities the operation needs on top of
drop: [ALL]: DAC_OVERRIDE for a backup (read files owned by any uid/gid);
CHOWN, DAC_OVERRIDE, FOWNER, FSETID for a restore (reproduce original
ownership). Grants nothing for maintenance, or when the mover does not run as
root (capabilities are inert for non-root); set runAsUser: 0 yourself.
inherit_security_context_from: Option<InheritSecurityContextFrom>Copy the UID/GID security context from a live workload rather than hard-coding it.
Requires the workload to pin runAsUser (container or pod level): a UID that comes
from the container image’s USER line is invisible in the pod spec and cannot be
inherited — the mover would silently run as its own image’s UID instead.
May be combined with securityContext/podSecurityContext, which override it
field-wise and act as the fallback when no workload pod can be resolved.
ttl_seconds_after_finished: Option<i64>Per-recipe override of Job.spec.ttlSecondsAfterFinished so finished Jobs self-GC.
Implementations§
Source§impl MoverSpec
impl MoverSpec
Sourcepub fn requires_privilege(&self) -> bool
pub fn requires_privilege(&self) -> bool
Whether this mover requests elevated privileges that the workload
namespace must explicitly opt into (ADR §4.11/§G16). True when
privilegedMode is set, or the securityContext runs as root / privileged
/ with escalation / with added Linux capabilities.
The rationale is the same as VolSync’s privileged-movers model: the
controller mints a mover ServiceAccount in the workload namespace, and a
tenant with access there could reuse it to run pods at the mover’s privilege.
Granting an elevated mover is therefore a per-namespace admin decision, gated
by a namespace annotation rather than allowed implicitly. Pure + exhaustive
so the definition of “privileged” lives in one tested place.
Sourcepub fn privileged_mode_warning(&self, op: MoverOperation) -> Option<String>
pub fn privileged_mode_warning(&self, op: MoverOperation) -> Option<String>
Admission-time warning when privilegedMode: true would certainly grant nothing:
this spec pins a non-zero runAsUser (capabilities are inert for non-root, and
privilegedMode never picks a UID).
Judged on hardened ⊂ self only. A spec with no runAsUser stays silent: the
repository’s moverDefaults may pin runAsUser: 0 and is invisible here, so
warning would be a false positive. The controller’s PrivilegedModeInert Event,
which sees the merged context, reports that case. An inheritSecurityContextFrom
identity resolves at reconcile time, so it stays silent too.
Sourcepub fn merge_over(&self, base: Option<&MoverSpec>) -> MoverSpec
pub fn merge_over(&self, base: Option<&MoverSpec>) -> MoverSpec
Overlay self — the HIGHER layer — onto base, field by field, producing
one MoverSpec that stands in for both. This is what lets an invocation carry
its own mover overrides on top of a shared, GitOps-managed recipe:
Snapshot.spec.mover merged over SnapshotPolicy.spec.mover (#464).
The merge delegates to the SAME primitives the repository-layer merge uses, so a per-run override can never resolve differently from a per-recipe one:
securityContext/podSecurityContextgo throughmerge_context_pairas one(container, pod)layer pair — field-wise per dimension plus identity promotion, so a policy’s container-levelrunAsUsercan never shadow a snapshot’s pod-level one. That merge is associative, so folding these two layers here and then handing the result toresolve_moveris identical to a flathardened ⊂ moverDefaults ⊂ inherited ⊂ policy ⊂ snapshotmerge.resourcesviamerge_resources_opt(per-key requests/limits).cacheviaCacheDefaults::merge(per-field).privilegedMode,ttlSecondsAfterFinishedandinheritSecurityContextFromare whole-value knobs with no inner structure to merge, so the higher layer’s value wins outright andNonefalls through tobase.
base: None is the identity: the result is self unchanged. Because the layer
order is fixed by this signature, a caller cannot accidentally invert it.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for MoverSpec
impl<'de> Deserialize<'de> for MoverSpec
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 MoverSpec
impl JsonSchema for MoverSpec
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 inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreimpl StructuralPartialEq for MoverSpec
Auto Trait Implementations§
impl Freeze for MoverSpec
impl RefUnwindSafe for MoverSpec
impl Send for MoverSpec
impl Sync for MoverSpec
impl Unpin for MoverSpec
impl UnsafeUnpin for MoverSpec
impl UnwindSafe for MoverSpec
Blanket Implementations§
§impl<T> AnyExt for T
impl<T> AnyExt for T
§fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
fn downcast_ref<T>(this: &Self) -> Option<&T>where
T: Any,
T behind reference§fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>where
T: Any,
T behind mutable reference§fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>where
T: Any,
T behind Rc pointer§fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>where
T: Any,
T behind Arc pointer§fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>where
T: Any,
T behind Box pointer§fn downcast_move<T>(this: Self) -> Option<T>
fn downcast_move<T>(this: Self) -> Option<T>
Self to T,
useful only in generic context as a workaround for specializationSource§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, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
impl<T, X> CoerceTo<T> for Xwhere
T: CoerceFrom<X> + ?Sized,
fn coerce_rc_to(self: Rc<X>) -> Rc<T>
fn coerce_box_to(self: Box<X>) -> Box<T>
fn coerce_ref_to(&self) -> &T
fn coerce_mut_to(&mut self) -> &mut T
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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 more