feat: Support zstd compression (#134)

All supported versions of podman, buildah, and docker support the zstd
compression format. This format should allow users to pull less data
when updating their computers.
This commit is contained in:
Gerald Pinder 2024-03-23 17:32:21 -04:00 committed by GitHub
parent da628db1ee
commit dcfdacc518
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 63 additions and 15 deletions

View file

@ -21,7 +21,10 @@ use typed_builder::TypedBuilder;
use crate::{
commands::template::TemplateCommand,
credentials,
drivers::{opts::BuildTagPushOpts, Driver},
drivers::{
opts::{BuildTagPushOpts, CompressionType},
Driver,
},
};
use super::BlueBuildCommand;
@ -42,6 +45,12 @@ pub struct BuildCommand {
#[builder(default)]
push: bool,
/// The compression format the images
/// will be pushed in.
#[arg(short, long, default_value_t = CompressionType::Zstd)]
#[builder(default)]
compression_format: CompressionType,
/// Block `bluebuild` from retrying to push the image.
#[arg(short, long, default_value_t = true)]
#[builder(default)]
@ -207,6 +216,7 @@ impl BuildCommand {
.push(self.push)
.no_retry_push(self.no_retry_push)
.retry_count(self.retry_count)
.compression(self.compression_format)
.build()
};

View file

@ -22,8 +22,11 @@ use uuid::Uuid;
use crate::{credentials, image_metadata::ImageMetadata};
use self::{
buildah_driver::BuildahDriver, docker_driver::DockerDriver, opts::BuildTagPushOpts,
podman_driver::PodmanDriver, skopeo_driver::SkopeoDriver,
buildah_driver::BuildahDriver,
docker_driver::DockerDriver,
opts::{BuildTagPushOpts, CompressionType},
podman_driver::PodmanDriver,
skopeo_driver::SkopeoDriver,
};
mod buildah_driver;
@ -117,7 +120,7 @@ pub trait BuildDriver: Sync + Send {
///
/// # Errors
/// Will error if the push fails.
fn push(&self, image: &str) -> Result<()>;
fn push(&self, image: &str, compression: CompressionType) -> Result<()>;
/// Runs the login logic for the strategy.
///
@ -173,7 +176,7 @@ pub trait BuildDriver: Sync + Send {
debug!("Pushing image {tag_image}");
self.push(&tag_image)
self.push(&tag_image, opts.compression)
})?;
}
}

View file

@ -7,7 +7,7 @@ use serde::Deserialize;
use crate::credentials;
use super::{BuildDriver, DriverVersion};
use super::{opts::CompressionType, BuildDriver, DriverVersion};
#[derive(Debug, Deserialize)]
struct BuildahVersionJson {
@ -68,9 +68,13 @@ impl BuildDriver for BuildahDriver {
Ok(())
}
fn push(&self, image: &str) -> Result<()> {
fn push(&self, image: &str, compression: CompressionType) -> Result<()> {
trace!("buildah push {image}");
let status = Command::new("buildah").arg("push").arg(image).status()?;
let status = Command::new("buildah")
.arg("push")
.arg(format!("--compression-format={compression}"))
.arg(image)
.status()?;
if status.success() {
info!("Successfully pushed {image}!");

View file

@ -11,7 +11,11 @@ use serde::Deserialize;
use crate::image_metadata::ImageMetadata;
use super::{credentials, opts::BuildTagPushOpts, BuildDriver, DriverVersion, InspectDriver};
use super::{
credentials,
opts::{BuildTagPushOpts, CompressionType},
BuildDriver, DriverVersion, InspectDriver,
};
#[derive(Debug, Deserialize)]
struct DockerVerisonJsonClient {
@ -88,7 +92,7 @@ impl BuildDriver for DockerDriver {
Ok(())
}
fn push(&self, image: &str) -> Result<()> {
fn push(&self, image: &str, _: CompressionType) -> Result<()> {
trace!("DockerDriver::push({image})");
trace!("docker push {image}");
@ -162,8 +166,11 @@ impl BuildDriver for DockerDriver {
}
if opts.push {
trace!("--push");
command.arg("--push");
trace!("--output type=image,name={image},push=true,compression={},oci-mediatypes=true", opts.compression);
command.arg("--output").arg(format!(
"type=image,name={image},push=true,compression={},oci-mediatypes=true",
opts.compression
));
} else {
trace!("--builder default");
command.arg("--builder").arg("default");

View file

@ -1,7 +1,24 @@
use std::borrow::Cow;
use clap::ValueEnum;
use typed_builder::TypedBuilder;
#[derive(Debug, Copy, Clone, Default, ValueEnum)]
pub enum CompressionType {
#[default]
Zstd,
Gzip,
}
impl std::fmt::Display for CompressionType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Zstd => "zstd",
Self::Gzip => "gzip",
})
}
}
/// Options for building, tagging, and pusing images.
#[derive(Debug, Clone, TypedBuilder)]
pub struct BuildTagPushOpts<'a> {
@ -34,4 +51,7 @@ pub struct BuildTagPushOpts<'a> {
/// Defaults to 1.
#[builder(default = 1)]
pub retry_count: u8,
#[builder(default)]
pub compression: CompressionType,
}

View file

@ -8,7 +8,7 @@ use serde::Deserialize;
use crate::image_metadata::ImageMetadata;
use super::{credentials, BuildDriver, DriverVersion, InspectDriver};
use super::{credentials, opts::CompressionType, BuildDriver, DriverVersion, InspectDriver};
#[derive(Debug, Deserialize)]
struct PodmanVersionJsonClient {
@ -79,9 +79,13 @@ impl BuildDriver for PodmanDriver {
Ok(())
}
fn push(&self, image: &str) -> Result<()> {
fn push(&self, image: &str, compression: CompressionType) -> Result<()> {
trace!("podman push {image}");
let status = Command::new("podman").arg("push").arg(image).status()?;
let status = Command::new("podman")
.arg("push")
.arg(format!("--compression-format={compression}"))
.arg(image)
.status()?;
if status.success() {
info!("Successfully pushed {image}!");