chore: merge release-v0.1.11 into main
This commit is contained in:
@@ -1,17 +1,16 @@
|
|||||||
### 2022-12-25
|
### 2023-01-03
|
||||||
|
|
||||||
### Chores
|
### Chores
|
||||||
+ dependencies updated, [1525b3150293015c0fb2f2161da463b21ac2694c], [8d539ab14809136d743c49d60779687fc8eeef6d], [1774217a8a657d261397d213e5ecee667cf3b6b1]
|
+ dependencies updated, [9b09146aadae5727a5fee4de5fe0c1d70c581c22]
|
||||||
+ Rust 1.66 linting, [bf9dcac7045c0d2314df147ec2744a3ad886564b]
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
+ Caching on github action, [a91c9aa45ffd5c998cd1b83d8e90d0912893c31f]
|
+ `install.sh` script added, for automated platform selection, download, and installation, [7a42eba6b0968314af40ff87bcc42d288f6860bc], [e0703b76a1a28cfe266f130a7f7dec92f1b5ad58]
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
+ comment typo, [7899b773569fed86343a035d3023bf34297fdabb]
|
+ If a sort order is set, sort containers on every `update_stats()` execution, [cfdea77594e48c8c20a4d6e6c7ea31c9181361a1]
|
||||||
|
|
||||||
### Refactors
|
### Refactors
|
||||||
+ remove_ansi() to single liner, [57c3a6c186b916faba24bf7b5cdbbda31d636a7e]
|
+ input sort executed in app_data struct `sort_by_header()`, [3cdc5fae02097628799209f371ae9292e513e76c]
|
||||||
|
|
||||||
|
|
||||||
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
|
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.1.11'>v0.1.11</a>
|
||||||
|
### 2023-01-03
|
||||||
|
|
||||||
|
### Chores
|
||||||
|
+ dependencies updated, [9b09146a](https://github.com/mrjackwills/oxker/commit/9b09146aadae5727a5fee4de5fe0c1d70c581c22)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
+ `install.sh` script added, for automated platform selection, download, and installation, [7a42eba6](https://github.com/mrjackwills/oxker/commit/7a42eba6b0968314af40ff87bcc42d288f6860bc), [e0703b76](https://github.com/mrjackwills/oxker/commit/e0703b76a1a28cfe266f130a7f7dec92f1b5ad58)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
+ If a sort order is set, sort containers on every `update_stats()` execution, [cfdea775](https://github.com/mrjackwills/oxker/commit/cfdea77594e48c8c20a4d6e6c7ea31c9181361a1)
|
||||||
|
|
||||||
|
### Refactors
|
||||||
|
+ input sort executed in app_data struct `sort_by_header()`, [3cdc5fae](https://github.com/mrjackwills/oxker/commit/3cdc5fae02097628799209f371ae9292e513e76c)
|
||||||
|
|
||||||
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.1.10'>v0.1.10</a>
|
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.1.10'>v0.1.10</a>
|
||||||
### 2022-12-25
|
### 2022-12-25
|
||||||
|
|
||||||
|
|||||||
Generated
+9
-9
@@ -540,9 +540,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.16.0"
|
version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
@@ -558,7 +558,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxker"
|
name = "oxker"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bollard",
|
"bollard",
|
||||||
@@ -724,9 +724,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.5"
|
version = "0.36.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
|
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -750,18 +750,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.151"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.151"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
|
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "oxker"
|
name = "oxker"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Jack Wills <email@mrjackwills.com>"]
|
authors = ["Jack Wills <email@mrjackwills.com>"]
|
||||||
description = "A simple tui to view & control docker containers"
|
description = "A simple tui to view & control docker containers"
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ install -Dm 755 oxker -t "${HOME}/.local/bin" &&
|
|||||||
rm oxker_linux_x86_64.tar.gz oxker
|
rm oxker_linux_x86_64.tar.gz oxker
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or, for automatic platform selection, download, and installation (to `$HOME/.local/bin`)
|
||||||
|
|
||||||
|
*One should verify all scripts before running in your shell*
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://raw.githubusercontent.com/mrjackwills/oxker/main/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
```oxker```
|
```oxker```
|
||||||
|
|||||||
+1
-3
@@ -153,7 +153,6 @@ check_tag () {
|
|||||||
break;;
|
break;;
|
||||||
*)
|
*)
|
||||||
error_close "invalid option $REPLY"
|
error_close "invalid option $REPLY"
|
||||||
break;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -268,8 +267,7 @@ main() {
|
|||||||
do
|
do
|
||||||
case $choice in
|
case $choice in
|
||||||
0)
|
0)
|
||||||
exit
|
exit;;
|
||||||
break;;
|
|
||||||
1)
|
1)
|
||||||
cargo_test
|
cargo_test
|
||||||
main
|
main
|
||||||
|
|||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
case "$(arch)" in
|
||||||
|
x86_64) SUFFIX="x86_64";;
|
||||||
|
aarch64) SUFFIX="aarch64";;
|
||||||
|
armv6l) SUFFIX="armv6";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$SUFFIX" ]; then
|
||||||
|
wget "https://github.com/mrjackwills/oxker/releases/latest/download/oxker_linux_${SUFFIX}.tar.gz"
|
||||||
|
tar xzvf "oxker_linux_${SUFFIX}.tar.gz" oxker
|
||||||
|
install -Dm 755 oxker -t "${HOME}/.local/bin"
|
||||||
|
rm "oxker_linux_${SUFFIX}.tar.gz" oxker
|
||||||
|
fi
|
||||||
+41
-16
@@ -56,21 +56,6 @@ impl fmt::Display for Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AppData {
|
impl AppData {
|
||||||
pub const fn get_sorted(&self) -> Option<(Header, SortedOrder)> {
|
|
||||||
self.sorted_by
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change the sorted order, also set the selected container state to match new order
|
|
||||||
pub fn set_sorted(&mut self, x: Option<(Header, SortedOrder)>) {
|
|
||||||
self.sorted_by = x;
|
|
||||||
self.sort_containers();
|
|
||||||
self.containers
|
|
||||||
.state
|
|
||||||
.select(self.containers.items.iter().position(|i| {
|
|
||||||
self.get_selected_container_id()
|
|
||||||
.map_or(false, |id| i.id == id)
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
/// Generate a default app_state
|
/// Generate a default app_state
|
||||||
pub fn default(args: CliArgs) -> Self {
|
pub fn default(args: CliArgs) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -82,6 +67,41 @@ impl AppData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn get_sorted(&self) -> Option<(Header, SortedOrder)> {
|
||||||
|
self.sorted_by
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove the sorted header & order, and sort by default - created datetime
|
||||||
|
pub fn reset_sorted(&mut self) {
|
||||||
|
self.set_sorted(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sort containers based on a given header, if headings match, and already ascending, remove sorting
|
||||||
|
pub fn set_sort_by_header(&mut self, selected_header: Header) {
|
||||||
|
let mut output = Some((selected_header, SortedOrder::Asc));
|
||||||
|
if let Some((current_header, order)) = self.get_sorted() {
|
||||||
|
if current_header == selected_header {
|
||||||
|
match order {
|
||||||
|
SortedOrder::Desc => output = None,
|
||||||
|
SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.set_sorted(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Change the sorted order, also set the selected container state to match new order
|
||||||
|
fn set_sorted(&mut self, x: Option<(Header, SortedOrder)>) {
|
||||||
|
self.sorted_by = x;
|
||||||
|
self.sort_containers();
|
||||||
|
self.containers
|
||||||
|
.state
|
||||||
|
.select(self.containers.items.iter().position(|i| {
|
||||||
|
self.get_selected_container_id()
|
||||||
|
.map_or(false, |id| i.id == id)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/// Current time as unix timestamp
|
/// Current time as unix timestamp
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
fn get_systemtime() -> u64 {
|
fn get_systemtime() -> u64 {
|
||||||
@@ -185,7 +205,7 @@ impl AppData {
|
|||||||
|
|
||||||
/// Sort the containers vec, based on a heading, either ascending or descending,
|
/// Sort the containers vec, based on a heading, either ascending or descending,
|
||||||
/// If not sort set, then sort by created time
|
/// If not sort set, then sort by created time
|
||||||
fn sort_containers(&mut self) {
|
pub fn sort_containers(&mut self) {
|
||||||
if let Some((head, ord)) = self.sorted_by {
|
if let Some((head, ord)) = self.sorted_by {
|
||||||
match head {
|
match head {
|
||||||
Header::State => match ord {
|
Header::State => match ord {
|
||||||
@@ -411,6 +431,7 @@ impl AppData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update container mem, cpu, & network stats, in single function so only need to call .lock() once
|
/// Update container mem, cpu, & network stats, in single function so only need to call .lock() once
|
||||||
|
/// Will also, if a sort is set, sort the containers
|
||||||
pub fn update_stats(
|
pub fn update_stats(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: &ContainerId,
|
id: &ContainerId,
|
||||||
@@ -439,6 +460,10 @@ impl AppData {
|
|||||||
container.tx.update(tx);
|
container.tx.update(tx);
|
||||||
container.mem_limit.update(mem_limit);
|
container.mem_limit.update(mem_limit);
|
||||||
}
|
}
|
||||||
|
// need to benchmark this?
|
||||||
|
if self.get_sorted().is_some() {
|
||||||
|
self.sort_containers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update, or insert, containers
|
/// Update, or insert, containers
|
||||||
|
|||||||
+15
-12
@@ -156,18 +156,20 @@ impl DockerData {
|
|||||||
let docker = Arc::clone(&self.docker);
|
let docker = Arc::clone(&self.docker);
|
||||||
let app_data = Arc::clone(&self.app_data);
|
let app_data = Arc::clone(&self.app_data);
|
||||||
let spawns = Arc::clone(&self.spawns);
|
let spawns = Arc::clone(&self.spawns);
|
||||||
let key = SpawnId::Stats((id.clone(), self.binate));
|
let spawn_key = SpawnId::Stats((id.clone(), self.binate));
|
||||||
let spawn_key = key.clone();
|
self.spawns
|
||||||
self.spawns.lock().entry(key).or_insert_with(|| {
|
.lock()
|
||||||
tokio::spawn(Self::update_container_stat(
|
.entry(spawn_key.clone())
|
||||||
docker,
|
.or_insert_with(|| {
|
||||||
id.clone(),
|
tokio::spawn(Self::update_container_stat(
|
||||||
app_data,
|
docker,
|
||||||
*is_running,
|
id.clone(),
|
||||||
spawns,
|
app_data,
|
||||||
spawn_key,
|
*is_running,
|
||||||
))
|
spawns,
|
||||||
});
|
spawn_key,
|
||||||
|
))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self.binate = self.binate.toggle();
|
self.binate = self.binate.toggle();
|
||||||
}
|
}
|
||||||
@@ -299,6 +301,7 @@ impl DockerData {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.update_all_container_stats(&all_ids);
|
self.update_all_container_stats(&all_ids);
|
||||||
|
self.app_data.lock().sort_containers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Animate the loading icon
|
/// Animate the loading icon
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use tui::layout::Rect;
|
|||||||
|
|
||||||
mod message;
|
mod message;
|
||||||
use crate::{
|
use crate::{
|
||||||
app_data::{AppData, DockerControls, Header, SortedOrder},
|
app_data::{AppData, DockerControls, Header},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
docker_data::DockerMessage,
|
docker_data::DockerMessage,
|
||||||
ui::{GuiState, SelectablePanel, Status},
|
ui::{GuiState, SelectablePanel, Status},
|
||||||
@@ -121,19 +121,9 @@ impl InputHandler {
|
|||||||
self.mouse_capture = !self.mouse_capture;
|
self.mouse_capture = !self.mouse_capture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sort containers based on a given header, if headings match, and already ascending, remove sorting
|
/// Sort the containers by a given header
|
||||||
fn sort(&self, selected_header: Header) {
|
fn sort(&self, selected_header: Header) {
|
||||||
let mut locked_data = self.app_data.lock();
|
self.app_data.lock().set_sort_by_header(selected_header);
|
||||||
let mut output = Some((selected_header, SortedOrder::Asc));
|
|
||||||
if let Some((current_header, order)) = locked_data.get_sorted() {
|
|
||||||
if current_header == selected_header {
|
|
||||||
match order {
|
|
||||||
SortedOrder::Desc => output = None,
|
|
||||||
SortedOrder::Asc => output = Some((selected_header, SortedOrder::Desc)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locked_data.set_sorted(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a quit message to docker, to abort all spawns, if an error is returned, set is_running to false here instead
|
/// Send a quit message to docker, to abort all spawns, if an error is returned, set is_running to false here instead
|
||||||
@@ -173,7 +163,7 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match key_code {
|
match key_code {
|
||||||
KeyCode::Char('0') => self.app_data.lock().set_sorted(None),
|
KeyCode::Char('0') => self.app_data.lock().reset_sorted(),
|
||||||
KeyCode::Char('1') => self.sort(Header::State),
|
KeyCode::Char('1') => self.sort(Header::State),
|
||||||
KeyCode::Char('2') => self.sort(Header::Status),
|
KeyCode::Char('2') => self.sort(Header::Status),
|
||||||
KeyCode::Char('3') => self.sort(Header::Cpu),
|
KeyCode::Char('3') => self.sort(Header::Cpu),
|
||||||
|
|||||||
Reference in New Issue
Block a user