mod controller;
mod crd;
mod executor;
mod function;
mod manifests;
mod membership;
mod resources;
mod site;
use clap::Subcommand;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("kubernetes: {0}")]
Kube(#[from] kube::Error),
#[error("manifest: {0}")]
Yaml(#[from] serde_yaml::Error),
#[error("manifest json: {0}")]
Json(#[from] serde_json::Error),
#[error("cluster api: {0}")]
Http(#[from] reqwest::Error),
#[error("operator: {0}")]
Other(String),
}
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, clap::Args)]
pub struct OperatorArgs {
#[command(subcommand)]
command: OperatorCommand,
}
#[derive(Debug, Subcommand)]
enum OperatorCommand {
Run(controller::RunArgs),
Crds,
Manifests(manifests::ManifestArgs),
}
#[derive(Debug, serde::Serialize)]
#[serde(tag = "result", rename_all = "snake_case")]
pub enum OperatorOutput {
Ran,
Crds {
documents: Vec<serde_json::Value>,
#[serde(skip)]
yaml: String,
},
Manifests {
documents: Vec<serde_json::Value>,
#[serde(skip)]
yaml: String,
},
}
impl crate::output::Rendered for OperatorOutput {
fn render_human(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
match self {
Self::Ran => Ok(()),
Self::Crds { yaml, .. } | Self::Manifests { yaml, .. } => {
write!(w, "{yaml}")
}
}
}
}
fn yaml_documents(yaml: &str) -> Vec<serde_json::Value> {
use serde::Deserialize as _;
serde_yaml::Deserializer::from_str(yaml)
.filter_map(|doc| serde_yaml::Value::deserialize(doc).ok())
.filter_map(|value| serde_json::to_value(value).ok())
.collect()
}
pub async fn run(args: OperatorArgs) -> Result<OperatorOutput> {
match args.command {
OperatorCommand::Run(a) => {
controller::run(a).await?;
Ok(OperatorOutput::Ran)
}
OperatorCommand::Crds => {
let yaml = manifests::crds_yaml()?;
let documents = yaml_documents(&yaml);
Ok(OperatorOutput::Crds { documents, yaml })
}
OperatorCommand::Manifests(a) => {
let yaml = manifests::manifests_yaml(&a)?;
let documents = yaml_documents(&yaml);
Ok(OperatorOutput::Manifests { documents, yaml })
}
}
}