crossplane_fn_sdk_unofficial/lib.rs
1//! This is an **unofficial** Rust [composite function sdk](https://docs.crossplane.io/latest/guides/write-a-composition-function-in-go/)
2//! for [crossplane](https://www.crossplane.io/).
3//!
4//! Crossplane composite functions are implemented as gRPC server that have to handle specific cli args to setup mtls.
5//! This sdk cares about this part and has generated rust types from the published Crossplane protocol buffer schema.
6//! Furthermore, it provides some helper functions to simplify function writing.
7//!
8//! The central functionality besides some type mapping helper traits is provided via the [`run_server`]-function
9//! which will start a gRPC server that handles the composite function requests with the business logic provided by
10//! the sdk-user.
11//!
12//! Crossplane expects it's users to only output those fields they want to influence into the desired state.
13//! If you are looking for a crate that helps deriving partial representation of Kubernetes types my other crate [`optionable`](https://crates.io/crates/optionable)
14//! might be useful as well.
15//!
16//! # Compile-time dependencies
17//! The protocol buffer library [prost-wkt-types](https://docs.rs/prost-wkt-types/latest/prost_wkt_types) used by the sdk requires [protoc](https://protobuf.dev/installation/) at compile-time.
18//!
19//! # Examples
20//! ## Direct composite function (synchronous)
21//! ```
22//! # use std::error::Error;
23//! # use clap::Parser;
24//! # use tonic::Status;
25//! # use crossplane_fn_sdk_unofficial::{run_server, Args, IntoResponseMeta};
26//! # use crossplane_fn_sdk_unofficial::crossplane::{RunFunctionRequest, RunFunctionResponse};
27//! fn composite_function(request: RunFunctionRequest) -> Result<RunFunctionResponse,Status> {
28//! // Business logic goes here
29//! Ok(RunFunctionResponse {
30//! context: request.context,
31//! meta: Some(request.meta.into_response_meta(60)),
32//! desired: request.desired,
33//! ..Default::default()
34//! })
35//! }
36//!
37//! # tokio_test::block_on(async {
38//! # Ok::<_, Box<dyn Error>>(
39//! run_server(Args::parse(), composite_function).await?
40//! # )
41//! # });
42//! ```
43//! ## Explicit Trait-implementation (asynchronous)
44//! ```
45//! # use std::error::Error;
46//! # use clap::Parser;
47//! # use tonic::Status;
48//! # use crossplane_fn_sdk_unofficial::{run_server, Args, CompositeFunction, IntoResponseMeta};
49//! # use crossplane_fn_sdk_unofficial::crossplane::{RunFunctionRequest, RunFunctionResponse};
50//! struct ExampleFunction{}
51//!
52//! #[tonic::async_trait]
53//! impl CompositeFunction for ExampleFunction {
54//! async fn run_function(&self,request: RunFunctionRequest) -> Result<RunFunctionResponse,Status> {
55//! // Business logic goes here
56//! Ok(RunFunctionResponse {
57//! context: request.context,
58//! meta: Some(request.meta.into_response_meta(60)),
59//! desired: request.desired,
60//! ..Default::default()
61//! })
62//! }
63//! }
64//!
65//! # tokio_test::block_on(async {
66//! # Ok::<_, Box<dyn Error>>(
67//! run_server(Args::parse(), ExampleFunction{}).await?
68//! # )
69//! # });
70//! ```
71pub use clap;
72pub use tokio;
73pub use tonic;
74
75pub use map_meta::IntoResponseMeta;
76pub use map_resource::{TryFromResource, TryIntoResource};
77pub use server::{run_server, Args, CompositeFunction};
78mod error;
79mod map_meta;
80mod map_resource;
81mod server;
82
83/// Rust types generated from the [official crossplane protobuf types](https://github.com/crossplane/crossplane/tree/main/proto/fn/v1)
84/// for composite function.
85#[allow(warnings)]
86#[allow(clippy)]
87#[allow(unknown_lints)]
88pub mod crossplane {
89 include!("generated/crossplane.rs");
90
91 impl From<bool> for Ready {
92 fn from(value: bool) -> Self {
93 match value {
94 true => Ready::True,
95 _ => Ready::False,
96 }
97 }
98 }
99}