Add docker to needed.txt and add basic docker image support.

This commit is contained in:
Hellx2 2024-08-18 19:37:10 +10:00
parent b7e9476431
commit ae1f1edd76
5 changed files with 200 additions and 26 deletions

View file

@ -1,6 +1,3 @@
cargo cargo
gtk4-devel gtk4-devel
docker
I didn't need to install this? - Deyo
cairo-gobject-devel

91
src/containers/images.rs Normal file
View file

@ -0,0 +1,91 @@
use gtk::{prelude::BoxExt, Label};
use super::Image;
pub fn images() -> gtk::Box {
let images_box = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.build();
/*
Using unwrap here is allowed since this will always
return a Some when the second param is false
*/
let images = crate::pkexec("docker images".to_owned(), false)
.unwrap()
.lines()
.map(|x| x.parse::<Image>().unwrap())
.collect::<Vec<Image>>();
for image in images {
let image_box = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.css_classes(["image-box"])
.build();
let repo_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
repo_box.append(
&Label::builder()
.label("Repository: ")
.css_classes(["repo-label"])
.build(),
);
repo_box.append(&Label::builder().label(&image.repository).build());
let tag_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
tag_box.append(
&Label::builder()
.label("Tag: ")
.css_classes(["tag-label"])
.build(),
);
tag_box.append(&Label::builder().label(&image.tag).build());
let id_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
id_box.append(
&Label::builder()
.label("Image ID: ")
.css_classes(["id-label"])
.build(),
);
id_box.append(&Label::builder().label(&image.id).build());
let created_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
created_box.append(
&Label::builder()
.label("Created at: ")
.css_classes(["created-label"])
.build(),
);
created_box.append(&Label::builder().label(&image.created).build());
let size_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.build();
size_box.append(
&Label::builder()
.label("Size: ")
.css_classes(["size-label"])
.build(),
);
size_box.append(&Label::builder().label(&image.size).build());
image_box.append(&repo_box);
image_box.append(&tag_box);
image_box.append(&id_box);
image_box.append(&created_box);
image_box.append(&size_box);
images_box.append(&image_box);
}
images_box
}

69
src/containers/mod.rs Normal file
View file

@ -0,0 +1,69 @@
use std::str::FromStr;
use gtk::{prelude::BoxExt, Stack, StackSidebar};
use images::images;
pub mod images;
/**
Page for managing Docker containers and images.
## TODO
- Move to it's own file/folder
- Add the following pages: "Containers", "Images", "Browse"
*/
pub fn containers() -> gtk::Box {
// Initialize the box that will be used as a page.
let containers_box = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.css_classes(["containers-box"])
.build();
let containers_stack = Stack::builder()
.halign(gtk::Align::Fill)
.valign(gtk::Align::Fill)
.hexpand(true)
.vexpand(true)
.build();
let containers_sidebar = StackSidebar::builder()
.stack(&containers_stack)
.halign(gtk::Align::Start)
.valign(gtk::Align::Fill)
.build();
containers_stack.add_titled(&images(), Some("images"), "Images");
// Start the docker daemon if it isn't running.
if std::fs::metadata("/var/run/docker.pid").is_err() {
crate::pkexec("dockerd".to_owned(), true);
}
// Append a new label as a title and return the box.
containers_box.append(&containers_sidebar);
containers_box.append(&containers_stack);
containers_box
}
pub struct Image {
pub repository: String,
pub tag: String,
pub id: String,
pub created: String,
pub size: String,
}
impl FromStr for Image {
type Err = String;
fn from_str(value: &str) -> Result<Self, String> {
let mut parts = value.split_whitespace().map(|x| x.to_owned());
Ok(Self {
repository: parts.next().expect("Failed to get repository."),
tag: parts.next().expect("Failed to get tag."),
id: parts.next().expect("Failed to get ID."),
created: parts.next().expect("Failed to get created time."),
size: parts.next().expect("Failed to get size."),
})
}
}

View file

@ -6,6 +6,7 @@ use gtk::{
Stack, StackSwitcher, Stack, StackSwitcher,
}; };
pub mod containers;
pub mod drivers; pub mod drivers;
pub mod packages; pub mod packages;
@ -65,7 +66,7 @@ fn on_activate(app: &Application) {
*/ */
main_stack.add_titled(&packages::packages(), Some("packages"), "Packages"); main_stack.add_titled(&packages::packages(), Some("packages"), "Packages");
main_stack.add_titled(&drivers::drivers(), Some("drivers"), "Drivers"); main_stack.add_titled(&drivers::drivers(), Some("drivers"), "Drivers");
main_stack.add_titled(&containers(), Some("containers"), "Containers"); main_stack.add_titled(&containers::containers(), Some("containers"), "Containers");
main_stack.add_titled(&virtualization(), Some("virtualization"), "Virtualization"); main_stack.add_titled(&virtualization(), Some("virtualization"), "Virtualization");
// Append the switcher and stack to the main box // Append the switcher and stack to the main box
@ -77,26 +78,6 @@ fn on_activate(app: &Application) {
main_window.present(); main_window.present();
} }
/**
Page for managing Docker containers and images.
## TODO
- Move to it's own file/folder
- Add the following pages: "Containers", "Images", "Browse"
*/
fn containers() -> gtk::Box {
// Initialize the box that will be used as a page.
let containers_box = gtk::Box::builder()
.orientation(Horizontal)
.css_classes(["containers-box"])
.build();
// Append a new label as a title and return the box.
containers_box.append(&gtk::Label::new(Some("Containers")));
containers_box
}
/** /**
For managing virtual machines. For managing virtual machines.
@ -116,6 +97,28 @@ fn virtualization() -> gtk::Box {
virtualization_box virtualization_box
} }
pub fn pkexec(cmd: String, spawn: bool) -> Option<String> {
dbg!(cmd.split_whitespace().next());
if spawn {
std::process::Command::new("pkexec")
.args(cmd.split_whitespace())
.spawn()
.expect("Failed to spawn child process!");
None
} else {
Some(
String::from_utf8(
std::process::Command::new("pkexec")
.args(cmd.split_whitespace())
.output()
.expect("Failed to get output of command.")
.stdout,
)
.expect("Failed to convert command stdout to string!"),
)
}
}
/// Function to link `style.css` to the application. /// Function to link `style.css` to the application.
fn on_startup(_: &Application) { fn on_startup(_: &Application) {
let css_provider = gtk::CssProvider::new(); let css_provider = gtk::CssProvider::new();

View file

@ -26,9 +26,23 @@
padding: 10px; padding: 10px;
} }
/* Packages */
.license-label, .license-label,
.version-label, .version-label,
.size-label, .size-label,
.description-label { .description-label,
/* Containers */
.repo-label,
.tag-label,
.id-label,
.created-label,
.size-label {
font-weight: bold; font-weight: bold;
} }
.image-box {
border-radius: 10px;
box-shadow: -1px -1px #ff0000;
margin: 10px;
}