Skip to content

Commit

Permalink
feat: use ContainerId new_type
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjackwills committed Oct 1, 2022
1 parent 6731002 commit 41cbb84
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 43 deletions.
43 changes: 41 additions & 2 deletions src/app_data/container_state.rs
Expand Up @@ -11,6 +11,45 @@ const ONE_KB: f64 = 1000.0;
const ONE_MB: f64 = ONE_KB * 1000.0;
const ONE_GB: f64 = ONE_MB * 1000.0;

#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct ContainerId(String);

impl From<String> for ContainerId {
fn from(x: String) -> Self {
Self(x)
}
}

impl From<&String> for ContainerId {
fn from(x: &String) -> Self {
Self(x.clone())
}
}

impl From<&str> for ContainerId {
fn from(x: &str) -> Self {
Self(x.to_owned())
}
}

impl ContainerId {
pub fn get(&self) -> &str {
self.0.as_str()
}
}

impl Ord for ContainerId {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}

impl PartialOrd for ContainerId {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

#[derive(Debug, Clone)]
pub struct StatefulList<T> {
pub state: ListState,
Expand Down Expand Up @@ -326,7 +365,7 @@ pub type CpuTuple = (Vec<(f64, f64)>, CpuStats, State);
pub struct ContainerItem {
pub cpu_stats: VecDeque<CpuStats>,
pub docker_controls: StatefulList<DockerControls>,
pub id: String,
pub id: ContainerId,
pub image: String,
pub last_updated: u64,
pub logs: StatefulList<ListItem<'static>>,
Expand All @@ -341,7 +380,7 @@ pub struct ContainerItem {

impl ContainerItem {
/// Create a new container item
pub fn new(id: String, status: String, image: String, state: State, name: String) -> Self {
pub fn new(id: ContainerId, status: String, image: String, state: State, name: String) -> Self {
let mut docker_controls = StatefulList::new(DockerControls::gen_vec(state));
docker_controls.start();
Self {
Expand Down
33 changes: 14 additions & 19 deletions src/app_data/mod.rs
Expand Up @@ -163,20 +163,14 @@ impl AppData {
}

/// Find the id of the currently selected container.
/// If any containers on system, will always return a string.
/// If any containers on system, will always return a container id
/// Only returns None when no containers found.
pub fn get_selected_container_id(&self) -> Option<String> {
pub fn get_selected_container_id(&self) -> Option<ContainerId> {
let mut output = None;
if let Some(index) = self.containers.state.selected() {
let id = self
.containers
.items
.iter()
.skip(index)
.take(1)
.map(|i| i.id.clone())
.collect::<String>();
output = Some(id);
if let Some(x) = self.containers.items.get(index) {
output = Some(x.id.clone());
}
}
output
}
Expand Down Expand Up @@ -307,7 +301,7 @@ impl AppData {
}
}

pub fn initialised(&mut self, all_ids: &[(bool, String)]) -> bool {
pub fn initialised(&mut self, all_ids: &[(bool, ContainerId)]) -> bool {
let count_is_running = all_ids.iter().filter(|i| i.0).count();
let number_with_cpu_status = self
.containers
Expand Down Expand Up @@ -379,7 +373,7 @@ impl AppData {
}

/// Get all containers ids
pub fn get_all_ids(&self) -> Vec<String> {
pub fn get_all_ids(&self) -> Vec<ContainerId> {
self.containers
.items
.iter()
Expand All @@ -388,14 +382,14 @@ impl AppData {
}

/// find container given id
fn get_container_by_id(&mut self, id: &str) -> Option<&mut ContainerItem> {
self.containers.items.iter_mut().find(|i| i.id == id)
fn get_container_by_id(&mut self, id: &ContainerId) -> Option<&mut ContainerItem> {
self.containers.items.iter_mut().find(|i| &i.id == id)
}

/// Update container mem, cpu, & network stats, in single function so only need to call .lock() once
pub fn update_stats(
&mut self,
id: &str,
id: &ContainerId,
cpu_stat: Option<f64>,
mem_stat: Option<u64>,
mem_limit: u64,
Expand Down Expand Up @@ -435,7 +429,7 @@ impl AppData {
if !containers
.iter()
.filter_map(|i| i.id.as_ref())
.any(|x| x == id)
.any(|x| ContainerId::from(x) == id.clone())
{
// If removed container is currently selected, then change selected to previous
// This will default to 0 in any edge cases
Expand Down Expand Up @@ -476,7 +470,8 @@ impl AppData {
.as_ref()
.map_or("".to_owned(), std::clone::Clone::clone);

if let Some(current_container) = self.get_container_by_id(id) {
let id = ContainerId::from(id.as_str());
if let Some(current_container) = self.get_container_by_id(&id) {
if current_container.name != name {
current_container.name = name;
};
Expand Down Expand Up @@ -512,7 +507,7 @@ impl AppData {
}

/// update logs of a given container, based on id
pub fn update_log_by_id(&mut self, output: &[String], id: &str) {
pub fn update_log_by_id(&mut self, output: &[String], id: &ContainerId) {
let tz = Self::get_systemtime();
let color = self.args.color;
let raw = self.args.raw;
Expand Down
12 changes: 7 additions & 5 deletions src/docker_data/message.rs
@@ -1,10 +1,12 @@
use crate::app_data::ContainerId;

#[derive(Debug, Clone)]
pub enum DockerMessage {
Update,
Start(String),
Restart(String),
Pause(String),
Unpause(String),
Stop(String),
Start(ContainerId),
Restart(ContainerId),
Pause(ContainerId),
Unpause(ContainerId),
Stop(ContainerId),
Quit,
}
34 changes: 17 additions & 17 deletions src/docker_data/mod.rs
Expand Up @@ -16,7 +16,7 @@ use tokio::{sync::mpsc::Receiver, task::JoinHandle};
use uuid::Uuid;

use crate::{
app_data::{AppData, DockerControls},
app_data::{AppData, ContainerId, DockerControls},
app_error::AppError,
parse_args::CliArgs,
ui::GuiState,
Expand All @@ -26,8 +26,8 @@ pub use message::DockerMessage;

#[derive(Debug, Clone, Eq, Hash, PartialEq)]
enum SpawnId {
Stats((String, Binate)),
Log(String),
Stats((ContainerId, Binate)),
Log(ContainerId),
}

/// Cpu & Mem stats take twice as long as the update interval to get a value, so will have two being executed at the same time
Expand Down Expand Up @@ -94,15 +94,15 @@ impl DockerData {
/// remove if from spawns hashmap when complete
async fn update_container_stat(
docker: Arc<Docker>,
id: String,
id: ContainerId,
app_data: Arc<Mutex<AppData>>,
is_running: bool,
spawns: Arc<Mutex<HashMap<SpawnId, JoinHandle<()>>>>,
spawn_id: SpawnId,
) {
let mut stream = docker
.stats(
&id,
id.get(),
Some(StatsOptions {
stream: false,
one_shot: !is_running,
Expand Down Expand Up @@ -149,7 +149,7 @@ impl DockerData {
}

/// Update all stats, spawn each container into own tokio::spawn thread
fn update_all_container_stats(&mut self, all_ids: &[(bool, String)]) {
fn update_all_container_stats(&mut self, all_ids: &[(bool, ContainerId)]) {
for (is_running, id) in all_ids.iter() {
let docker = Arc::clone(&self.docker);
let app_data = Arc::clone(&self.app_data);
Expand All @@ -174,7 +174,7 @@ impl DockerData {
/// Get all current containers, handle into ContainerItem in the app_data struct rather than here
/// Just make sure that items sent are guaranteed to have an id
/// Will ignore any container that contains `oxker` as an entry point
pub async fn update_all_containers(&mut self) -> Vec<(bool, String)> {
pub async fn update_all_containers(&mut self) -> Vec<(bool, ContainerId)> {
let containers = self
.docker
.list_containers(Some(ListContainersOptions::<String> {
Expand Down Expand Up @@ -211,7 +211,7 @@ impl DockerData {
(
i.state == Some("running".to_owned())
|| i.state == Some("restarting".to_owned()),
id.clone(),
ContainerId::from(id.as_str()),
)
})
})
Expand All @@ -223,7 +223,7 @@ impl DockerData {
/// remove if from spawns hashmap when complete
async fn update_log(
docker: Arc<Docker>,
id: String,
id: ContainerId,
timestamps: bool,
since: u64,
app_data: Arc<Mutex<AppData>>,
Expand All @@ -232,11 +232,11 @@ impl DockerData {
let options = Some(LogsOptions::<String> {
stdout: true,
timestamps,
since: since as i64,
since: i64::try_from(since).unwrap_or_default(),
..Default::default()
});

let mut logs = docker.logs(&id, options);
let mut logs = docker.logs(id.get(), options);
let mut output = vec![];

while let Some(value) = logs.next().await {
Expand All @@ -252,7 +252,7 @@ impl DockerData {
}

/// Update all logs, spawn each container into own tokio::spawn thread
fn init_all_logs(&mut self, all_ids: &[(bool, String)]) {
fn init_all_logs(&mut self, all_ids: &[(bool, ContainerId)]) {
for (_, id) in all_ids.iter() {
let docker = Arc::clone(&self.docker);
let app_data = Arc::clone(&self.app_data);
Expand Down Expand Up @@ -349,7 +349,7 @@ impl DockerData {
match message {
DockerMessage::Pause(id) => {
let loading_spin = self.loading_spin(loading_uuid).await;
if docker.pause_container(&id).await.is_err() {
if docker.pause_container(id.get()).await.is_err() {
app_data
.lock()
.set_error(AppError::DockerCommand(DockerControls::Pause));
Expand All @@ -358,7 +358,7 @@ impl DockerData {
}
DockerMessage::Restart(id) => {
let loading_spin = self.loading_spin(loading_uuid).await;
if docker.restart_container(&id, None).await.is_err() {
if docker.restart_container(id.get(), None).await.is_err() {
app_data
.lock()
.set_error(AppError::DockerCommand(DockerControls::Restart));
Expand All @@ -368,7 +368,7 @@ impl DockerData {
DockerMessage::Start(id) => {
let loading_spin = self.loading_spin(loading_uuid).await;
if docker
.start_container(&id, None::<StartContainerOptions<String>>)
.start_container(id.get(), None::<StartContainerOptions<String>>)
.await
.is_err()
{
Expand All @@ -380,7 +380,7 @@ impl DockerData {
}
DockerMessage::Stop(id) => {
let loading_spin = self.loading_spin(loading_uuid).await;
if docker.stop_container(&id, None).await.is_err() {
if docker.stop_container(id.get(), None).await.is_err() {
app_data
.lock()
.set_error(AppError::DockerCommand(DockerControls::Stop));
Expand All @@ -389,7 +389,7 @@ impl DockerData {
}
DockerMessage::Unpause(id) => {
let loading_spin = self.loading_spin(loading_uuid).await;
if docker.unpause_container(&id).await.is_err() {
if docker.unpause_container(id.get()).await.is_err() {
app_data
.lock()
.set_error(AppError::DockerCommand(DockerControls::Unpause));
Expand Down
1 change: 1 addition & 0 deletions src/input_handler/mod.rs
Expand Up @@ -137,6 +137,7 @@ impl InputHandler {
}

/// Handle any keyboard button events
#[allow(clippy::too_many_lines)]
async fn button_press(&mut self, key_code: KeyCode) {
let show_error = self.app_data.lock().show_error;
let show_info = self.gui_state.lock().show_help;
Expand Down

0 comments on commit 41cbb84

Please sign in to comment.