Skip to content
Open
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
1 change: 1 addition & 0 deletions integration-tests/test-repo/files/bind/test-file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test Content
53 changes: 53 additions & 0 deletions integration-tests/test-repo/recipes/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,56 @@ modules:
snippets:
- '[ "$(cat /tmp/test-secret)" == "TEST_PASS" ]'

# test tmpfs mounts and is writable
- type: script
mounts:
- type: tmpfs
destination: /tmp/test-tmpfs
snippets:
- '[ -d /tmp/test-tmpfs ]'
- 'echo "Hello, World!" > /tmp/test-tmpfs/hello.txt'
- '[ "$(cat /tmp/test-tmpfs/hello.txt)" == "Hello, World!" ]'

# tmpfs should no longer be available in later module runs
- type: script
snippets:
- '[ ! -d /tmp/test-tmpfs ]'

# cache mount defined at recipe should be available in all module runs with shared content
- type: script
snippets:
- '[ -d /var/cache/private ]'
- 'echo "Cache Test" > /var/cache/private/cache_test.txt'

- type: script
snippets:
- '[ "$(cat /var/cache/private/cache_test.txt)" == "Cache Test" ]'

# test bind mounts
- type: script
mounts:
- type: bind
source: files/bind
destination: /var/bind-test
snippets:
- '[ -d /var/bind-test ]'
- '[ "$(cat /var/bind-test/test-file.txt)" == "Test Content" ]'
# test writing to bind mount
- 'echo "New Content" > /var/bind-test/new-file.txt'
- '[ "$(cat /var/bind-test/new-file.txt)" == "New Content" ]'
- 'rm /var/bind-test/new-file.txt'

# test readonly bind mounts
- type: script
mounts:
- type: bind
source: files/bind
destination: /var/readonly-bind-test
readonly: true
snippets:
- '[ -d /var/readonly-bind-test ]'
- '[ "$(cat /var/readonly-bind-test/test-file.txt)" == "Test Content" ]'
# test that writing to readonly bind mount fails
- 'if echo "New Content" > /var/readonly-bind-test/new-file.txt 2>/dev/null; then exit 1; else exit 0; fi'


5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-arm64
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe-bluefin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ base-image: ghcr.io/ublue-os/bluefin
blue-build-tag: none
cosign-version: none
image-version: stable
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-build-chunked-oci
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe-buildah.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-buildah
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-docker-external
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ image-version: latest
platforms:
- linux/amd64
- linux/arm64
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ image-version: latest
platforms:
- linux/amd64
- linux/arm64
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ image-version: latest
platforms:
- linux/amd64
- linux/arm64
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ image-version: latest
platforms:
- linux/amd64
- linux/arm64
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ image-version: latest
platforms:
- linux/amd64
- linux/arm64
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe-podman.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-podman
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe-rechunk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: cli/test-rechunk
description: This is my personal OS image.
base-image: quay.io/fedora/fedora-bootc
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/test-repo/recipes/recipe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ base-image: quay.io/fedora/fedora-bootc
blue-build-tag: none
cosign-version: none
image-version: latest
mounts:
- type: cache
sharing: private
id: private-cache
destination: /var/cache/private
stages:
- from-file: stages.yml
modules:
Expand Down
2 changes: 2 additions & 0 deletions recipe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod akmods_info;
mod maybe_version;
mod module;
mod module_ext;
mod mount;
mod recipe;
mod stage;
mod stages_ext;
Expand All @@ -15,6 +16,7 @@ pub use akmods_info::*;
pub use maybe_version::*;
pub use module::*;
pub use module_ext::*;
pub use mount::*;
pub use recipe::*;
pub use stage::*;
pub use stages_ext::*;
Expand Down
6 changes: 5 additions & 1 deletion recipe/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use miette::{Result, bail};
use serde::{Deserialize, Serialize};
use serde_yaml::Value;

