1use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::Result;
8
9#[derive(Serialize, Deserialize, Debug, Clone)]
12#[non_exhaustive]
13pub struct CtlResponse<T> {
14 pub(crate) success: bool,
16 pub(crate) message: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub(crate) response: Option<T>,
21}
22
23impl<T> CtlResponse<T> {
24 #[must_use]
26 pub fn ok(response: T) -> Self {
27 CtlResponse {
28 success: true,
29 message: String::new(),
30 response: Some(response),
31 }
32 }
33
34 #[must_use]
36 pub fn succeeded(&self) -> bool {
37 self.success
38 }
39
40 #[must_use]
42 pub fn message(&self) -> &str {
43 &self.message
44 }
45
46 #[must_use]
48 pub fn data(&self) -> Option<&T> {
49 self.response.as_ref()
50 }
51
52 #[must_use]
54 pub fn into_data(self) -> Option<T> {
55 self.response
56 }
57}
58
59impl CtlResponse<()> {
60 #[must_use]
63 pub fn success(message: String) -> Self {
64 CtlResponse {
65 success: true,
66 message,
67 response: None,
68 }
69 }
70
71 #[must_use]
75 pub fn error(message: &str) -> Self {
76 CtlResponse {
77 success: false,
78 message: message.to_string(),
79 response: None,
80 }
81 }
82}
83
84#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
86#[non_exhaustive]
87pub struct ScaleComponentCommand {
88 #[serde(default)]
90 pub(crate) component_ref: String,
91 pub(crate) component_id: String,
93 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub(crate) annotations: Option<BTreeMap<String, String>>,
97 #[serde(default, alias = "count", rename = "count")]
101 pub(crate) max_instances: u32,
102 #[serde(default)]
104 pub(crate) host_id: String,
105 #[serde(default)]
111 pub(crate) config: Vec<String>,
112 #[serde(default)]
113 pub(crate) allow_update: bool,
119}
120
121impl ScaleComponentCommand {
122 #[must_use]
123 pub fn component_ref(&self) -> &str {
124 &self.component_ref
125 }
126
127 #[must_use]
128 pub fn component_id(&self) -> &str {
129 &self.component_id
130 }
131
132 #[must_use]
133 pub fn allow_update(&self) -> bool {
134 self.allow_update
135 }
136
137 #[must_use]
138 pub fn config(&self) -> &Vec<String> {
139 &self.config
140 }
141
142 #[must_use]
143 pub fn annotations(&self) -> Option<&BTreeMap<String, String>> {
144 self.annotations.as_ref()
145 }
146
147 #[must_use]
148 pub fn max_instances(&self) -> u32 {
149 self.max_instances
150 }
151
152 #[must_use]
153 pub fn host_id(&self) -> &str {
154 &self.host_id
155 }
156
157 #[must_use]
158 pub fn builder() -> ScaleComponentCommandBuilder {
159 ScaleComponentCommandBuilder::default()
160 }
161}
162
163#[derive(Clone, Debug, Default, Eq, PartialEq)]
165#[non_exhaustive]
166pub struct ScaleComponentCommandBuilder {
167 component_ref: Option<String>,
168 component_id: Option<String>,
169 annotations: Option<BTreeMap<String, String>>,
170 max_instances: Option<u32>,
171 host_id: Option<String>,
172 config: Option<Vec<String>>,
173 allow_update: Option<bool>,
174}
175
176impl ScaleComponentCommandBuilder {
177 #[must_use]
178 pub fn new() -> Self {
179 Self::default()
180 }
181
182 #[must_use]
183 pub fn component_ref(mut self, v: &str) -> Self {
184 self.component_ref = Some(v.into());
185 self
186 }
187
188 #[must_use]
189 pub fn component_id(mut self, v: &str) -> Self {
190 self.component_id = Some(v.into());
191 self
192 }
193
194 #[must_use]
195 pub fn annotations(mut self, v: impl Into<BTreeMap<String, String>>) -> Self {
196 self.annotations = Some(v.into());
197 self
198 }
199
200 #[must_use]
201 pub fn max_instances(mut self, v: u32) -> Self {
202 self.max_instances = Some(v);
203 self
204 }
205
206 #[must_use]
207 pub fn host_id(mut self, v: &str) -> Self {
208 self.host_id = Some(v.into());
209 self
210 }
211
212 #[must_use]
213 pub fn config(mut self, v: Vec<String>) -> Self {
214 self.config = Some(v);
215 self
216 }
217
218 #[must_use]
219 pub fn allow_update(mut self, v: bool) -> Self {
220 self.allow_update = Some(v);
221 self
222 }
223
224 pub fn build(self) -> Result<ScaleComponentCommand> {
225 Ok(ScaleComponentCommand {
226 component_ref: self
227 .component_ref
228 .ok_or_else(|| "component ref is required for scaling components".to_string())?,
229 component_id: self
230 .component_id
231 .ok_or_else(|| "component id is required for scaling components".to_string())?,
232 annotations: self.annotations,
233 max_instances: self.max_instances.unwrap_or(0),
234 host_id: self
235 .host_id
236 .ok_or_else(|| "host id is required for scaling hosts host".to_string())?,
237 config: self.config.unwrap_or_default(),
238 allow_update: self.allow_update.unwrap_or_default(),
239 })
240 }
241}
242
243#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
246#[non_exhaustive]
247pub struct StartProviderCommand {
248 provider_id: String,
250 #[serde(default)]
252 provider_ref: String,
253 #[serde(default)]
255 host_id: String,
256 #[serde(default)]
262 config: Vec<String>,
263 #[serde(default, skip_serializing_if = "Option::is_none")]
266 annotations: Option<BTreeMap<String, String>>,
267}
268
269impl StartProviderCommand {
270 #[must_use]
271 pub fn provider_id(&self) -> &str {
272 &self.provider_id
273 }
274
275 #[must_use]
276 pub fn provider_ref(&self) -> &str {
277 &self.provider_ref
278 }
279
280 #[must_use]
281 pub fn host_id(&self) -> &str {
282 &self.host_id
283 }
284
285 #[must_use]
286 pub fn config(&self) -> &Vec<String> {
287 &self.config
288 }
289
290 #[must_use]
291 pub fn annotations(&self) -> Option<&BTreeMap<String, String>> {
292 self.annotations.as_ref()
293 }
294
295 #[must_use]
296 pub fn builder() -> StartProviderCommandBuilder {
297 StartProviderCommandBuilder::default()
298 }
299}
300
301#[derive(Clone, Debug, Default, Eq, PartialEq)]
303#[non_exhaustive]
304pub struct StartProviderCommandBuilder {
305 host_id: Option<String>,
306 provider_id: Option<String>,
307 provider_ref: Option<String>,
308 annotations: Option<BTreeMap<String, String>>,
309 config: Option<Vec<String>>,
310}
311
312impl StartProviderCommandBuilder {
313 #[must_use]
314 pub fn new() -> Self {
315 Self::default()
316 }
317
318 #[must_use]
319 pub fn provider_ref(mut self, v: &str) -> Self {
320 self.provider_ref = Some(v.into());
321 self
322 }
323
324 #[must_use]
325 pub fn provider_id(mut self, v: &str) -> Self {
326 self.provider_id = Some(v.into());
327 self
328 }
329
330 #[must_use]
331 pub fn annotations(mut self, v: impl Into<BTreeMap<String, String>>) -> Self {
332 self.annotations = Some(v.into());
333 self
334 }
335
336 #[must_use]
337 pub fn host_id(mut self, v: &str) -> Self {
338 self.host_id = Some(v.into());
339 self
340 }
341
342 #[must_use]
343 pub fn config(mut self, v: Vec<String>) -> Self {
344 self.config = Some(v);
345 self
346 }
347
348 pub fn build(self) -> Result<StartProviderCommand> {
349 Ok(StartProviderCommand {
350 provider_ref: self
351 .provider_ref
352 .ok_or_else(|| "provider ref is required for starting providers".to_string())?,
353 provider_id: self
354 .provider_id
355 .ok_or_else(|| "provider id is required for starting providers".to_string())?,
356 annotations: self.annotations,
357 host_id: self
358 .host_id
359 .ok_or_else(|| "host id is required for starting providers".to_string())?,
360 config: self.config.unwrap_or_default(),
361 })
362 }
363}
364
365#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
367#[non_exhaustive]
368pub struct StopHostCommand {
369 #[serde(default)]
371 pub(crate) host_id: String,
372 #[serde(default, skip_serializing_if = "Option::is_none")]
374 pub(crate) timeout: Option<u64>,
375}
376
377impl StopHostCommand {
378 #[must_use]
379 pub fn host_id(&self) -> &str {
380 &self.host_id
381 }
382
383 #[must_use]
384 pub fn timeout(&self) -> Option<u64> {
385 self.timeout
386 }
387
388 #[must_use]
389 pub fn builder() -> StopHostCommandBuilder {
390 StopHostCommandBuilder::default()
391 }
392}
393
394#[derive(Clone, Debug, Default, Eq, PartialEq)]
395#[non_exhaustive]
396pub struct StopHostCommandBuilder {
397 host_id: Option<String>,
398 timeout: Option<u64>,
399}
400
401impl StopHostCommandBuilder {
402 #[must_use]
403 pub fn new() -> Self {
404 Self::default()
405 }
406
407 #[must_use]
408 pub fn host_id(mut self, v: &str) -> Self {
409 self.host_id = Some(v.into());
410 self
411 }
412
413 #[must_use]
414 pub fn timeout(mut self, v: u64) -> Self {
415 self.timeout = Some(v);
416 self
417 }
418
419 pub fn build(self) -> Result<StopHostCommand> {
420 Ok(StopHostCommand {
421 host_id: self
422 .host_id
423 .ok_or_else(|| "host id is required for stopping host".to_string())?,
424 timeout: self.timeout,
425 })
426 }
427}
428
429#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
431#[non_exhaustive]
432pub struct StopProviderCommand {
433 #[serde(default)]
435 pub(crate) host_id: String,
436 #[serde(default, alias = "provider_ref")]
438 pub(crate) provider_id: String,
439}
440
441impl StopProviderCommand {
442 #[must_use]
443 pub fn host_id(&self) -> &str {
444 &self.host_id
445 }
446
447 #[must_use]
448 pub fn provider_id(&self) -> &str {
449 &self.provider_id
450 }
451
452 #[must_use]
453 pub fn builder() -> StopProviderCommandBuilder {
454 StopProviderCommandBuilder::default()
455 }
456}
457
458#[derive(Clone, Debug, Default, Eq, PartialEq)]
460#[non_exhaustive]
461pub struct StopProviderCommandBuilder {
462 host_id: Option<String>,
463 provider_id: Option<String>,
464}
465
466impl StopProviderCommandBuilder {
467 #[must_use]
468 pub fn new() -> Self {
469 Self::default()
470 }
471
472 #[must_use]
473 pub fn host_id(mut self, v: &str) -> Self {
474 self.host_id = Some(v.into());
475 self
476 }
477
478 #[must_use]
479 pub fn provider_id(mut self, v: &str) -> Self {
480 self.provider_id = Some(v.into());
481 self
482 }
483
484 pub fn build(self) -> Result<StopProviderCommand> {
485 Ok(StopProviderCommand {
486 host_id: self
487 .host_id
488 .ok_or_else(|| "host id is required for stopping provider".to_string())?,
489 provider_id: self
490 .provider_id
491 .ok_or_else(|| "provider id is required for stopping provider".to_string())?,
492 })
493 }
494}
495
496#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
500#[non_exhaustive]
501pub struct UpdateComponentCommand {
502 #[serde(default)]
504 pub(crate) component_id: String,
505 #[serde(default, skip_serializing_if = "Option::is_none")]
509 pub(crate) annotations: Option<BTreeMap<String, String>>,
510 #[serde(default)]
512 pub(crate) host_id: String,
513 #[serde(default)]
515 pub(crate) new_component_ref: String,
516}
517
518impl UpdateComponentCommand {
519 #[must_use]
520 pub fn host_id(&self) -> &str {
521 &self.host_id
522 }
523
524 #[must_use]
525 pub fn component_id(&self) -> &str {
526 &self.component_id
527 }
528
529 #[must_use]
530 pub fn new_component_ref(&self) -> &str {
531 &self.new_component_ref
532 }
533
534 #[must_use]
535 pub fn annotations(&self) -> Option<&BTreeMap<String, String>> {
536 self.annotations.as_ref()
537 }
538
539 #[must_use]
540 pub fn builder() -> UpdateComponentCommandBuilder {
541 UpdateComponentCommandBuilder::default()
542 }
543}
544
545#[derive(Clone, Debug, Default, Eq, PartialEq)]
547#[non_exhaustive]
548pub struct UpdateComponentCommandBuilder {
549 host_id: Option<String>,
550 component_id: Option<String>,
551 new_component_ref: Option<String>,
552 annotations: Option<BTreeMap<String, String>>,
553}
554
555impl UpdateComponentCommandBuilder {
556 #[must_use]
557 pub fn new() -> Self {
558 Self::default()
559 }
560
561 #[must_use]
562 pub fn host_id(mut self, v: &str) -> Self {
563 self.host_id = Some(v.into());
564 self
565 }
566
567 #[must_use]
568 pub fn component_id(mut self, v: &str) -> Self {
569 self.component_id = Some(v.into());
570 self
571 }
572
573 #[must_use]
574 pub fn new_component_ref(mut self, v: &str) -> Self {
575 self.new_component_ref = Some(v.into());
576 self
577 }
578
579 #[must_use]
580 pub fn annotations(mut self, v: impl Into<BTreeMap<String, String>>) -> Self {
581 self.annotations = Some(v.into());
582 self
583 }
584
585 pub fn build(self) -> Result<UpdateComponentCommand> {
586 Ok(UpdateComponentCommand {
587 host_id: self
588 .host_id
589 .ok_or_else(|| "host id is required for updating components".to_string())?,
590 component_id: self
591 .component_id
592 .ok_or_else(|| "component id is required for updating components".to_string())?,
593 new_component_ref: self.new_component_ref.ok_or_else(|| {
594 "new component ref is required for updating components".to_string()
595 })?,
596 annotations: self.annotations,
597 })
598 }
599}
600
601#[cfg(test)]
602mod tests {
603 use std::collections::BTreeMap;
604
605 use super::{
606 ScaleComponentCommand, StartProviderCommand, StopHostCommand, StopProviderCommand,
607 UpdateComponentCommand,
608 };
609
610 #[test]
611 fn scale_component_command_builder() {
612 assert_eq!(
613 ScaleComponentCommand {
614 component_ref: "component_ref".into(),
615 component_id: "component_id".into(),
616 host_id: "host_id".into(),
617 config: vec!["c".into()],
618 allow_update: true,
619 annotations: Some(BTreeMap::from([("a".into(), "b".into())])),
620 max_instances: 1,
621 },
622 ScaleComponentCommand::builder()
623 .component_ref("component_ref")
624 .component_id("component_id")
625 .host_id("host_id")
626 .config(vec!["c".into()])
627 .allow_update(true)
628 .annotations(BTreeMap::from([("a".into(), "b".into())]))
629 .max_instances(1)
630 .build()
631 .unwrap()
632 )
633 }
634
635 #[test]
636 fn start_provider_command_builder() {
637 assert_eq!(
638 StartProviderCommand {
639 provider_id: "provider_id".into(),
640 provider_ref: "provider_ref".into(),
641 host_id: "host_id".into(),
642 config: vec!["p".into()],
643 annotations: Some(BTreeMap::from([("a".into(), "b".into())])),
644 },
645 StartProviderCommand::builder()
646 .provider_id("provider_id")
647 .provider_ref("provider_ref")
648 .host_id("host_id")
649 .config(vec!["p".into()])
650 .annotations(BTreeMap::from([("a".into(), "b".into())]))
651 .build()
652 .unwrap()
653 )
654 }
655
656 #[test]
657 fn stop_host_command_builder() {
658 assert_eq!(
659 StopHostCommand {
660 host_id: "host_id".into(),
661 timeout: Some(1),
662 },
663 StopHostCommand::builder()
664 .host_id("host_id")
665 .timeout(1)
666 .build()
667 .unwrap()
668 )
669 }
670
671 #[test]
672 fn stop_provider_command_builder() {
673 assert_eq!(
674 StopProviderCommand {
675 host_id: "host_id".into(),
676 provider_id: "provider_id".into(),
677 },
678 StopProviderCommand::builder()
679 .provider_id("provider_id")
680 .host_id("host_id")
681 .build()
682 .unwrap()
683 )
684 }
685
686 #[test]
687 fn update_component_command_builder() {
688 assert_eq!(
689 UpdateComponentCommand {
690 host_id: "host_id".into(),
691 component_id: "component_id".into(),
692 new_component_ref: "new_component_ref".into(),
693 annotations: Some(BTreeMap::from([("a".into(), "b".into())])),
694 },
695 UpdateComponentCommand::builder()
696 .host_id("host_id")
697 .component_id("component_id")
698 .new_component_ref("new_component_ref")
699 .annotations(BTreeMap::from([("a".into(), "b".into())]))
700 .build()
701 .unwrap()
702 )
703 }
704}