Skip to content

Commit

Permalink
list HTTP, HTTPS and TCP listeners in the CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
Keksoj committed Jan 12, 2023
1 parent 079d025 commit c4c51fa
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 10 deletions.
7 changes: 6 additions & 1 deletion bin/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,10 @@ pub enum SubCmd {
email: String,
#[clap(long = "id", help = "cluster identifier (usually an application)")]
cluster_id: String,
#[clap(long = "old-cert", help = "path of the previous certificate (optional)")]
#[clap(
long = "old-cert",
help = "path of the previous certificate (optional)"
)]
old_certificate_path: Option<String>,
#[clap(long = "new-cert", help = "where to write the new certificate")]
new_certificate_path: String,
Expand Down Expand Up @@ -561,6 +564,8 @@ pub enum ListenerCmd {
#[clap(subcommand)]
cmd: TcpListenerCmd,
},
#[clap(name = "list", about = "List all listeners")]
List,
}

#[derive(Subcommand, PartialEq, Eq, Clone, Debug)]
Expand Down
2 changes: 2 additions & 0 deletions bin/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub enum Success {
DumpState(CommandResponseContent), // the cloned state
HandledClientRequest,
ListFrontends(CommandResponseContent), // the list of frontends
ListListeners(CommandResponseContent), // the list of listeners
ListWorkers(CommandResponseContent),
LoadState(String, usize, usize), // state path, oks, errors
Logging(String), // new logging level
Expand Down Expand Up @@ -149,6 +150,7 @@ impl std::fmt::Display for Success {
Self::DumpState(_) => write!(f, "Successfully gathered state from the main process"),
Self::HandledClientRequest => write!(f, "Successfully handled the client request"),
Self::ListFrontends(_) => write!(f, "Successfully gathered the list of frontends"),
Self::ListListeners(_) => write!(f, "Successfully listed all listeners"),
Self::ListWorkers(_) => write!(f, "Successfully listed all workers"),
Self::LoadState(path, ok, error) => write!(
f,
Expand Down
15 changes: 14 additions & 1 deletion bin/src/command/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use sozu_command_lib::{
buffer::fixed::Buffer,
command::{
CommandRequest, CommandRequestOrder, CommandResponse, CommandResponseContent,
CommandStatus, FrontendFilters, ListedFrontends, RunState, WorkerInfo, PROTOCOL_VERSION,
CommandStatus, FrontendFilters, ListedFrontends, ListenersList, RunState, WorkerInfo,
PROTOCOL_VERSION,
},
config::Config,
logging,
Expand Down Expand Up @@ -55,6 +56,7 @@ impl CommandServer {
CommandRequestOrder::DumpState => self.dump_state().await,
CommandRequestOrder::ListWorkers => self.list_workers().await,
CommandRequestOrder::ListFrontends(filters) => self.list_frontends(filters).await,
CommandRequestOrder::ListListeners => self.list_listeners(),
CommandRequestOrder::LoadState { path } => {
self.load_state(
Some(request_identifier.client),
Expand Down Expand Up @@ -419,6 +421,16 @@ impl CommandServer {
)))
}

fn list_listeners(&self) -> anyhow::Result<Option<Success>> {
Ok(Some(Success::ListListeners(
CommandResponseContent::ListenersList(ListenersList {
http_listeners: self.state.http_listeners.clone(),
https_listeners: self.state.https_listeners.clone(),
tcp_listeners: self.state.tcp_listeners.clone(),
}),
)))
}

pub async fn list_workers(&mut self) -> anyhow::Result<Option<Success>> {
let workers: Vec<WorkerInfo> = self
.workers
Expand Down Expand Up @@ -1402,6 +1414,7 @@ impl CommandServer {
| Success::ListFrontends(crd)
| Success::ListWorkers(crd)
| Success::Query(crd)
| Success::ListListeners(crd)
| Success::Status(crd) => Some(crd),
_ => None,
};
Expand Down
26 changes: 25 additions & 1 deletion bin/src/ctl/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
create_channel,
display::{
print_available_metrics, print_certificates, print_frontend_list, print_json_response,
print_metrics, print_query_response_data, print_status,
print_listeners, print_metrics, print_query_response_data, print_status,
},
CommandManager,
},
Expand Down Expand Up @@ -750,6 +750,30 @@ impl CommandManager {
Ok(())
}

pub fn list_listeners(&mut self) -> anyhow::Result<()> {
let id = generate_id();

self.send_request(&id, CommandRequestOrder::ListListeners)?;

loop {
let response = self.read_channel_message_with_timeout()?;
match response.status {
CommandStatus::Processing => println!("processing order…"),
CommandStatus::Error => {
bail!("could not get the list of listeners: {}", response.message);
}
CommandStatus::Ok => {
match response.content {
Some(CommandResponseContent::ListenersList(list)) => print_listeners(list),
_ => println!("Received an unexpected response: {:?}", response),
}
break;
}
}
}
Ok(())
}

pub fn order_command(&mut self, order: ProxyRequestOrder) -> Result<(), anyhow::Error> {
let id = generate_id();

Expand Down
115 changes: 114 additions & 1 deletion bin/src/ctl/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,117 @@ use anyhow::{self, bail, Context};
use prettytable::{Row, Table};

use sozu_command_lib::{
command::{CommandResponseContent, ListedFrontends, WorkerInfo},
command::{CommandResponseContent, ListedFrontends, ListenersList, WorkerInfo},
proxy::{
AggregatedMetricsData, ClusterMetricsData, FilteredData, QueryAnswer,
QueryAnswerCertificate, QueryAnswerMetrics, Route, WorkerMetrics,
},
};

pub fn print_listeners(listeners_list: ListenersList) {
println!("\nHTTP LISTENERS\n================");

for (_, (http_listener, activated)) in listeners_list.http_listeners.iter() {
let mut table = Table::new();
table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS);
table.add_row(row![
"socket address",
format!("{:?}", http_listener.address)
]);
table.add_row(row![
"public address",
format!("{:?}", http_listener.public_address),
]);
table.add_row(row!["404", http_listener.answer_404]);
table.add_row(row!["503", http_listener.answer_503]);
table.add_row(row!["expect proxy", http_listener.expect_proxy]);
table.add_row(row!["sticky name", http_listener.sticky_name]);
table.add_row(row!["front timeout", http_listener.front_timeout]);
table.add_row(row!["back timeout", http_listener.back_timeout]);
table.add_row(row!["connect timeout", http_listener.connect_timeout]);
table.add_row(row!["request timeout", http_listener.request_timeout]);
table.add_row(row!["activated", activated]);
table.printstd();
}

println!("\nHTTPS LISTENERS\n================");

for (_, (https_listener, activated)) in listeners_list.https_listeners.iter() {
let mut table = Table::new();
table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS);
let mut tls_versions = String::new();
for tls_version in https_listener.versions.iter() {
tls_versions.push_str(&format!("{:?}\n", tls_version));
}

table.add_row(row![
"socket address",
format!("{:?}", https_listener.address)
]);
table.add_row(row![
"public address",
format!("{:?}", https_listener.public_address)
]);
table.add_row(row!["404", https_listener.answer_404,]);
table.add_row(row!["503", https_listener.answer_503,]);
table.add_row(row!["versions", tls_versions]);
table.add_row(row![
"cipher list",
list_string_vec(&https_listener.cipher_list),
]);
table.add_row(row![
"cipher suites",
list_string_vec(&https_listener.cipher_suites),
]);
table.add_row(row![
"signature algorithms",
list_string_vec(&https_listener.signature_algorithms),
]);
table.add_row(row![
"groups list",
list_string_vec(&https_listener.groups_list),
]);
table.add_row(row!["key", format!("{:?}", https_listener.key),]);
table.add_row(row!["expect proxy", https_listener.expect_proxy,]);
table.add_row(row!["sticky name", https_listener.sticky_name,]);
table.add_row(row!["front timeout", https_listener.front_timeout,]);
table.add_row(row!["back timeout", https_listener.back_timeout,]);
table.add_row(row!["connect timeout", https_listener.connect_timeout,]);
table.add_row(row!["request timeout", https_listener.request_timeout,]);
table.add_row(row!["activated", activated]);
table.printstd();
}

println!("\nTCP LISTENERS\n================");

if !listeners_list.tcp_listeners.is_empty() {
let mut table = Table::new();
table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS);
table.add_row(row!["TCP frontends"]);
table.add_row(row![
"socket address",
"public address",
"expect proxy",
"front timeout",
"back timeout",
"connect timeout",
"activated"
]);
for (_, (tcp_listener, activated)) in listeners_list.tcp_listeners.iter() {
table.add_row(row![
format!("{:?}", tcp_listener.address),
format!("{:?}", tcp_listener.public_address),
tcp_listener.expect_proxy,
tcp_listener.front_timeout,
tcp_listener.back_timeout,
tcp_listener.connect_timeout,
activated,
]);
}
table.printstd();
}
}

pub fn print_status(worker_info_vec: Vec<WorkerInfo>) {
let mut table = Table::new();
table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS);
Expand Down Expand Up @@ -626,3 +730,12 @@ pub fn print_available_metrics(answers: &BTreeMap<String, QueryAnswer>) -> anyho
}
Ok(())
}

