1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::io::Write;
use seaplane::api::locks::v1::{LockInfo, LockInfoInner, LockName as LockNameModel};
use serde::Serialize;
use tabwriter::TabWriter;
use crate::{
context::Ctx,
error::{CliError, Result},
ops::EncodedString,
printer::{printer, Output},
};
#[derive(Debug, Default, Clone, Serialize)]
pub struct LockName {
pub name: EncodedString,
}
impl LockName {
pub fn new<S: Into<String>>(name: S) -> Self { Self { name: EncodedString::new(name.into()) } }
pub fn from_name_unencoded<S: AsRef<[u8]>>(name: S) -> Self {
let name = base64::encode_config(name.as_ref(), base64::URL_SAFE_NO_PAD);
Self { name: EncodedString::new(name) }
}
pub fn to_model(&self) -> LockNameModel { LockNameModel::from_encoded(self.name.to_string()) }
}
#[derive(Debug, Serialize)]
pub struct HeldLock {
pub lock_id: String,
pub sequencer: u32,
}
impl Output for HeldLock {
fn print_json(&self, _ctx: &Ctx) -> Result<()> {
cli_println!("{}", serde_json::to_string(self)?);
Ok(())
}
fn print_table(&self, ctx: &Ctx) -> Result<()> {
let show_headers = !ctx.locks_ctx.get_or_init().no_header;
let mut ptr = printer();
let id_prefix = if show_headers { "LOCK-ID: " } else { "" };
let seq_prefix = if show_headers { "SEQUENCER: " } else { "" };
writeln!(ptr, "{id_prefix}{}", self.lock_id)?;
writeln!(ptr, "{seq_prefix}{}", self.sequencer)?;
ptr.flush()?;
Ok(())
}
}
#[derive(Debug, Serialize)]
pub struct ListedLockInfoInner {
pub ttl: u32,
#[serde(rename = "client-id")]
pub client_id: String,
pub ip: String,
}
impl From<LockInfoInner> for ListedLockInfoInner {
fn from(other: LockInfoInner) -> Self {
Self { ttl: other.ttl, client_id: other.client_id, ip: other.ip }
}
}
#[derive(Debug, Serialize)]
pub struct ListedLock {
name: EncodedString,
id: String,
info: ListedLockInfoInner,
}
impl From<LockInfo> for ListedLock {
fn from(other: LockInfo) -> Self {
let info = other.info.into();
Self {
name: EncodedString::new(other.name.encoded().to_owned()),
id: other.id.encoded().to_owned(),
info,
}
}
}
pub fn print_lock_table<I>(headers: bool, chunk: I, ctx: &Ctx) -> Result<()>
where
I: IntoIterator<Item = ListedLock>,
{
let buffer = Vec::new();
let mut tw = TabWriter::new(buffer);
if headers {
writeln!(tw, "LOCK-NAME\tLOCK-ID\tCLIENT-ID\tCLIENT-IP\tTTL")?;
}
let locksctx = ctx.locks_ctx.get_or_init();
for l in chunk {
if locksctx.decode {
tw.write_all(&l.name.decoded()?)?;
} else {
write!(tw, "{}", l.name)?;
};
writeln!(tw, "\t{}\t{}\t{}\t{}", l.id, l.info.client_id, l.info.ip, l.info.ttl)?;
}
tw.flush()?;
let mut ptr = printer();
let page = tw
.into_inner()
.map_err(|_| CliError::bail("IO flush error writing locks"))?;
ptr.write_all(&page)?;
ptr.flush()?;
Ok(())
}