Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions crates/lib/src/bootc_composefs/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ pub(crate) async fn initialize_composefs_repository(
/// Ex
/// docker://quay.io/some-image
/// containers-storage:some-image
/// docker-daemon:some-image-id
pub(crate) fn get_imgref(transport: &str, image: &str) -> String {
let img = image.strip_prefix(":").unwrap_or(&image);
let transport = transport.strip_suffix(":").unwrap_or(&transport);

if transport == "registry" {
format!("docker://{img}")
} else if transport == "docker-daemon" {
format!("docker-daemon:{img}")
} else {
format!("{transport}:{img}")
}
Expand Down Expand Up @@ -138,4 +141,12 @@ mod tests {
format!("docker://{IMAGE_NAME}")
);
}

#[test]
fn test_get_imgref_docker_daemon_transport() {
assert_eq!(
get_imgref("docker-daemon", IMAGE_NAME),
format!("docker-daemon:{IMAGE_NAME}")
);
}
}
2 changes: 1 addition & 1 deletion crates/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub(crate) struct SwitchOpts {
#[clap(long = "soft-reboot")]
pub(crate) soft_reboot: Option<SoftRebootMode>,

/// The transport; e.g. oci, oci-archive, containers-storage. Defaults to `registry`.
/// The transport; e.g. registry, oci, oci-archive, docker-daemon, containers-storage. Defaults to `registry`.
#[clap(long, default_value = "registry")]
pub(crate) transport: String,

Expand Down
6 changes: 6 additions & 0 deletions crates/ostree-ext/src/container/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub enum Transport {
ContainerStorage,
/// Local directory (`dir:`)
Dir,
/// Local Docker daemon (`docker-daemon:`)
DockerDaemon,
}

/// Combination of a remote image reference and transport.
Expand Down Expand Up @@ -114,6 +116,7 @@ impl TryFrom<&str> for Transport {
Self::DOCKER_ARCHIVE_STR => Self::DockerArchive,
Self::CONTAINERS_STORAGE_STR => Self::ContainerStorage,
Self::LOCAL_DIRECTORY_STR => Self::Dir,
Self::DOCKER_DAEMON_STR => Self::DockerDaemon,
o => return Err(anyhow!("Unknown transport '{}'", o)),
})
}
Expand All @@ -126,6 +129,7 @@ impl Transport {
const CONTAINERS_STORAGE_STR: &'static str = "containers-storage";
const LOCAL_DIRECTORY_STR: &'static str = "dir";
const REGISTRY_STR: &'static str = "registry";
const DOCKER_DAEMON_STR: &'static str = "docker-daemon";

/// Retrieve an identifier that can then be re-parsed from [`Transport::try_from::<&str>`].
pub fn serializable_name(&self) -> &'static str {
Expand All @@ -136,6 +140,7 @@ impl Transport {
Transport::DockerArchive => Self::DOCKER_ARCHIVE_STR,
Transport::ContainerStorage => Self::CONTAINERS_STORAGE_STR,
Transport::Dir => Self::LOCAL_DIRECTORY_STR,
Transport::DockerDaemon => Self::DOCKER_DAEMON_STR,
}
}
}
Expand Down Expand Up @@ -258,6 +263,7 @@ impl std::fmt::Display for Transport {
Self::OciDir => "oci:",
Self::ContainerStorage => "containers-storage:",
Self::Dir => "dir:",
Self::DockerDaemon => "docker-daemon:",
};
f.write_str(s)
}
Expand Down
25 changes: 21 additions & 4 deletions crates/ostree-ext/src/container/unencapsulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,34 @@ pub(crate) async fn fetch_layer<'a>(
tracing::debug!("fetching {}", layer.digest());
let layer_index = manifest.layers().iter().position(|x| x == layer).unwrap();
let (blob, driver, size);
let media_type: oci_image::MediaType;
let mut media_type: oci_image::MediaType;
match transport_src {
Transport::ContainerStorage => {
let layer_info = layer_info
.ok_or_else(|| anyhow!("skopeo too old to pull from containers-storage"))?;
// Both containers-storage and docker-daemon store layers uncompressed in their
// local storage, even though the manifest may indicate they are compressed.
// We need to use the actual media type from layer_info to avoid decompression errors.
Transport::ContainerStorage | Transport::DockerDaemon => {
let layer_info = layer_info.ok_or_else(|| {
anyhow!("skopeo too old to pull from containers-storage or docker-daemon")
})?;
let n_layers = layer_info.len();
let layer_blob = layer_info.get(layer_index).ok_or_else(|| {
anyhow!("blobid position {layer_index} exceeds diffid count {n_layers}")
})?;
size = layer_blob.size;
media_type = layer_blob.media_type.clone();

// docker-daemon stores layers uncompressed even when the media type
// indicates gzip compression. Translate to the uncompressed variant.
if transport_src == Transport::DockerDaemon {
if let oci_image::MediaType::Other(t) = &media_type {
if t.as_str() == "application/vnd.docker.image.rootfs.diff.tar.gzip" {
media_type = oci_image::MediaType::Other(
"application/vnd.docker.image.rootfs.diff.tar".to_string(),
);
}
}
}

(blob, driver) = proxy.get_blob(img, &layer_blob.digest, size).await?;
}
_ => {
Expand Down