1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
//! Roperator lets you easily write Kubernetes Operators that manage a potentially complex set of //! _child_ Kuberntes resources for each instance of a _parent_ Custom Resource. //! //! To get started, all you need is an `OperatorConfig` and a `Handler` implementation. //! //! Busybox operator example: //! ```no_run //! use roperator::prelude::*; //! use roperator::serde_json::json; //! //! /// Name of our operator, which is automatically added as a label value in all of the child resources we create //! const OPERATOR_NAME: &str = "echoserver-example"; //! //! // a `K8sType` with basic info about our parent CRD //! static PARENT_TYPE: &K8sType = &K8sType { //! api_version: "example.roperator.com/v1alpha1", //! kind: "BusyBox", //! plural_kind: "busyboxes", //! }; //! //! // In your main function create the OperatorConfig, which tells Roperator about //! // the types of your parent and child resources, and about how to deal with //! // each type of child resource when it needs updated //! let operator_config = OperatorConfig::new(OPERATOR_NAME, PARENT_TYPE) //! .with_child(k8s_types::core::v1::Pod, ChildConfig::recreate()); //! //! // this function will block the current thread indifinitely while the operator runs //! run_operator(operator_config, handle_sync); //! //! fn handle_sync(request: &SyncRequest) -> Result<SyncResponse, Error> { //! // for this tiny example, we'll only create a single Pod. You can also use any of the types //! // defined in the k8s_openapi crate, which has serializable structs for all the usual resources //! let pod = json!({ //! "metadata": { //! "namespace": request.parent.namespace(), //! "name": format!("{}-busybox", request.parent.name()), //! }, //! "spec": { //! "containers": [ //! { //! "name": "busybox", //! "image": "busybox:latest", //! "command": [ //! "bash", //! "-c", //! format!("while true; do; echo 'Hello from {}'; sleep 10; done;", request.parent.name()), //! ] //! } //! ] //! } //! }); //! let status = json!({ //! // normally, we'd derive the status by taking a look at the existing `children` in the request //! "message": "everything looks good here!", //! }); //! Ok(SyncResponse { //! status, //! children: vec![pod], //! resync: None, //! }) //! } //! ``` //! //! The main function in most operators just needs to call `roperator::runner::run_operator` or //! `roperator::runner::run_operator_with_client_config`, passing the `OperatorConfig` and your `Handler` implementation. //! #[macro_use] extern crate serde_derive; pub mod config; pub mod handler; pub mod k8s_types; pub mod resource; pub mod runner; pub use serde; pub use serde_json; pub use serde_yaml; pub mod prelude { pub use crate::config::{ChildConfig, ClientConfig, OperatorConfig, UpdateStrategy}; pub use crate::handler::{FinalizeResponse, Handler, SyncRequest, SyncResponse}; pub use crate::k8s_types::{self, K8sType}; pub use crate::resource::K8sResource; pub use crate::runner::run_operator; pub use anyhow::Error; pub use serde::{Deserialize, Serialize}; }