diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c01623..e4c2345 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+### Chores
++ dependencies updated, [e3aa4420cb510df0381e311d37e768937070387a]
++ docker-compose alpine bump, [911c6596684db4ccbe7a55aadd6f595a95f89bb0]
++ github workflow use dtolnay/rust-toolchain, [57c18878690477a05d7330112a65d1d58a07901e]
+
+
+### Features
++ Clicking a header now toggles between Ascending -> Descending -> Default/no order. Use create_time as the default order - maybe add created column in future version, closes #18, [cf14ba498987db587c0f5bef8a67cf4113ffcb1e], [d1de291473d8a1028f1936429832d3820d75df54]
++ `-s` flag for showing self when operating in a containerised environment, [c93870e5fbbc7df35c69d32e4460d2104e521e33]
+
+
# v0.1.7
### 2022-11-13
diff --git a/README.md b/README.md
index ab0b38b..80875ea 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,7 @@ Available command line arguments
|```-r```| show raw logs, by default oxker will remove ANSI formatting (conflicts with -c) |
|```-c```| attempt to color the logs (conflicts with -r) |
|```-t```| remove timestamps from each log entry |
+|```-s```| if running via docker, will show the oxker container |
|```-g```| no tui, basically a pointless debugging mode, for now |
## Build step
diff --git a/containerised/Dockerfile b/containerised/Dockerfile
index 0d99e80..525ea7d 100644
--- a/containerised/Dockerfile
+++ b/containerised/Dockerfile
@@ -55,5 +55,6 @@ FROM alpine:latest AS runtime
COPY --from=builder /oxker /usr/local/bin
COPY ./containerised/start_oxker.sh ./
-# Run the application, this is used in the application itself, to stop itself show when running from a docker container, so DO NOT EDIT
+# Run the application
+# this is used in the application itself, to stop itself show when running from a docker container, so DO NOT EDIT
ENTRYPOINT [ "./start_oxker.sh"]
diff --git a/containerised/Dockerfile_dev b/containerised/Dockerfile_dev
index cc13dc0..4a91c38 100644
--- a/containerised/Dockerfile_dev
+++ b/containerised/Dockerfile_dev
@@ -8,13 +8,16 @@ FROM alpine:latest AS runtime
COPY ./target/x86_64-unknown-linux-musl/release/oxker /usr/local/bin
COPY ./containerised/start_oxker.sh ./
-# Run the application, this is used in the application itself, to stop itself show when running from a docker container, so DO NOT EDIT
+# Run the application
+# this is used in the application itself, to stop itself show when running from a docker container, so DO NOT EDIT
ENTRYPOINT [ "./start_oxker.sh"]
## One liner to build musl program, build docker image, then execute the image
-# cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
+# cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
+# Build production version
+# docker build --platform linux/arm/v6 --platform linux/arm64 --platform linux/amd64 -t oxker_dev -f containerised/Dockerfile . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
-## Buildx command to build musl version for all three platforms, should probably be executed in create_release
+# Buildx command to build musl version for all three platforms, should probably be executed in create_release
# docker buildx create --use
-# docker buildx build --platform linux/arm/v6,linux/arm64,linux/amd64 -t oxker_dev_all -o type=tar,dest=/tmp/oxker_dev_all.tar -f containerised/Dockerfile .
\ No newline at end of file
+# docker buildx build --platform linux/arm/v6,linux/arm64,linux/amd64 -t oxker_dev_all -o type=tar,dest=/tmp/oxker_dev_all.tar -f containerised/Dockerfile .
diff --git a/create_release.sh b/create_release.sh
index e25c211..102c776 100755
--- a/create_release.sh
+++ b/create_release.sh
@@ -104,12 +104,12 @@ update_release_body_and_changelog () {
echo -e "# ${NEW_TAG_WITH_V}\n${DATE_SUBHEADING}${CHANGELOG_ADDITION}$(cat CHANGELOG.md)" > CHANGELOG.md
# Update changelog to add links to commits [hex:8](url_with_full_commit)
- # "[aaaaaaaaaabbbbbbbbbbccccccccccddddddddd]" -> "[aaaaaaaa](https:/www.../commit/aaaaaaaaaabbbbbbbbbbccccccccccddddddddd),"
+ # "[aaaaaaaaaabbbbbbbbbbccccccccccddddddddd]" -> "[aaaaaaaa](https:/www.../commit/aaaaaaaaaabbbbbbbbbbccccccccccddddddddd)"
sed -i -E "s=(\s)\[([0-9a-f]{8})([0-9a-f]{32})\]= [\2](${GIT_REPO_URL}/commit/\2\3)=g" ./CHANGELOG.md
# Update changelog to add links to closed issues - comma included!
- # "closes #1," -> "closes [#1](https:/www.../issues/1),""
- sed -i -r -E "s=closes \#([0-9]+)\,=closes [#\1](${GIT_REPO_URL}/issues/\1),=g" ./CHANGELOG.md
+ # "closes #1" -> "closes [#1](https:/www.../issues/1),""
+ sed -i -r -E "s=closes \#([0-9]+)\=closes [#\1](${GIT_REPO_URL}/issues/\1)=g" ./CHANGELOG.md
}
# update version in cargo.toml, to match selected current version
diff --git a/src/app_data/container_state.rs b/src/app_data/container_state.rs
index b1a2b64..39a2d6c 100644
--- a/src/app_data/container_state.rs
+++ b/src/app_data/container_state.rs
@@ -356,6 +356,7 @@ pub type CpuTuple = (Vec<(f64, f64)>, CpuStats, State);
/// Info for each container
#[derive(Debug, Clone)]
pub struct ContainerItem {
+ pub created: u64,
pub cpu_stats: VecDeque,
pub docker_controls: StatefulList,
pub id: ContainerId,
@@ -366,19 +367,27 @@ pub struct ContainerItem {
pub mem_stats: VecDeque,
pub name: String,
pub rx: ByteStats,
- pub tx: ByteStats,
pub state: State,
pub status: String,
+ pub tx: ByteStats,
}
impl ContainerItem {
/// Create a new container item
- pub fn new(id: ContainerId, status: String, image: String, state: State, name: String) -> Self {
+ pub fn new(
+ id: ContainerId,
+ status: String,
+ image: String,
+ state: State,
+ name: String,
+ created: u64,
+ ) -> Self {
let mut docker_controls = StatefulList::new(DockerControls::gen_vec(state));
docker_controls.start();
let mut logs = StatefulList::new(vec![]);
logs.end();
Self {
+ created,
cpu_stats: VecDeque::with_capacity(60),
docker_controls,
id,
@@ -389,9 +398,9 @@ impl ContainerItem {
mem_stats: VecDeque::with_capacity(60),
name,
rx: ByteStats::default(),
- tx: ByteStats::default(),
state,
status,
+ tx: ByteStats::default(),
}
}
diff --git a/src/app_data/mod.rs b/src/app_data/mod.rs
index e429d1c..18fa486 100644
--- a/src/app_data/mod.rs
+++ b/src/app_data/mod.rs
@@ -11,10 +11,10 @@ pub use container_state::*;
/// Global app_state, stored in an Arc
#[derive(Debug, Clone)]
pub struct AppData {
- args: CliArgs,
error: Option,
logs_parsed: bool,
sorted_by: Option<(Header, SortedOrder)>,
+ pub args: CliArgs,
pub containers: StatefulList,
}
@@ -171,19 +171,20 @@ impl AppData {
output
}
- /// Sort the containers vec, based on a heading, either ascending or descending
- pub fn sort_containers(&mut self) {
- if let Some((head, ord)) = self.sorted_by.as_ref() {
+ /// Sort the containers vec, based on a heading, either ascending or descending,
+ /// If not sort set, then sort by created time
+ fn sort_containers(&mut self) {
+ if let Some((head, ord)) = self.sorted_by {
match head {
Header::State => match ord {
- SortedOrder::Desc => self
- .containers
- .items
- .sort_by(|a, b| a.state.order().cmp(&b.state.order())),
SortedOrder::Asc => self
.containers
.items
.sort_by(|a, b| b.state.order().cmp(&a.state.order())),
+ SortedOrder::Desc => self
+ .containers
+ .items
+ .sort_by(|a, b| a.state.order().cmp(&b.state.order())),
},
Header::Status => match ord {
SortedOrder::Asc => self
@@ -238,6 +239,10 @@ impl AppData {
SortedOrder::Desc => self.containers.items.sort_by(|a, b| b.tx.cmp(&a.tx)),
},
}
+ } else {
+ self.containers
+ .items
+ .sort_by(|a, b| a.created.cmp(&b.created))
}
}
@@ -428,9 +433,13 @@ impl AppData {
pub fn update_containers(&mut self, all_containers: &mut [ContainerSummary]) {
let all_ids = self.get_all_ids();
+ // Sort the containes by created, that have a constant order
+ all_containers.sort_by(|a, b| a.created.cmp(&b.created));
+
if !all_containers.is_empty() && self.containers.state.selected().is_none() {
self.containers.start();
}
+ let now = Self::get_systemtime();
for (index, id) in all_ids.iter().enumerate() {
if !all_containers
@@ -472,6 +481,8 @@ impl AppData {
.map_or(String::new(), std::clone::Clone::clone);
let id = ContainerId::from(id);
+
+ let created = i.created.map_or(now, |i| u64::try_from(i).unwrap_or(now));
// If container info already in containers Vec, then just update details
if let Some(item) = self.get_container_by_id(&id) {
if item.name != name {
@@ -496,7 +507,7 @@ impl AppData {
};
// else container not known, so make new ContainerItem and push into containers Vec
} else {
- let container = ContainerItem::new(id, status, image, state, name);
+ let container = ContainerItem::new(id, status, image, state, name, created);
self.containers.items.push(container);
}
}
diff --git a/src/docker_data/mod.rs b/src/docker_data/mod.rs
index f80c516..2ef4653 100644
--- a/src/docker_data/mod.rs
+++ b/src/docker_data/mod.rs
@@ -51,14 +51,14 @@ impl Binate {
pub struct DockerData {
app_data: Arc>,
+ args: CliArgs,
+ binate: Binate,
docker: Arc,
gui_state: Arc>,
initialised: bool,
is_running: Arc,
receiver: Receiver,
spawns: Arc>>>,
- timestamps: bool,
- binate: Binate,
}
impl DockerData {
@@ -173,7 +173,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
+ /// Will ignore any container that uses `./start_oxker.sh` as an entry point, unless the `-s` flag is set
pub async fn update_all_containers(&mut self) -> Vec<(bool, ContainerId)> {
let containers = self
.docker
@@ -188,7 +188,11 @@ impl DockerData {
.into_iter()
.filter_map(|f| match f.id {
Some(_) => {
- if f.command.as_ref().map_or(false, |c| c.contains("oxker")) {
+ if f.command
+ .as_ref()
+ .map_or(false, |c| c.starts_with("./start_oxker.sh"))
+ && self.args.show_self
+ {
None
} else {
Some(f)
@@ -200,9 +204,6 @@ impl DockerData {
self.app_data.lock().update_containers(&mut output);
- let current_sort = self.app_data.lock().get_sorted();
- self.app_data.lock().set_sorted(current_sort);
-
// Just get the containers that are currently running, or being restarted, no point updating info on paused or dead containers
output
.into_iter()
@@ -263,7 +264,7 @@ impl DockerData {
tokio::spawn(Self::update_log(
docker,
id.clone(),
- self.timestamps,
+ self.args.timestamp,
0,
app_data,
spawns,
@@ -288,7 +289,7 @@ impl DockerData {
tokio::spawn(Self::update_log(
docker,
container.id.clone(),
- self.timestamps,
+ self.args.timestamp,
container.last_updated,
app_data,
spawns,
@@ -323,6 +324,7 @@ impl DockerData {
let loading_spin = self.loading_spin(loading_uuid).await;
let all_ids = self.update_all_containers().await;
+
self.update_all_container_stats(&all_ids);
// Maybe only do a single one at first?
@@ -410,22 +412,22 @@ impl DockerData {
/// Initialise self, and start the message receiving loop
pub async fn init(
- args: CliArgs,
app_data: Arc>,
docker: Arc,
gui_state: Arc>,
receiver: Receiver,
is_running: Arc,
) {
+ let args = app_data.lock().args;
if app_data.lock().get_error().is_none() {
let mut inner = Self {
app_data,
+ args,
docker,
gui_state,
initialised: false,
receiver,
spawns: Arc::new(Mutex::new(HashMap::new())),
- timestamps: args.timestamp,
is_running,
binate: Binate::One,
};
diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs
index 5f61d01..5597eac 100644
--- a/src/input_handler/mod.rs
+++ b/src/input_handler/mod.rs
@@ -121,13 +121,16 @@ impl InputHandler {
self.mouse_capture = !self.mouse_capture;
}
- /// Sort containers based on a given header, switch asc to desc if already sorted, else always desc
- fn sort(&self, header: Header) {
- let mut output = Some((header, SortedOrder::Desc));
+ /// Sort containers based on a given header, if headings match, and already ascending, remove sorting
+ fn sort(&self, selected_header: Header) {
let mut locked_data = self.app_data.lock();
- if let Some((h, order)) = locked_data.get_sorted().as_ref() {
- if &SortedOrder::Desc == order && h == &header {
- output = Some((header, SortedOrder::Asc));
+ 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);
diff --git a/src/main.rs b/src/main.rs
index 6f69c8c..5b4b42a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -50,7 +50,6 @@ async fn main() {
let docker = Arc::new(docker);
let is_running = Arc::clone(&is_running);
tokio::spawn(DockerData::init(
- args,
docker_app_data,
docker,
docker_gui_state,
diff --git a/src/parse_args/mod.rs b/src/parse_args/mod.rs
index 5c70ce9..2a881ba 100644
--- a/src/parse_args/mod.rs
+++ b/src/parse_args/mod.rs
@@ -23,6 +23,10 @@ pub struct CliArgs {
#[clap(short = 'r', conflicts_with = "color")]
pub raw: bool,
+ /// Show self when running as a docker container
+ #[clap(short = 's')]
+ pub show_self: bool,
+
/// Don't draw gui - for debugging - mostly pointless
#[clap(short = 'g')]
pub gui: bool,
@@ -43,6 +47,7 @@ impl CliArgs {
color: args.color,
docker_interval: args.docker_interval,
gui: !args.gui,
+ show_self: !args.show_self,
raw: args.raw,
timestamp: !args.timestamp,
}
diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs
index 4ca9be5..17c06f8 100644
--- a/src/ui/draw_blocks.rs
+++ b/src/ui/draw_blocks.rs
@@ -364,7 +364,7 @@ pub fn heading_bar(
if x == a {
match b {
SortedOrder::Asc => suffix = " ⌃",
- SortedOrder::Desc => suffix = " ⌄",
+ SortedOrder::Desc => suffix = " ⌄",
}
suffix_margin = 2;
color = Color::White;