Trait peace_cfg::Item

source ·
pub trait Item: DynClone {
    type Error: Error + Send + Sync;
    type State: Clone + Debug + Display + PartialEq + Serialize + DeserializeOwned + Send + Sync + 'static;
    type StateDiff: Clone + Debug + Display + Serialize + DeserializeOwned + Send + Sync + 'static;
    type Params<'exec>: Params<Spec = ParamsSpec<Self::Params<'exec>>> + Clone + Debug + Serialize + DeserializeOwned + Send + Sync + 'static;
    type Data<'exec>: Data<'exec>;

    // Required methods
    fn id(&self) -> &ItemId;
    fn setup<'life0, 'life1, 'async_trait>(
        &'life0 self,
        resources: &'life1 mut Resources<Empty>
    ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn try_state_current<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params_partial: &'life1 <Self::Params<'life2> as Params>::Partial,
        data: Self::Data<'life3>
    ) -> Pin<Box<dyn Future<Output = Result<Option<Self::State>, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait;
    fn state_current<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params: &'life1 Self::Params<'life2>,
        data: Self::Data<'life3>
    ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait;
    fn try_state_goal<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params_partial: &'life1 <Self::Params<'life2> as Params>::Partial,
        data: Self::Data<'life3>
    ) -> Pin<Box<dyn Future<Output = Result<Option<Self::State>, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait;
    fn state_goal<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params: &'life1 Self::Params<'life2>,
        data: Self::Data<'life3>
    ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait;
    fn state_diff<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
        params_partial: &'life0 <Self::Params<'life1> as Params>::Partial,
        data: Self::Data<'life2>,
        state_a: &'life3 Self::State,
        state_b: &'life4 Self::State
    ) -> Pin<Box<dyn Future<Output = Result<Self::StateDiff, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait,
             'life4: 'async_trait;
    fn state_clean<'life0, 'life1, 'life2, 'async_trait>(
        params_partial: &'life0 <Self::Params<'life1> as Params>::Partial,
        data: Self::Data<'life2>
    ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;
    fn apply_check<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'async_trait>(
        params: &'life0 Self::Params<'life1>,
        data: Self::Data<'life2>,
        state_current: &'life3 Self::State,
        state_target: &'life4 Self::State,
        diff: &'life5 Self::StateDiff
    ) -> Pin<Box<dyn Future<Output = Result<ApplyCheck, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait,
             'life4: 'async_trait,
             'life5: 'async_trait;
    fn apply_dry<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params: &'life1 Self::Params<'life2>,
        data: Self::Data<'life3>,
        state_current: &'life4 Self::State,
        state_target: &'life5 Self::State,
        diff: &'life6 Self::StateDiff
    ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait,
             'life4: 'async_trait,
             'life5: 'async_trait,
             'life6: 'async_trait;
    fn apply<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
        fn_ctx: FnCtx<'life0>,
        params: &'life1 Self::Params<'life2>,
        data: Self::Data<'life3>,
        state_current: &'life4 Self::State,
        state_target: &'life5 Self::State,
        diff: &'life6 Self::StateDiff
    ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait,
             'life4: 'async_trait,
             'life5: 'async_trait,
             'life6: 'async_trait;
}
Expand description

Defines all of the data and logic to manage an item.

The item may be simple or complex, ranging from:

  • File download.
  • Application installation.
  • Server launching / initialization.
  • Multiple cloud resource management.

The lifecycle functions include:

  1. Status discovery.
  2. Execution.
  3. Backup.
  4. Restoration.
  5. Clean up / deletion.

Since the latter four functions are write-operations, their specification includes a dry run function.

§Logical IDs vs Physical IDs

A logical ID is defined by code, and does not change. A physical ID is one generated during execution, which may be random or computed.

§Examples

The following are examples of logical IDs and corresponding physical IDs:

  • If the function creates a file, the ID may be the full file path, or it may be the file name, assuming the file path may be deduced by the clean up logic from Data.

  • If the function instantiates a virtual machine on a cloud platform, this may be the ID of the instance so that it may be terminated.

Logical IDPhysical ID
app.file_path/mnt/data/app.zip
app_server_instance_idef34a9a4-0c02-45a6-96ec-a4db06d4980c
app_server.address10.0.0.1

