use crate::Error;
use crate::proto::v1::{Capability, CredentialData, Resource, RunFunctionRequest, credentials};
use crate::resource::{pb_to_json, struct_to_json};
pub const WATCHED_RESOURCE_KEY: &str = "ops.crossplane.io/watched-resource";
pub fn get_input<T: serde::de::DeserializeOwned>(req: &RunFunctionRequest) -> Result<T, Error> {
let input = req.input.as_ref().ok_or(Error::MissingInput)?;
Ok(serde_json::from_value(struct_to_json(input))?)
}
pub fn observed_composite(req: &RunFunctionRequest) -> Option<&Resource> {
req.observed.as_ref()?.composite.as_ref()
}
pub fn observed_composed<'a>(req: &'a RunFunctionRequest, name: &str) -> Option<&'a Resource> {
req.observed.as_ref()?.resources.get(name)
}
pub fn get_context_key(req: &RunFunctionRequest, key: &str) -> Option<serde_json::Value> {
req.context.as_ref()?.fields.get(key).map(pb_to_json)
}
pub fn get_required_resources(
req: &RunFunctionRequest,
name: &str,
) -> Option<Vec<serde_json::Value>> {
let resources = req.required_resources.get(name)?;
Some(
resources
.items
.iter()
.filter_map(|r| r.resource.as_ref())
.map(struct_to_json)
.collect(),
)
}
pub fn get_required_resource(req: &RunFunctionRequest, name: &str) -> Option<serde_json::Value> {
get_required_resources(req, name)?.into_iter().next()
}
pub fn get_required_resources_as<T: serde::de::DeserializeOwned>(
req: &RunFunctionRequest,
name: &str,
) -> Result<Option<Vec<T>>, Error> {
get_required_resources(req, name)
.map(|resources| resources.into_iter().map(serde_json::from_value).collect())
.transpose()
.map_err(Error::from)
}
pub fn get_required_resource_as<T: serde::de::DeserializeOwned>(
req: &RunFunctionRequest,
name: &str,
) -> Result<Option<T>, Error> {
get_required_resource(req, name)
.map(serde_json::from_value)
.transpose()
.map_err(Error::from)
}
pub fn get_watched_resource(req: &RunFunctionRequest) -> Option<serde_json::Value> {
get_required_resource(req, WATCHED_RESOURCE_KEY)
}
pub fn get_credential_data<'a>(
req: &'a RunFunctionRequest,
name: &str,
) -> Option<&'a CredentialData> {
match req.credentials.get(name)?.source.as_ref()? {
credentials::Source::CredentialData(data) => Some(data),
}
}
pub fn advertises_capabilities(req: &RunFunctionRequest) -> bool {
has_capability(req, Capability::Capabilities)
}
pub fn has_capability(req: &RunFunctionRequest, cap: Capability) -> bool {
req.meta
.as_ref()
.is_some_and(|m| m.capabilities().any(|c| c == cap))
}
pub fn get_required_schema(req: &RunFunctionRequest, name: &str) -> Option<serde_json::Value> {
req.required_schemas
.get(name)?
.openapi_v3
.as_ref()
.map(struct_to_json)
}