use serde::de;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize)]
pub struct SecretInfo {
pub name: String,
pub created_at_millis: i64,
pub updated_at_millis: i64,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct SecretReference {
pub name: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub namespace_path: Vec<String>,
}
impl SecretReference {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
namespace_path: Vec::new(),
}
}
pub fn in_namespace(name: impl Into<String>, namespace_path: Vec<String>) -> Self {
Self {
name: name.into(),
namespace_path,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum SecretBinding {
Env {
variable: String,
secret_ref: SecretReference,
},
Unrecognized { kind: String },
}
impl SecretBinding {
pub fn kind(&self) -> &str {
match self {
Self::Env { .. } => "env",
Self::Unrecognized { kind } => kind,
}
}
pub fn variable(&self) -> Option<&str> {
match self {
Self::Env { variable, .. } => Some(variable),
Self::Unrecognized { .. } => None,
}
}
pub fn secret(&self) -> Option<&SecretReference> {
match self {
Self::Env { secret_ref, .. } => Some(secret_ref),
Self::Unrecognized { .. } => None,
}
}
}
#[derive(Deserialize)]
struct EnvSecretBindingWire {
variable: String,
secret_ref: SecretReference,
}
impl<'de> Deserialize<'de> for SecretBinding {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Self, D::Error> {
let value = Value::deserialize(deserializer)?;
let kind = value
.get("kind")
.ok_or_else(|| de::Error::missing_field("kind"))?
.as_str()
.ok_or_else(|| de::Error::custom("secret binding kind must be a string"))?
.to_string();
match kind.as_str() {
"env" => {
let wire: EnvSecretBindingWire =
serde_json::from_value(value).map_err(de::Error::custom)?;
Ok(Self::Env {
variable: wire.variable,
secret_ref: wire.secret_ref,
})
}
_ => Ok(Self::Unrecognized { kind }),
}
}
}
impl Serialize for SecretBinding {
fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
#[derive(Serialize)]
struct EnvBindingRef<'a> {
kind: &'static str,
variable: &'a str,
secret_ref: &'a SecretReference,
}
#[derive(Serialize)]
struct UnrecognizedBindingRef<'a> {
kind: &'a str,
}
match self {
Self::Env {
variable,
secret_ref,
} => EnvBindingRef {
kind: "env",
variable,
secret_ref,
}
.serialize(serializer),
Self::Unrecognized { kind } => UnrecognizedBindingRef { kind }.serialize(serializer),
}
}
}