Required Associated Types§

source

type Error: Error + Send + Sync

Consumer provided error type.

source

type State: Clone + Debug + Display + PartialEq + Serialize + DeserializeOwned + Send + Sync + 'static

Summary of the managed item’s state.

For an extensive explanation of state, and how to define it, please see the state concept as well as the State type.

This type is used to represent the current state of the item (if it exists), the goal state of the item (what is intended to exist), and is used in the diff calculation – what is the difference between the current and goal states.

§Examples
  • A file’s state may be its path, and a hash of its contents.
  • A server’s state may be its operating system, CPU and memory capacity, IP address, and ID.
source

type StateDiff: Clone + Debug + Display + Serialize + DeserializeOwned + Send + Sync + 'static

Diff between the current and target States.

§Design Note

Initially I thought the field-wise diff between two States is suitable, but:

  • Externally controlled state may not be known ahead of time.
  • It isn’t easy or necessarily goal to compare every single field.
  • state.apply(diff) = state_goal may not be meaningful for a field level diff, and the apply may be a complex process.
source

type Params<'exec>: Params<Spec = ParamsSpec<Self::Params<'exec>>> + Clone + Debug + Serialize + DeserializeOwned + Send + Sync + 'static

Parameters to use this item.

Item consumers must provide for this item to work.

§Examples
  • For a file download item:

    • URL of the file.
    • Credentials.
  • For a server launch item:

    • Image ID.
    • Server size.
§Implementors

Peace will automatically save and load these into Resources when a command context is built.

source

type Data<'exec>: Data<'exec>

Data that the item accesses at runtime.

These may be objects instantiated in setup for use during execution, or information calculated from previous items.

Required Methods§

source

fn id(&self) -> &ItemId

Returns the ID of this full spec.

§Implementors

The ID should be a unique value that does not change over the lifetime of the managed item.

ItemIds must begin with a letter or underscore, and contain only letters, numbers, and underscores. The item_id! macro provides a compile time check to ensure that these conditions are upheld.

const fn id() -> ItemId {
    item_id!("my_item")
}
§Design Note

This is an instance method as logic for an Item may be used for multiple tasks. For example, an Item implemented to download a file may be instantiated with different files to download, and each instance of the Item should have its own ID.

source

fn setup<'life0, 'life1, 'async_trait>( &'life0 self, resources: &'life1 mut Resources<Empty> ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Inserts an instance of each data type in Resources.

§Implementors

Resources is the map of any type, and an instance of each data type must be inserted into the map so that item functions can borrow the instance of that type.

source

fn try_state_current<'life0, 'life1, 'life2, 'life3, 'async_trait>( fn_ctx: FnCtx<'life0>, params_partial: &'life1 <Self::Params<'life2> as Params>::Partial, data: Self::Data<'life3> ) -> Pin<Box<dyn Future<Output = Result<Option<Self::State>, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Returns the current state of the managed item, if possible.

This should return Ok(None) if the state is not able to be queried, such as when failing to connect to a remote host, instead of returning an error.

source

fn state_current<'life0, 'life1, 'life2, 'life3, 'async_trait>( fn_ctx: FnCtx<'life0>, params: &'life1 Self::Params<'life2>, data: Self::Data<'life3> ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Returns the current state of the managed item.

This is expected to successfully discover the current state, so errors will be presented to the user.

source

fn try_state_goal<'life0, 'life1, 'life2, 'life3, 'async_trait>( fn_ctx: FnCtx<'life0>, params_partial: &'life1 <Self::Params<'life2> as Params>::Partial, data: Self::Data<'life3> ) -> Pin<Box<dyn Future<Output = Result<Option<Self::State>, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Returns the goal state of the managed item, if possible.

This should return Ok(None) if the state is not able to be queried, such as when failing to read a potentially non-existent file to determine its content hash, instead of returning an error.

source

fn state_goal<'life0, 'life1, 'life2, 'life3, 'async_trait>( fn_ctx: FnCtx<'life0>, params: &'life1 Self::Params<'life2>, data: Self::Data<'life3> ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Returns the goal state of the managed item.

This is expected to successfully discover the goal state, so errors will be presented to the user.

