Skip to content

Commit

Permalink
feat: Support zstd compression (#134)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gmpinder authored Mar 23, 2024
1 parent da628db commit dcfdacc
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 15 deletions.
12 changes: 11 additions & 1 deletion src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)]
Expand Down Expand Up @@ -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()
};

Expand Down
11 changes: 7 additions & 4 deletions src/drivers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -173,7 +176,7 @@ pub trait BuildDriver: Sync + Send {

debug!("Pushing image {tag_image}");

self.push(&tag_image)
self.push(&tag_image, opts.compression)
})?;
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/drivers/buildah_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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}!");
Expand Down
15 changes: 11 additions & 4 deletions src/drivers/docker_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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}");
Expand Down Expand Up @@ -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");
Expand Down
20 changes: 20 additions & 0 deletions src/drivers/opts/build.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand Down Expand Up @@ -34,4 +51,7 @@ pub struct BuildTagPushOpts<'a> {
/// Defaults to 1.
#[builder(default = 1)]
pub retry_count: u8,

#[builder(default)]
pub compression: CompressionType,
}
10 changes: 7 additions & 3 deletions src/drivers/podman_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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}!");
Expand Down

0 comments on commit dcfdacc

Please sign in to comment.