use kube::CustomResource; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(CustomResource, Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] #[kube( group = "irc.josie.cloud", version = "v1alpha1", kind = "ErgoNetwork", namespaced, status = "ErgoNetworkStatus", shortname = "ergo", printcolumn = r#"{"name":"Hostname", "type":"string", "jsonPath":".spec.hostname"}"#, printcolumn = r#"{"name":"Network", "type":"string", "jsonPath":".spec.networkName"}"#, printcolumn = r#"{"name":"Ready", "type":"string", "jsonPath":".status.conditions[?(@.type==\"Ready\")].status"}"# )] pub struct ErgoNetworkSpec { pub hostname: String, #[serde(default, rename = "networkName")] pub network_name: Option, #[serde(default, rename = "operCredentials")] pub oper_credentials: Option, #[serde(default)] pub listeners: Vec, #[serde(default)] pub tls: Option, #[serde(default)] pub route: Option, #[serde(default)] pub resources: Option, #[serde(default)] pub storage: Option, #[serde(default)] pub oauth2: Option, #[serde(default)] pub cloaking: Option, #[serde(default, rename = "maxSendq")] pub max_sendq: Option, #[serde(default)] pub limits: Option, #[serde(default)] pub vhosts: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct OperCredentials { #[serde(rename = "secretName")] pub secret_name: String, #[serde(default, rename = "className")] pub class_name: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct StorageSpec { #[serde(default = "default_storage_size")] pub size: String, #[serde(default, rename = "storageClassName")] pub storage_class_name: Option, } fn default_storage_size() -> String { "1Gi".to_string() } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct Listener { pub address: String, #[serde(default)] pub tls: bool, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct TlsSpec { pub issuer_ref: IssuerRef, pub dns_names: Vec, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct IssuerRef { pub name: String, pub kind: String, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct RouteSpec { pub host: String, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct OAuth2Spec { pub introspection_url: String, pub secret_ref: String, #[serde(default = "default_true")] pub autocreate: bool, #[serde(default, rename = "clientId")] pub client_id: Option, } fn default_true() -> bool { true } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct CloakingSpec { pub netname: String, #[serde(default, rename = "cidrLenIpv4")] pub cidr_len_ipv4: Option, #[serde(default, rename = "cidrLenIpv6")] pub cidr_len_ipv6: Option, #[serde(default, rename = "numBits")] pub num_bits: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct LimitsSpec { #[serde(default)] pub nicklen: Option, #[serde(default)] pub identlen: Option, #[serde(default)] pub realnamelen: Option, #[serde(default)] pub channellen: Option, #[serde(default)] pub awaylen: Option, #[serde(default)] pub kicklen: Option, #[serde(default)] pub topiclen: Option, #[serde(default, rename = "monitorEntries")] pub monitor_entries: Option, #[serde(default, rename = "whowasEntries")] pub whowas_entries: Option, #[serde(default, rename = "chanListModes")] pub chan_list_modes: Option, #[serde(default, rename = "registrationMessages")] pub registration_messages: Option, #[serde(default)] pub multiline: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct MultilineSpec { #[serde(default, rename = "maxBytes")] pub max_bytes: Option, #[serde(default, rename = "maxLines")] pub max_lines: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct VhostSpec { #[serde(default)] pub enabled: Option, #[serde(default, rename = "maxLength")] pub max_length: Option, #[serde(default, rename = "validRegexp")] pub valid_regexp: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct ResourceRequirements { #[serde(default)] pub requests: Option, #[serde(default)] pub limits: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct ResourceList { #[serde(default)] pub memory: Option, #[serde(default)] pub cpu: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct ErgoNetworkStatus { #[serde(default)] pub conditions: Vec, #[serde(default)] pub observed_generation: Option, } #[derive(Serialize, Deserialize, Default, Debug, Clone, JsonSchema)] pub struct Condition { #[serde(rename = "type")] pub type_: String, pub status: String, pub reason: String, pub message: String, pub last_transition_time: String, } #[cfg(test)] mod tests { use super::*; use kube::CustomResourceExt; #[test] fn crd_generates_valid_schema() { let crd = ErgoNetwork::crd(); let name = crd.metadata.name.unwrap(); assert_eq!(name, "ergonetworks.irc.josie.cloud"); } #[test] fn default_spec_has_sane_values() { let spec = ErgoNetworkSpec::default(); assert!(spec.listeners.is_empty()); assert!(spec.tls.is_none()); assert!(spec.route.is_none()); assert!(spec.resources.is_none()); assert!(spec.storage.is_none()); assert!(spec.oper_credentials.is_none()); assert!(spec.network_name.is_none()); } #[test] fn default_spec_has_no_oauth2() { let spec = ErgoNetworkSpec::default(); assert!(spec.oauth2.is_none()); } #[test] fn default_spec_has_no_cloaking() { let spec = ErgoNetworkSpec::default(); assert!(spec.cloaking.is_none()); } }