Skip to content

Commit

Permalink
Merge pull request ostreedev#366 from cgwalters/deploy-warn-filtered
Browse files Browse the repository at this point in the history
container: Add an API to warn about non-ostree compatible content
  • Loading branch information
jmarrero authored Sep 13, 2022
2 parents f99c7fe + 0079d52 commit 550faa8
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 12 deletions.
23 changes: 11 additions & 12 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,18 +573,10 @@ async fn container_store(
let _ = printer.await;
}
let import = import?;
let commit = &repo.load_commit(&import.merge_commit)?.0;
let commit_meta = &glib::VariantDict::new(Some(&commit.child_value(0)));
let filtered = commit_meta.lookup::<ostree_container::store::MetaFilteredData>(
ostree_container::store::META_FILTERED,
)?;
if let Some(filtered) = filtered {
for (layerid, filtered) in filtered {
eprintln!("Unsupported paths filtered from {}:", layerid);
for (prefix, count) in filtered {
eprintln!(" {}: {}", prefix, count);
}
}
if let Some(msg) =
ostree_container::store::image_filtered_content_warning(repo, &imgref.imgref)?
{
eprintln!("{msg}")
}
println!("Wrote: {} => {}", imgref, import.merge_commit);
Ok(())
Expand Down Expand Up @@ -793,6 +785,7 @@ where
} => {
let sysroot = &ostree::Sysroot::new(Some(&gio::File::for_path(&sysroot)));
sysroot.load(gio::NONE_CANCELLABLE)?;
let repo = &sysroot.repo().unwrap();
let kargs = karg.as_deref();
let kargs = kargs.map(|v| {
let r: Vec<_> = v.iter().map(|s| s.as_str()).collect();
Expand All @@ -811,6 +804,12 @@ where
Some(options),
)
.await?;
if let Some(msg) = ostree_container::store::image_filtered_content_warning(
repo,
&imgref.imgref,
)? {
eprintln!("{msg}")
}
if let Some(p) = write_commitid_to {
std::fs::write(&p, state.merge_commit.as_bytes())
.with_context(|| format!("Failed to write commitid to {}", p))?;
Expand Down
33 changes: 33 additions & 0 deletions lib/src/container/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,39 @@ fn prune_image(repo: &ostree::Repo, image: &ImageReference) -> Result<()> {
Ok(())
}

/// Given an image, if it has any non-ostree compatible content, return a suitable
/// warning message.
pub fn image_filtered_content_warning(
repo: &ostree::Repo,
image: &ImageReference,
) -> Result<Option<String>> {
use std::fmt::Write;

let ostree_ref = ref_for_image(image)?;
let rev = repo.require_rev(&ostree_ref)?;
let commit_obj = repo.load_commit(rev.as_str())?.0;
let commit_meta = &glib::VariantDict::new(Some(&commit_obj.child_value(0)));

let r = commit_meta
.lookup::<MetaFilteredData>(META_FILTERED)?
.filter(|v| !v.is_empty())
.map(|v| {
let mut filtered = HashMap::<&String, u32>::new();
for paths in v.values() {
for (k, v) in paths {
let e = filtered.entry(k).or_default();
*e += v;
}
}
let mut buf = "Image contains non-ostree compatible file paths:".to_string();
for (k, v) in filtered {
write!(buf, " {k}: {v}").unwrap();
}
buf
});
Ok(r)
}

/// Remove the specified image references.
///
/// This function assumes no transaction is active on the repository.
Expand Down
64 changes: 64 additions & 0 deletions lib/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ async fn impl_test_container_chunked(format: ExportLayout) -> Result<()> {

assert_eq!(store::list_images(fixture.destrepo()).unwrap().len(), 1);

assert!(
store::image_filtered_content_warning(fixture.destrepo(), &imgref.imgref)
.unwrap()
.is_none()
);

const ADDITIONS: &str = indoc::indoc! { "
r usr/bin/bash bash-v0
"};
Expand Down Expand Up @@ -835,6 +841,12 @@ r usr/bin/bash bash-v0
let _import = imp.import(prep).await.unwrap();
assert_eq!(store::list_images(fixture.destrepo()).unwrap().len(), 2);

assert!(
store::image_filtered_content_warning(fixture.destrepo(), &derived_imgref.imgref)
.unwrap()
.is_none()
);

// Should only be new layers
let n_removed = store::gc_image_layers(fixture.destrepo())?;
assert_eq!(n_removed, 0);
Expand All @@ -861,6 +873,58 @@ r usr/bin/bash bash-v0
Ok(())
}

#[tokio::test]
async fn test_container_var_content() -> Result<()> {
let fixture = Fixture::new_v1()?;

let imgref = fixture.export_container(ExportLayout::V1).await.unwrap().0;
let imgref = OstreeImageReference {
sigverify: SignatureSource::ContainerPolicyAllowInsecure,
imgref,
};

// Build a derived image
let derived_path = &fixture.path.join("derived.oci");
let srcpath = imgref.imgref.name.as_str();
oci_clone(srcpath, derived_path).await.unwrap();
let temproot = &fixture.path.join("temproot");
|| -> Result<_> {
std::fs::create_dir(temproot)?;
let temprootd = Dir::open_ambient_dir(temproot, cap_std::ambient_authority())?;
let mut db = DirBuilder::new();
db.mode(0o755);
db.recursive(true);
temprootd.create_dir_with("var/lib", &db)?;
temprootd.write("var/lib/foo", "junk var data")?;
Ok(())
}()
.context("generating temp content")?;
ostree_ext::integrationtest::generate_derived_oci(derived_path, temproot)?;

let derived_imgref = OstreeImageReference {
sigverify: SignatureSource::ContainerPolicyAllowInsecure,
imgref: ImageReference {
transport: Transport::OciDir,
name: derived_path.to_string(),
},
};
let mut imp =
store::ImageImporter::new(fixture.destrepo(), &derived_imgref, Default::default()).await?;
let prep = match imp.prepare().await.unwrap() {
store::PrepareResult::AlreadyPresent(_) => panic!("should not be already imported"),
store::PrepareResult::Ready(r) => r,
};
let _import = imp.import(prep).await.unwrap();

assert!(
store::image_filtered_content_warning(fixture.destrepo(), &derived_imgref.imgref)
.unwrap()
.is_some()
);

Ok(())
}

/// Copy an OCI directory.
async fn oci_clone(src: impl AsRef<Utf8Path>, dest: impl AsRef<Utf8Path>) -> Result<()> {
let src = src.as_ref();
Expand Down

0 comments on commit 550faa8

Please sign in to comment.