1use std::fmt::Display;
2
3use crate::{
4 log_types::{BackendAddr, LoggableTime},
5 names::{BackendActionName, BackendName},
6 typed_socket::ChannelMessage,
7 types::{
8 backend_state::TerminationReason, BackendState, BearerToken, ClusterName, KeyConfig,
9 NodeId, SecretToken, Subdomain, TerminationKind,
10 },
11};
12use serde::{Deserialize, Serialize};
13use serde_json::Value;
14
15#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
16pub enum ApiErrorKind {
17 FailedToAcquireKey,
18 KeyUnheldNoSpawnConfig,
19 KeyHeldUnhealthy,
20 KeyHeld,
21 NoDroneAvailable,
22 FailedToRemoveKey,
23 DatabaseError,
24 NoClusterProvided,
25 NotFound,
26 InvalidClusterName,
27 Other,
28}
29
30#[derive(thiserror::Error, Debug, Serialize, Deserialize)]
31pub struct ApiError {
32 pub id: String,
33 pub kind: ApiErrorKind,
34 pub message: String,
35}
36
37impl Display for ApiError {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "{:?}", self)
40 }
41}
42
43#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable, PartialEq)]
44pub struct KeyDeadlines {
45 pub renew_at: LoggableTime,
47
48 pub soft_terminate_at: LoggableTime,
50
51 pub hard_terminate_at: LoggableTime,
53}
54
55#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable, PartialEq)]
56pub struct AcquiredKey {
57 pub key: KeyConfig,
59
60 pub deadlines: KeyDeadlines,
62
63 pub token: i64,
69}
70
71#[derive(Serialize, Deserialize, Debug, Clone)]
72pub enum BackendAction {
73 Spawn {
74 executable: Value,
75 key: AcquiredKey,
76 static_token: Option<BearerToken>,
77 },
78 Terminate {
79 kind: TerminationKind,
80 reason: TerminationReason,
81 },
82}
83
84impl valuable::Valuable for BackendAction {
85 fn as_value(&self) -> valuable::Value {
86 valuable::Value::Mappable(self)
87 }
88
89 fn visit(&self, visit: &mut dyn valuable::Visit) {
90 match self {
91 BackendAction::Spawn {
92 key, static_token, ..
93 } => {
94 visit.visit_entry(valuable::Value::String("key"), key.as_value());
95 visit.visit_entry(
96 valuable::Value::String("static_token"),
97 static_token.as_value(),
98 );
99 }
100 BackendAction::Terminate { kind, reason } => {
101 visit.visit_entry(valuable::Value::String("kind"), kind.as_value());
102 visit.visit_entry(valuable::Value::String("reason"), reason.as_value());
103 }
104 }
105 }
106}
107
108impl valuable::Mappable for BackendAction {
109 fn size_hint(&self) -> (usize, Option<usize>) {
110 match self {
111 BackendAction::Spawn { .. } => (2, Some(2)),
112 BackendAction::Terminate { .. } => (2, Some(2)),
113 }
114 }
115}
116
117#[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable)]
118pub struct BackendStateMessage {
119 pub event_id: BackendEventId,
120 pub backend_id: BackendName,
121 pub state: BackendState,
122
123 pub timestamp: LoggableTime,
126}
127
128#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, valuable::Valuable)]
129pub struct BackendEventId(i64);
130
131impl From<i64> for BackendEventId {
132 fn from(i: i64) -> Self {
133 Self(i)
134 }
135}
136
137impl From<BackendEventId> for i64 {
138 fn from(id: BackendEventId) -> Self {
139 id.0
140 }
141}
142
143#[derive(Serialize, Deserialize, Debug, Clone)]
144pub struct RenewKeyRequest {
145 pub backend: BackendName,
146
147 pub local_time: LoggableTime,
148}
149
150#[derive(Serialize, Deserialize, Debug, Clone)]
151pub struct Heartbeat {
152 pub local_time: LoggableTime,
153}
154
155#[derive(Serialize, Deserialize, Debug, Clone)]
156pub enum MessageFromDrone {
157 Heartbeat(Heartbeat),
158 BackendEvent(BackendStateMessage),
159 BackendMetrics(BackendMetricsMessage),
160 AckAction { action_id: BackendActionName },
161 RenewKey(RenewKeyRequest),
162}
163
164#[derive(Serialize, Deserialize, Debug, Clone)]
165pub struct BackendMetricsMessage {
166 pub backend_id: BackendName,
167 pub mem_used: u64,
170 pub mem_total: u64,
173 pub mem_active: u64,
175 pub mem_inactive: u64,
177 pub mem_unevictable: u64,
179 pub mem_limit: u64,
181 pub cpu_used: u64,
183 pub sys_cpu: u64,
185}
186
187impl ChannelMessage for MessageFromDrone {
188 type Reply = MessageToDrone;
189}
190
191#[derive(Serialize, Deserialize, Debug, Clone)]
192pub struct RenewKeyResponse {
193 pub backend: BackendName,
195
196 pub deadlines: Option<KeyDeadlines>,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct BackendActionMessage {
203 pub action_id: BackendActionName,
204 pub backend_id: BackendName,
205 pub drone_id: NodeId,
206 pub action: BackendAction,
207}
208
209#[derive(Serialize, Deserialize, Debug, Clone)]
210pub enum MessageToDrone {
211 Action(BackendActionMessage),
212 AckEvent {
214 event_id: BackendEventId,
215 },
216 RenewKeyResponse(RenewKeyResponse),
217}
218
219impl ChannelMessage for MessageToDrone {
220 type Reply = MessageFromDrone;
221}
222
223#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
224pub struct RouteInfo {
225 pub backend_id: BackendName,
226 pub address: BackendAddr,
227 pub secret_token: SecretToken,
228 pub cluster: ClusterName,
229 pub user: Option<String>,
230 pub user_data: Option<serde_json::Value>,
231 pub subdomain: Option<Subdomain>,
232}
233
234#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
235pub enum CertManagerRequest {
236 CertLeaseRequest,
238
239 SetTxtRecord { txt_value: String },
242
243 ReleaseCertLease,
246}
247
248impl ChannelMessage for CertManagerRequest {
249 type Reply = CertManagerResponse;
250}
251
252#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, valuable::Valuable)]
253pub enum CertManagerResponse {
254 CertLeaseResponse { accepted: bool },
256
257 SetTxtRecordResponse { accepted: bool },
259}
260
261#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
262pub struct RouteInfoRequest {
263 pub token: BearerToken,
264}
265
266impl ChannelMessage for RouteInfoRequest {
267 type Reply = RouteInfoResponse;
268}
269
270#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
271pub struct RouteInfoResponse {
272 pub token: BearerToken,
273 pub route_info: Option<RouteInfo>,
274}
275
276impl ChannelMessage for RouteInfoResponse {
277 type Reply = RouteInfoRequest;
278}
279
280impl ChannelMessage for CertManagerResponse {
281 type Reply = CertManagerRequest;
282}
283
284#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
285pub enum MessageFromProxy {
286 RouteInfoRequest(RouteInfoRequest),
287 KeepAlive(BackendName),
288 CertManagerRequest(CertManagerRequest),
289}
290
291impl ChannelMessage for MessageFromProxy {
292 type Reply = MessageToProxy;
293}
294
295#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
296pub enum MessageToProxy {
297 RouteInfoResponse(RouteInfoResponse),
298 CertManagerResponse(CertManagerResponse),
299 BackendRemoved { backend: BackendName },
300}
301
302impl ChannelMessage for MessageToProxy {
303 type Reply = MessageFromProxy;
304}
305
306#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, valuable::Valuable)]
307pub enum MessageFromDns {
308 TxtRecordRequest { cluster: ClusterName },
309}
310
311impl ChannelMessage for MessageFromDns {
312 type Reply = MessageToDns;
313}
314
315#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
316pub enum MessageToDns {
317 TxtRecordResponse {
318 cluster: ClusterName,
319 txt_value: Option<String>,
320 },
321}
322
323impl ChannelMessage for MessageToDns {
324 type Reply = MessageFromDns;
325}
326
327#[derive(Serialize, Deserialize, Debug)]
328pub struct StatusResponse {
329 pub status: String,
330 pub version: String,
331 pub hash: String,
332}