use std::fmt::Display;
use crate::{
log_types::{BackendAddr, LoggableTime},
names::{BackendActionName, BackendName},
typed_socket::ChannelMessage,
types::{
backend_state::TerminationReason, BackendState, BearerToken, ClusterName, KeyConfig,
NodeId, SecretToken, Subdomain, TerminationKind,
},
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub enum ApiErrorKind {
FailedToAcquireKey,
KeyUnheldNoSpawnConfig,
KeyHeldUnhealthy,
KeyHeld,
NoDroneAvailable,
FailedToRemoveKey,
DatabaseError,
NoClusterProvided,
NotFound,
InvalidClusterName,
Other,
}
#[derive(thiserror::Error, Debug, Serialize, Deserialize)]
pub struct ApiError {
pub id: String,
pub kind: ApiErrorKind,
pub message: String,
}
impl Display for ApiError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable, PartialEq)]
pub struct KeyDeadlines {
pub renew_at: LoggableTime,
pub soft_terminate_at: LoggableTime,
pub hard_terminate_at: LoggableTime,
}
#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable, PartialEq)]
pub struct AcquiredKey {
pub key: KeyConfig,
pub deadlines: KeyDeadlines,
pub token: i64,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum BackendAction {
Spawn {
executable: Value,
key: AcquiredKey,
static_token: Option<BearerToken>,
},
Terminate {
kind: TerminationKind,
reason: TerminationReason,
},
}
impl valuable::Valuable for BackendAction {
fn as_value(&self) -> valuable::Value {
valuable::Value::Mappable(self)
}
fn visit(&self, visit: &mut dyn valuable::Visit) {
match self {
BackendAction::Spawn {
key, static_token, ..
} => {
visit.visit_entry(valuable::Value::String("key"), key.as_value());
visit.visit_entry(
valuable::Value::String("static_token"),
static_token.as_value(),
);
}
BackendAction::Terminate { kind, reason } => {
visit.visit_entry(valuable::Value::String("kind"), kind.as_value());
visit.visit_entry(valuable::Value::String("reason"), reason.as_value());
}
}
}
}
impl valuable::Mappable for BackendAction {
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
BackendAction::Spawn { .. } => (2, Some(2)),
BackendAction::Terminate { .. } => (2, Some(2)),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable)]
pub struct BackendStateMessage {
pub event_id: BackendEventId,
pub backend_id: BackendName,
pub state: BackendState,
pub timestamp: LoggableTime,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, valuable::Valuable)]
pub struct BackendEventId(i64);
impl From<i64> for BackendEventId {
fn from(i: i64) -> Self {
Self(i)
}
}
impl From<BackendEventId> for i64 {
fn from(id: BackendEventId) -> Self {
id.0
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RenewKeyRequest {
pub backend: BackendName,
pub local_time: LoggableTime,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Heartbeat {
pub local_time: LoggableTime,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum MessageFromDrone {
Heartbeat(Heartbeat),
BackendEvent(BackendStateMessage),
BackendMetrics(BackendMetricsMessage),
AckAction { action_id: BackendActionName },
RenewKey(RenewKeyRequest),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BackendMetricsMessage {
pub backend_id: BackendName,
pub mem_used: u64,
pub mem_total: u64,
pub mem_active: u64,
pub mem_inactive: u64,
pub mem_unevictable: u64,
pub mem_limit: u64,
pub cpu_used: u64,
pub sys_cpu: u64,
}
impl ChannelMessage for MessageFromDrone {
type Reply = MessageToDrone;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RenewKeyResponse {
pub backend: BackendName,
pub deadlines: Option<KeyDeadlines>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BackendActionMessage {
pub action_id: BackendActionName,
pub backend_id: BackendName,
pub drone_id: NodeId,
pub action: BackendAction,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum MessageToDrone {
Action(BackendActionMessage),
AckEvent {
event_id: BackendEventId,
},
RenewKeyResponse(RenewKeyResponse),
}
impl ChannelMessage for MessageToDrone {
type Reply = MessageFromDrone;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct RouteInfo {
pub backend_id: BackendName,
pub address: BackendAddr,
pub secret_token: SecretToken,
pub cluster: ClusterName,
pub user: Option<String>,
pub user_data: Option<serde_json::Value>,
pub subdomain: Option<Subdomain>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum CertManagerRequest {
CertLeaseRequest,
SetTxtRecord { txt_value: String },
ReleaseCertLease,
}
impl ChannelMessage for CertManagerRequest {
type Reply = CertManagerResponse;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, valuable::Valuable)]
pub enum CertManagerResponse {
CertLeaseResponse { accepted: bool },
SetTxtRecordResponse { accepted: bool },
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct RouteInfoRequest {
pub token: BearerToken,
}
impl ChannelMessage for RouteInfoRequest {
type Reply = RouteInfoResponse;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct RouteInfoResponse {
pub token: BearerToken,
pub route_info: Option<RouteInfo>,
}
impl ChannelMessage for RouteInfoResponse {
type Reply = RouteInfoRequest;
}
impl ChannelMessage for CertManagerResponse {
type Reply = CertManagerRequest;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum MessageFromProxy {
RouteInfoRequest(RouteInfoRequest),
KeepAlive(BackendName),
CertManagerRequest(CertManagerRequest),
}
impl ChannelMessage for MessageFromProxy {
type Reply = MessageToProxy;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum MessageToProxy {
RouteInfoResponse(RouteInfoResponse),
CertManagerResponse(CertManagerResponse),
BackendRemoved { backend: BackendName },
}
impl ChannelMessage for MessageToProxy {
type Reply = MessageFromProxy;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, valuable::Valuable)]
pub enum MessageFromDns {
TxtRecordRequest { cluster: ClusterName },
}
impl ChannelMessage for MessageFromDns {
type Reply = MessageToDns;
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum MessageToDns {
TxtRecordResponse {
cluster: ClusterName,
txt_value: Option<String>,
},
}
impl ChannelMessage for MessageToDns {
type Reply = MessageFromDns;
}
#[derive(Serialize, Deserialize, Debug)]
pub struct StatusResponse {
pub status: String,
pub version: String,
pub hash: String,
}