§Examples
  • For a file download item, the goal state could be the destination path and a content hash.

  • For a web application service item, the goal state could be the web service is running on the latest version.

source

fn state_diff<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( params_partial: &'life0 <Self::Params<'life1> as Params>::Partial, data: Self::Data<'life2>, state_a: &'life3 Self::State, state_b: &'life4 Self::State ) -> Pin<Box<dyn Future<Output = Result<Self::StateDiff, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Returns the difference between two states.

§Implementors

When this type is serialized, it should provide “just enough” / meaningful information to the user on what has changed. So instead of including the complete goal [State], it should only include the parts that changed.

This function call is intended to be cheap and fast.

§Examples
  • For a file download item, the difference could be the content hash changes from abcd to efgh.

  • For a web application service item, the goal state could be the application version changing from 1 to 2.

source

fn state_clean<'life0, 'life1, 'life2, 'async_trait>( params_partial: &'life0 <Self::Params<'life1> as Params>::Partial, data: Self::Data<'life2> ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Returns the representation of a clean State.

§Implementors

This should return essentially the None concept of the item state. The diff between this and the current state will be shown to the user when they want to see what would be cleaned up by the clean command.

source

fn apply_check<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'async_trait>( params: &'life0 Self::Params<'life1>, data: Self::Data<'life2>, state_current: &'life3 Self::State, state_target: &'life4 Self::State, diff: &'life5 Self::StateDiff ) -> Pin<Box<dyn Future<Output = Result<ApplyCheck, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, 'life5: 'async_trait,

Returns whether apply needs to be executed.

If the current state is already in sync with the target state, then apply does not have to be executed.

§Examples
  • For a file download item, if the destination file differs from the file on the server, then the file needs to be downloaded.

  • For a web application service item, if the web service is running, but reports a previous version, then the service may need to be restarted.

§Implementors

This function call is intended to be cheap and fast.

§Parameters
  • fn_ctx: Context to send progress updates.
  • params: Parameters to the item.
  • data: Runtime data that the function reads from or writes to.
  • state_current: Current State of the managed item, returned from state_current.
  • state_target: Target State of the managed item, either state_clean or state_goal.
  • state_diff: Goal State of the managed item, returned from state_diff.
source

fn apply_dry<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>( fn_ctx: FnCtx<'life0>, params: &'life1 Self::Params<'life2>, data: Self::Data<'life3>, state_current: &'life4 Self::State, state_target: &'life5 Self::State, diff: &'life6 Self::StateDiff ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, 'life5: 'async_trait, 'life6: 'async_trait,

Dry-run transform of the current state to the target state.

This will only be called if check returns ExecRequired.

This should mirror the logic in [apply], with the following differences:

  • When state will actually be altered, this would skip the logic.

  • Where there would be IDs received from an external system, a placeholder ID should still be inserted into the runtime data. This should allow subsequent Items that rely on this one to use those placeholders in their logic.

§Implementors

This function call is intended to be read-only and cheap.

§Parameters
  • fn_ctx: Context to send progress updates.
  • params: Parameters to the item.
  • data: Runtime data that the function reads from or writes to.
  • state_current: Current State of the managed item, returned from state_current.
  • state_target: Target State of the managed item, either state_clean or state_goal.
  • state_diff: Goal State of the managed item, returned from state_diff.
source

fn apply<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>( fn_ctx: FnCtx<'life0>, params: &'life1 Self::Params<'life2>, data: Self::Data<'life3>, state_current: &'life4 Self::State, state_target: &'life5 Self::State, diff: &'life6 Self::StateDiff ) -> Pin<Box<dyn Future<Output = Result<Self::State, Self::Error>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, 'life5: 'async_trait, 'life6: 'async_trait,

Transforms the current state to the target state.

This will only be called if check returns ExecRequired.

§Parameters
  • fn_ctx: Context to send progress updates.
  • params: Parameters to the item.
  • data: Runtime data that the function reads from or writes to.
  • state_current: Current State of the managed item, returned from state_current.
  • state_target: Target State of the managed item, either state_clean or state_goal.
  • state_diff: Goal State of the managed item, returned from state_diff.

Object Safety§

This trait is not object safe.

Implementors§