staircase 0.0.7

Kubernetes Step-based Operator
Documentation
//! Step-based controller building blocks.
//!
//! This module helps you build reconcilers that split one reconcile run into
//! ordered steps. Each step verifies one fix, applies at most one meaningful
//! modification, and then lets the next run observe fresh state.
mod plan;
mod reconciler;
mod run;
mod status;
mod step;

pub use plan::{BoxPlan, JoinSteps, Plan, PlanFuture, RunError, RunPlan, StepFailure};
pub use reconciler::{Reconciler, RunReconcilerConfig, run};
pub use run::{RunOutcome, RunStepConfig, run_plan};
pub use status::{KubeStatusUpdater, StatusUpdater};
pub use step::{
    Immutable, ImmutableStep, Mutable, MutableStep, MutableStepOutcome, MutableStepResult, RunContext, Step, StepFn,
    StepMode, StepOutcome, StepResult, immutable_step, mutable_step,
};

#[cfg(doctest)]
mod compile_fail_tests {
    /// ```compile_fail
    /// # use kube::CustomResource;
    /// # use schemars::JsonSchema;
    /// # use serde::{Deserialize, Serialize};
    /// # use staircase::controller::{Immutable, MutableStepOutcome, MutableStepResult, RunContext, Step};
    /// # #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
    /// # #[kube(group = "tests.staircase.dev", version = "v1", kind = "BadResource", status = "BadStatus", namespaced)]
    /// # struct BadSpec {}
    /// # #[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
    /// # struct BadStatus {}
    /// struct BadStep;
    ///
    /// impl Step for BadStep {
    ///     type Error = ();
    ///     type InData = ();
    ///     type Mode = Immutable;
    ///     type OutData = ();
    ///     type Resource = BadResource;
    ///
    ///     async fn run(
    ///         &self,
    ///         _: &RunContext<Self::Resource>,
    ///         _: Self::InData,
    ///     ) -> MutableStepResult<Self::Resource, Self::OutData, Self::Error> {
    ///         Ok(MutableStepOutcome::Modified { status: None })
    ///     }
    /// }
    /// ```
    struct ImmutableStepCannotReturnMutableOutcome;

    /// ```compile_fail
    /// # use kube::CustomResource;
    /// # use schemars::JsonSchema;
    /// # use serde::{Deserialize, Serialize};
    /// # use staircase::controller::{
    /// #     Immutable, Mutable, MutableStepOutcome, MutableStepResult, Plan, RunContext, Step, StepOutcome, StepResult,
    /// # };
    /// # #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
    /// # #[kube(group = "tests.staircase.dev", version = "v1", kind = "JoinResource", status = "JoinStatus", namespaced)]
    /// # struct JoinSpec {}
    /// # #[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
    /// # struct JoinStatus {}
    /// struct Load;
    /// struct Create;
    ///
    /// impl Step for Load {
    ///     type Error = ();
    ///     type InData = ();
    ///     type Mode = Immutable;
    ///     type OutData = ();
    ///     type Resource = JoinResource;
    ///
    ///     async fn run(
    ///         &self,
    ///         _: &RunContext<Self::Resource>,
    ///         data: Self::InData,
    ///     ) -> StepResult<Self::OutData, Self::Error> {
    ///         Ok(StepOutcome::NoModification { data })
    ///     }
    /// }
    ///
    /// impl Step for Create {
    ///     type Error = ();
    ///     type InData = ();
    ///     type Mode = Mutable;
    ///     type OutData = ();
    ///     type Resource = JoinResource;
    ///
    ///     async fn run(
    ///         &self,
    ///         _: &RunContext<Self::Resource>,
    ///         data: Self::InData,
    ///     ) -> MutableStepResult<Self::Resource, Self::OutData, Self::Error> {
    ///         Ok(MutableStepOutcome::NoModification { data })
    ///     }
    /// }
    ///
    /// let _ = Plan::from(Load).join((Create, Load));
    /// ```
    struct JoinCannotAcceptMutableStep;

    /// ```compile_fail
    /// # use kube::CustomResource;
    /// # use schemars::JsonSchema;
    /// # use serde::{Deserialize, Serialize};
    /// # use staircase::controller::{
    /// #     Immutable, Mutable, MutableStepOutcome, MutableStepResult, Plan, RunContext, Step, StepOutcome, StepResult,
    /// # };
    /// # #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
    /// # #[kube(group = "tests.staircase.dev", version = "v1", kind = "JoinMapResource", status = "JoinMapStatus", namespaced)]
    /// # struct JoinMapSpec {}
    /// # #[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
    /// # struct JoinMapStatus {}
    /// struct Load;
    /// struct Create;
    ///
    /// impl Step for Load {
    ///     type Error = ();
    ///     type InData = ();
    ///     type Mode = Immutable;
    ///     type OutData = ();
    ///     type Resource = JoinMapResource;
    ///
    ///     async fn run(
    ///         &self,
    ///         _: &RunContext<Self::Resource>,
    ///         data: Self::InData,
    ///     ) -> StepResult<Self::OutData, Self::Error> {
    ///         Ok(StepOutcome::NoModification { data })
    ///     }
    /// }
    ///
    /// impl Step for Create {
    ///     type Error = ();
    ///     type InData = ();
    ///     type Mode = Mutable;
    ///     type OutData = ();
    ///     type Resource = JoinMapResource;
    ///
    ///     async fn run(
    ///         &self,
    ///         _: &RunContext<Self::Resource>,
    ///         data: Self::InData,
    ///     ) -> MutableStepResult<Self::Resource, Self::OutData, Self::Error> {
    ///         Ok(MutableStepOutcome::NoModification { data })
    ///     }
    /// }
    ///
    /// let _ = Plan::from(Load).join_map((Create, Load), |(_, data)| data);
    /// ```
    struct JoinMapCannotAcceptMutableStep;

    /// ```compile_fail
    /// # use staircase::controller::{Plan, RunPlan};
    /// # use kube::CustomResource;
    /// # use schemars::JsonSchema;
    /// # use serde::{Deserialize, Serialize};
    /// # #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
    /// # #[kube(group = "tests.staircase.dev", version = "v1", kind = "PlanNodeResource", status = "PlanNodeStatus", namespaced)]
    /// # struct PlanNodeSpec {}
    /// # #[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
    /// # struct PlanNodeStatus {}
    /// let _ = staircase::controller::plan::Empty::<PlanNodeResource, (), ()> {
    ///     _marker: std::marker::PhantomData,
    /// };
    /// ```
    struct PlanNodesCannotBeConstructedThroughPrivateModule;

    /// ```compile_fail
    /// # use staircase::controller::Plan;
    /// # use kube::CustomResource;
    /// # use schemars::JsonSchema;
    /// # use serde::{Deserialize, Serialize};
    /// # #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
    /// # #[kube(group = "tests.staircase.dev", version = "v1", kind = "PlanEmptyResource", status = "PlanEmptyStatus", namespaced)]
    /// # struct PlanEmptySpec {}
    /// # #[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
    /// # struct PlanEmptyStatus {}
    /// let plan = Plan::empty::<PlanEmptyResource, (), ()>();
    /// let _inner = plan.inner;
    /// ```
    struct PlanInnerCannotBeAccessed;
}