fn list_string_vec(vec: &Vec<String>) -> String {
let mut output = String::new();
for item in vec.iter() {
output.push_str(&item);
output.push_str("\n");
}
output
}
1 change: 1 addition & 0 deletions bin/src/ctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl CommandManager {
ListenerCmd::Http { cmd } => self.http_listener_command(cmd),
ListenerCmd::Https { cmd } => self.https_listener_command(cmd),
ListenerCmd::Tcp { cmd } => self.tcp_listener_command(cmd),
ListenerCmd::List => self.list_listeners(),
},
SubCmd::Certificate { cmd } => match cmd {
CertificateCmd::Add {
Expand Down
35 changes: 29 additions & 6 deletions command/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::{collections::BTreeMap, fmt, net::SocketAddr};
use std::{
collections::{BTreeMap, HashMap},
fmt,
net::SocketAddr,
};

use crate::{
proxy::{
AggregatedMetricsData, HttpFrontend, ProxyEvent, ProxyRequestOrder, QueryAnswer,
TcpFrontend,
AggregatedMetricsData, HttpFrontend, HttpListener, HttpsListener, ProxyEvent,
ProxyRequestOrder, QueryAnswer, TcpFrontend, TcpListener,
},
state::ConfigState,
};
Expand All @@ -17,15 +21,21 @@ pub enum CommandRequestOrder {
/// an order to forward to workers
Proxy(Box<ProxyRequestOrder>),
/// save Sōzu's parseable state as a file
SaveState { path: String },
SaveState {
path: String,
},
/// load a state file
LoadState { path: String },
LoadState {
path: String,
},
/// dump the state in JSON
DumpState,
/// list the workers and their status
ListWorkers,
/// list the frontends, filtered by protocol and/or domain
ListFrontends(FrontendFilters),
// list all listeners
ListListeners,
/// launche a new worker
LaunchWorker(String),
/// upgrade the main process
Expand All @@ -35,7 +45,9 @@ pub enum CommandRequestOrder {
/// subscribe to proxy events
SubscribeEvents,
/// reload the configuration from the config file, or a new file
ReloadConfiguration { path: Option<String> },
ReloadConfiguration {
path: Option<String>,
},
/// give status of main process and all workers
Status,
}
Expand Down Expand Up @@ -96,6 +108,8 @@ pub enum CommandResponseContent {
FrontendList(ListedFrontends),
// this is new
Status(Vec<WorkerInfo>),
/// all listeners
ListenersList(ListenersList),
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
Expand All @@ -105,6 +119,15 @@ pub struct ListedFrontends {
pub tcp_frontends: Vec<TcpFrontend>,
}

/// All listeners, listed for the CLI.
/// the bool indicates if it is active or not
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct ListenersList {
pub http_listeners: HashMap<SocketAddr, (HttpListener, bool)>,
pub https_listeners: HashMap<SocketAddr, (HttpsListener, bool)>,
pub tcp_listeners: HashMap<SocketAddr, (TcpListener, bool)>,
}

/// Responses of the main process to the CLI (or other client)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CommandResponse {
Expand Down

0 comments on commit c4c51fa

Please sign in to comment.