use crate::{AkmodsInfo, ModuleExt, base_recipe_path};
use crate::{AkmodsInfo, ModuleExt, base_recipe_path, mount::Mount};

mod type_ver;

Expand Down Expand Up @@ -39,6 +39,10 @@ pub struct ModuleRequiredFields {
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub secrets: Vec<Secret>,

#[builder(default)]
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub mounts: Vec<Mount>,

#[serde(flatten)]
#[builder(default, into)]
pub config: IndexMap<String, Value>,
Expand Down
112 changes: 112 additions & 0 deletions recipe/src/mount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum MountCacheSharing {
/// The cache is shared between all builds.
#[serde(rename = "shared")]
Shared,

/// The cache is private to the current build.
#[serde(rename = "private")]
Private,

/// The cache is shared between builds, but only one build can use it at a time.
#[serde(rename = "locked")]
Locked,
}
impl std::fmt::Display for MountCacheSharing {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Shared => write!(f, "shared"),
Self::Private => write!(f, "private"),
Self::Locked => write!(f, "locked"),
}
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type")]
pub enum Mount {
/// A bind mount, which mounts a file or directory from the host.
#[serde(rename = "bind")]
Bind {
/// The source path on the host.
source: String,
/// The destination path in the container.
destination: String,
/// Whether the mount is read-only.
#[serde(default, rename = "readonly")]
readonly: bool,
},

/// A tmpfs mount, which mounts a temporary file system in memory.
#[serde(rename = "tmpfs")]
Tmpfs {
/// The destination path.
destination: String,
/// The size of the tmpfs. Can be specified in bytes or with a suffix (e.g. "100m" for 100 megabytes).
#[serde(skip_serializing_if = "Option::is_none")]
size: Option<String>,
},

/// A cache mount, which mounts a cache directory that can be shared between builds.
#[serde(rename = "cache")]
Cache {
/// The destination path.
destination: String,
/// The cache ID, which is used to identify the cache.
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
/// The cache sharing mode.
#[serde(skip_serializing_if = "Option::is_none")]
sharing: Option<MountCacheSharing>,
},
}

impl std::fmt::Display for Mount {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bind {
source,
destination,
readonly,
} => {
write!(f, "type=bind,source={source},dst={destination}")?;
if *readonly {
write!(f, ",readonly")?;
}
}
Self::Tmpfs { destination, size } => {
write!(f, "type=tmpfs,dst={destination}")?;
if let Some(size) = size {
write!(f, ",size={size}")?;
}
}
Self::Cache {
destination,
id,
sharing,
} => {
write!(f, "type=cache")?;
if let Some(sharing) = sharing {
write!(f, ",sharing={sharing}")?;
}
write!(f, ",dst={destination}")?;
if let Some(id) = id {
write!(f, ",id={id}")?;
}
}
}
Ok(())
}
}

impl Mount {
#[must_use]
pub const fn oci_suffix(&self) -> &'static str {
match self {
Self::Bind { .. } => ",z",
_ => "",
}
}
}
7 changes: 6 additions & 1 deletion recipe/src/recipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use miette::{Context, IntoDiagnostic, Result};
use oci_client::Reference;
use serde::{Deserialize, Serialize};

use crate::{Module, ModuleExt, StagesExt, maybe_version::MaybeVersion};
use crate::{Module, ModuleExt, StagesExt, maybe_version::MaybeVersion, mount::Mount};

/// The build recipe.
///
Expand Down Expand Up @@ -90,6 +90,11 @@ pub struct Recipe {
/// This hashmap provides custom labels from ther use to the image
#[serde(skip_serializing_if = "Option::is_none")]
pub labels: Option<HashMap<String, String>>,

/// The mounts to add to the image.
#[serde(skip_serializing_if = "Vec::is_empty", default)]
#[builder(default)]
pub mounts: Vec<Mount>,
}

impl Recipe {
Expand Down
Loading
Loading