Merge branch 'fix/dev_container' into dev

This commit is contained in:
Jack Wills
2022-09-05 08:33:37 -04:00
13 changed files with 203 additions and 63 deletions
+10 -6
View File
@@ -1,9 +1,13 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.217.4/containers/rust/.devcontainer/base.Dockerfile ARG VARIANT="bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
# [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye
ARG VARIANT="buster"
FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT}
RUN printf "alias cls='clear'\nalias ll='ls -l --human-readable --color=auto --group-directories-first --classify --time-style=long-iso -all'" >> /etc/bash.bashrc RUN printf "alias cls='clear'\nalias ll='ls -l --human-readable --color=auto --group-directories-first --classify --time-style=long-iso -all'" >> /etc/bash.bashrc
# RUN apt-get update && apt-get -y install upx-ucl ENV PATH="/home/vscode/.cargo/bin:${PATH}"
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends build-essential pkg-config libssl-dev
USER vscode
RUN curl --proto '=https' --tlsv1.2 -sSf curl https://sh.rustup.rs | sh -s -- -y
+1 -1
View File
@@ -34,7 +34,7 @@
"extensions": [ "extensions": [
"vadimcn.vscode-lldb", "vadimcn.vscode-lldb",
"mutantdino.resourcemonitor", "mutantdino.resourcemonitor",
"matklad.rust-analyzer", "rust-lang.rust-analyzer",
"tamasfe.even-better-toml", "tamasfe.even-better-toml",
"serayuzgur.crates", "serayuzgur.crates",
"christian-kohler.path-intellisense", "christian-kohler.path-intellisense",
+14
View File
@@ -1,3 +1,17 @@
### Chores
+ dependencies updated, [a3168daa3f769a6747dfbe61103073a7e80a1485], [78e59160bb6a978ee80e3a99eb72f051fb64e737]
### Fixes
+ limit image name to 64 chars max, [b8f7763dd5ac7d0361dd7bfc1dad40f50ee95ae1]
+ devcontainer updated, [3bde4f5629539cab3dbb57556663ab81685f9d7a]
### Features
+ derive Eq where appropriate, [d7c2601f959bc12a64cd25cef59c837e1e8c2b2a]
+ ignore containers 'oxker' containers, [1be9f52ad4a68f93142784e9df630c59cdec0a79]
### Refactors
+ improved way to remove leading '/' of container name, [832e9782d7765872cbb84df6b3703fc08cb353c9]
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.1.3'>v0.1.3</a> # <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.1.3'>v0.1.3</a>
### 2022-08-04 ### 2022-08-04
+4 -4
View File
@@ -14,15 +14,15 @@ categories = ["command-line-utilities"]
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
bollard = "0.13" bollard = "0.13"
cansi = "2.1" cansi = "2.2"
clap={version="3.2", features = ["derive", "unicode"] } clap={version="3.2", features = ["derive", "unicode"] }
crossterm = "0.24" crossterm = "0.25"
futures-util = "0.3" futures-util = "0.3"
parking_lot = {version= "0.12"} parking_lot = {version= "0.12"}
tokio = {version = "1.20", features=["full"]} tokio = {version = "1.21", features=["full"]}
tracing = "0.1" tracing = "0.1"
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
tui = "0.18" tui = "0.19"
[dev-dependencies] [dev-dependencies]
+103
View File
@@ -0,0 +1,103 @@
# FROM debian:bullseye-slim
# FROM
FROM alpine:latest
# FROM scratch
# DOCKER_GUID=1000 \
# DOCKER_UID=1000 \
# DOCKER_TIME_CONT=America \
# DOCKER_TIME_CITY=New_York \
# ARG DOCKER_APP_USER=oxker \
# DOCKER_APP_GROUP=docker
# ENV TZ=${DOCKER_TIME_CONT}/${DOCKER_TIME_CITY}
# RUN apt-get update \
# && apt-get install -y ca-certificates wget \
# && update-ca-certificates \
# RUN groupadd ${DOCKER_APP_GROUP}
# RUN useradd --no-create-home --no-log-init ${DOCKER_APP_USER}
# && mkdir /healthcheck /logs \
# && chown ${DOCKER_APP_USER}:${DOCKER_APP_GROUP} /logs
WORKDIR /app
# COPY --chown=${DOCKER_APP_USER}:${DOCKER_APP_GROUP} docker/healthcheck/health_api.sh /healthcheck
# Copy from local release destination
# COPY --chown=${DOCKER_APP_USER} target/release/oxker /app/
# COPY target/release/oxker .
# RUN mkdir app
COPY /target/x86_64-unknown-linux-musl/release/oxker ./
COPY ./start_oxker.sh ./
RUN chmod +x /app/start_oxker.sh
# Use an unprivileged user
# USER ${DOCKER_APP_USER}
ENV RUST_BACKTRACE=full
# ENTRYPOINT ["./oxker" ]
# CMD [ "./oxker"]
ENTRYPOINT ["/app/start_oxker.sh"]
# docker run --rm -ti \
# --name=ctop \
# --volume /var/run/docker.sock:/var/run/docker.sock:ro \
# # quay.io/vektorlab/ctop:latest
# docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker
# docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro ghcr.io/mrjackwills/oxker:latest
# could get arch, and then download appropoatley from github?
# FROM rust:latest as cargo-build
# WORKDIR /build
# ENV RUSTFLAGS="-C target-feature=+crt-static"
# COPY Cargo* ./build
# COPY src/ ./build
# RUN cargo build --release --target x86_64-unknown-linux-gnu
# #####################################
# #####################################
# FROM scratch
# COPY --from=cargo-build /build/target/x86_64-unknown-linux-gnu/release/oxker /oxker
# ENTRYPOINT [ "/oxker" ]
# FROM rust:latest AS build
# WORKDIR /oxker_build
# # Download the target for static linking.
# RUN rustup target add x86_64-unknown-linux-musl
# # Create a dummy project and build the app's dependencies.
# # If the Cargo.toml or Cargo.lock files have not changed,
# # we can use the docker build cache and skip these (typically slow) steps.
# RUN USER=root cargo new oxker --bin
# WORKDIR /oxker_build
# COPY Cargo.toml Cargo.lock ./
# # CMD ["sleep", "6000"]
# # RUN cargo build --release
# # Copy the source and build the application.
# COPY src ./src/
# RUN cargo install --target x86_64-unknown-linux-musl --path .
# # Copy the statically-linked binary into a scratch container.
# FROM scratch
# COPY --from=build /oxker_build/bin/oxker .
# # USER 1000
# CMD ["./oxker"]
# cross build --target x86_64-unknown-linux-musl --release
# rustup target add x86_64-unknown-linux-musl
# cargo build --release --target=x86_64-unknown-linux-musl
+6 -10
View File
@@ -1,17 +1,17 @@
<p align="center"> <p align="center">
<img src='./.github/logo.svg' width='125px'/> <img src='./.github/logo.svg' width='125px'/>
</p> </p>
<p align="center"> <p align="center">
<h1 align="center">oxker</h1> <h1 align="center">oxker</h1>
</p> </p>
<p align="center"> <p align="center">
A simple tui to view & control docker containers A simple tui to view & control docker containers
</p> </p>
<p align="center"> <p align="center">
Built in <a href='https://www.rust-lang.org/' target='_blank' rel='noopener noreferrer'>Rust</a>, making heavy use of <a href='https://github.com/fdehau/tui-rs' target='_blank' rel='noopener noreferrer'>tui-rs</a> & <a href='https://github.com/fussybeaver/bollard' target='_blank' rel='noopener noreferrer'>Bollard</a> Built in <a href='https://www.rust-lang.org/' target='_blank' rel='noopener noreferrer'>Rust</a>, making heavy use of <a href='https://github.com/fdehau/tui-rs' target='_blank' rel='noopener noreferrer'>tui-rs</a> & <a href='https://github.com/fussybeaver/bollard' target='_blank' rel='noopener noreferrer'>Bollard</a>
</p> </p>
<p align="center"> <p align="center">
@@ -25,8 +25,7 @@
Now published on <a href='https://www.crates.io/crates/oxker' target='_blank' rel='noopener noreferrer'>crates.io</a>, so if you have cargo installed, simply run Now published on <a href='https://www.crates.io/crates/oxker' target='_blank' rel='noopener noreferrer'>crates.io</a>, so if you have cargo installed, simply run
``` cargo install oxker``` ```cargo install oxker```
else see the <a href="https://github.com/mrjackwills/oxker/releases/latest" target='_blank' rel='noopener noreferrer'>pre-built binaries</a> else see the <a href="https://github.com/mrjackwills/oxker/releases/latest" target='_blank' rel='noopener noreferrer'>pre-built binaries</a>
@@ -107,11 +106,8 @@ using docker-compose.yml;
or individually or individually
```docker run --name redis -d redis:alpine3.16``` ```docker run --name redis -d redis:alpine3.16```
```docker run --name postgres -e POSTGRES_PASSWORD=never_use_this_password_in_production -d postgres:alpine3.16``` ```docker run --name postgres -e POSTGRES_PASSWORD=never_use_this_password_in_production -d postgres:alpine3.16```
```docker run -d --hostname my-rabbit --name rabbitmq rabbitmq:3``` ```docker run -d --hostname my-rabbit --name rabbitmq rabbitmq:3```
+15 -1
View File
@@ -78,7 +78,7 @@ impl<T> StatefulList<T> {
} }
/// States of the container /// States of the container
#[derive(Clone, Debug, PartialEq, PartialOrd)] #[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
pub enum State { pub enum State {
Dead, Dead,
Exited, Exited,
@@ -113,6 +113,20 @@ impl State {
} }
} }
impl From<String> for State {
fn from(input: String) -> Self {
match input.as_ref() {
"dead" => Self::Dead,
"exited" => Self::Exited,
"paused" => Self::Paused,
"removing" => Self::Removing,
"restarting" => Self::Restarting,
"running" => Self::Running,
_ => Self::Unknown,
}
}
}
impl From<&str> for State { impl From<&str> for State {
fn from(input: &str) -> Self { fn from(input: &str) -> Self {
match input { match input {
+27 -31
View File
@@ -20,7 +20,7 @@ pub struct AppData {
sorted_by: Option<(Header, SortedOrder)>, sorted_by: Option<(Header, SortedOrder)>,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum SortedOrder { pub enum SortedOrder {
Asc, Asc,
Desc, Desc,
@@ -313,7 +313,9 @@ impl AppData {
/// So can display nicely and evenly /// So can display nicely and evenly
pub fn get_width(&self) -> Columns { pub fn get_width(&self) -> Columns {
let mut output = Columns::new(); let mut output = Columns::new();
// Think this is causing issues
let count = |x: &String| x.chars().count(); let count = |x: &String| x.chars().count();
// let count = |_:&String|10;
for container in &self.containers.items { for container in &self.containers.items {
let cpu_count = count( let cpu_count = count(
@@ -437,51 +439,45 @@ impl AppData {
for i in containers.iter() { for i in containers.iter() {
if let Some(id) = i.id.as_ref() { if let Some(id) = i.id.as_ref() {
let mut name = i // maybe if no name then continue?
.names let name = i.names.as_ref().map_or("".to_owned(), |f|f.get(0).map_or("".to_owned(), |f|{
.as_ref() let mut n = f.clone();
.unwrap_or(&vec!["".to_owned()]) if n.starts_with('/') {
.get(0) n.remove(0);
.unwrap_or(&String::from("")) }
.clone(); n
if let Some(c) = name.chars().next() { }));
if c == '/' {
name.remove(0); let state = State::from(i.state.as_ref().map_or("dead".to_owned(), |f|f.trim().to_owned()));
} let status = i.status.as_ref().map_or("".to_owned(), |f| f.trim().to_owned());
} let image = i.image.as_ref().map_or("".to_owned(), |f|f.clone());
let state = State::from(i.state.as_ref().unwrap_or(&"dead".to_owned()).trim());
let status = i
.status
.as_ref()
.unwrap_or(&"".to_owned())
.trim()
.to_owned();
let image = i.image.as_ref().unwrap_or(&"".to_owned()).trim().to_owned();
if let Some(current_container) = self.get_container_by_id(id) { if let Some(current_container) = self.get_container_by_id(id) {
if current_container.name != name { if current_container.name != name {
current_container.name = name; current_container.name = name;
}; };
if current_container.status != status { if current_container.status != status {
current_container.status = status; current_container.status = status;
}; };
if current_container.state != state { if current_container.state != state {
current_container.docker_controls.items = DockerControls::gen_vec(&state); current_container.docker_controls.items = DockerControls::gen_vec(&state);
// Update the list state, needs to be None if the gen_vec returns an empty vec // Update the list state, needs to be None if the gen_vec returns an empty vec
match state { match state {
State::Removing | State::Restarting | State::Unknown => { State::Removing | State::Restarting | State::Unknown => {
current_container.docker_controls.state.select(None); current_container.docker_controls.state.select(None);
} }
_ => current_container.docker_controls.start(), _ => current_container.docker_controls.start(),
}; };
current_container.state = state; current_container.state = state;
}; };
if current_container.image != image { if current_container.image != image {
current_container.image = image; // current_container.image = image.chars().into_iter().take(64).collect();
current_container.image = image;
}; };
} else { } else {
let mut container = ContainerItem::new(id.clone(), status, image, state, name); // let mut container = ContainerItem::new(id.clone(), status, image.chars().into_iter().take(64).collect(), state, name);
let mut container = ContainerItem::new(id.clone(), status, image, state, name);
container.logs.end(); container.logs.end();
self.containers.items.push(container); self.containers.items.push(container);
} }
+14 -6
View File
@@ -1,6 +1,6 @@
use bollard::{ use bollard::{
container::{ListContainersOptions, LogsOptions, StartContainerOptions, Stats, StatsOptions}, container::{ListContainersOptions, LogsOptions, StartContainerOptions, Stats, StatsOptions},
Docker, Docker, service::ContainerSummary,
}; };
use futures_util::StreamExt; use futures_util::StreamExt;
use parking_lot::Mutex; use parking_lot::Mutex;
@@ -163,6 +163,7 @@ impl DockerData {
/// Get all current containers, handle into ContainerItem in the app_data struct rather than here /// 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 /// Just make sure that items sent are guaranteed to have an id
/// Will ignore any container that uses `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, String)> {
let containers = self let containers = self
.docker .docker
@@ -173,12 +174,19 @@ impl DockerData {
.await .await
.unwrap_or_default(); .unwrap_or_default();
let mut output = vec![]; let output = containers
// iter over containers, to only send ones which have an id, as use id for identification throughout!
containers
.iter() .iter()
.filter(|i| i.id.is_some()) .filter_map(|f| match f.id {
.for_each(|c| output.push(c.clone())); Some(_) => {
if f.command.as_ref().map_or(false, |c|c.contains("oxker")) {
None
} else {
Some(f.clone())
}
},
None => None,
})
.collect::<Vec<ContainerSummary>>();
self.app_data.lock().update_containers(&output); self.app_data.lock().update_containers(&output);
+1
View File
@@ -28,6 +28,7 @@ use ui::{create_ui, GuiState};
fn setup_tracing() { fn setup_tracing() {
tracing_subscriber::fmt().with_max_level(Level::INFO).init(); tracing_subscriber::fmt().with_max_level(Level::INFO).init();
// TODO write to file?
} }
#[tokio::main] #[tokio::main]
+1 -1
View File
@@ -6,7 +6,7 @@ pub mod log_sanitizer {
text::{Span, Spans}, text::{Span, Spans},
}; };
/// Attempt to colorize the given string to tui-rs standars /// Attempt to colorize the given string to tui-rs standards
pub fn colorize_logs(input: &str) -> Vec<Spans<'static>> { pub fn colorize_logs(input: &str) -> Vec<Spans<'static>> {
vec![Spans::from( vec![Spans::from(
categorise_text(input) categorise_text(input)
-3
View File
@@ -169,9 +169,6 @@ impl SelectablePanel {
/// Global gui_state, stored in an Arc<Mutex> /// Global gui_state, stored in an Arc<Mutex>
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct GuiState { pub struct GuiState {
// Think this should be a BMapTree, so can define order when iterating over potential intersects
// Is an issue if two panels are in the same space, sush as a smaller panel embedded, yet infront of, a larger panel
// If a BMapTree think it would mean have to implement ordering for SelectablePanel
panel_map: HashMap<SelectablePanel, Rect>, panel_map: HashMap<SelectablePanel, Rect>,
heading_map: HashMap<Header, Rect>, heading_map: HashMap<Header, Rect>,
loading_icon: Loading, loading_icon: Loading,
Executable
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
set -e
# No idea why this is sloving my issue, or even where the issue is originally coming from
sleep 1
exec ./oxker "$@"