diff --git a/examples/execd/src/layer.rs b/examples/execd/src/layer.rs deleted file mode 100644 index fbf4a124..00000000 --- a/examples/execd/src/layer.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::ExecDBuildpack; -use libcnb::build::BuildContext; -use libcnb::data::layer_content_metadata::LayerTypes; -use libcnb::generic::GenericMetadata; -use libcnb::layer::{Layer, LayerResult, LayerResultBuilder}; -use libcnb::{additional_buildpack_binary_path, Buildpack}; -use std::path::Path; - -pub(crate) struct ExecDLayer; - -impl Layer for ExecDLayer { - type Buildpack = ExecDBuildpack; - type Metadata = GenericMetadata; - - fn types(&self) -> LayerTypes { - LayerTypes { - launch: true, - build: false, - cache: false, - } - } - - fn create( - &mut self, - _context: &BuildContext, - _layer_path: &Path, - ) -> Result, ::Error> { - LayerResultBuilder::new(GenericMetadata::default()) - .exec_d_program( - "dice_roller", - additional_buildpack_binary_path!("dice_roller"), - ) - .build() - } -} diff --git a/examples/execd/src/main.rs b/examples/execd/src/main.rs index 84c2fc42..9686943c 100644 --- a/examples/execd/src/main.rs +++ b/examples/execd/src/main.rs @@ -1,18 +1,12 @@ -// This example uses the older trait Layer API. The example will be updated to the newer API -// before the next libcnb.rs release. -#![allow(deprecated)] - -mod layer; - -use crate::layer::ExecDLayer; use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder}; use libcnb::data::layer_name; use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; use libcnb::generic::{GenericError, GenericMetadata, GenericPlatform}; -use libcnb::{buildpack_main, Buildpack}; +use libcnb::{additional_buildpack_binary_path, buildpack_main, Buildpack}; // Suppress warnings due to the `unused_crate_dependencies` lint not handling integration tests well. use fastrand as _; +use libcnb::layer::UncachedLayerDefinition; #[cfg(test)] use libcnb_test as _; @@ -28,7 +22,19 @@ impl Buildpack for ExecDBuildpack { } fn build(&self, context: BuildContext) -> libcnb::Result { - context.handle_layer(layer_name!("layer_name"), ExecDLayer)?; + let layer_ref = context.uncached_layer( + layer_name!("layer_name"), + UncachedLayerDefinition { + build: false, + launch: true, + }, + )?; + + layer_ref.write_exec_d_programs([( + "dice_roller", + additional_buildpack_binary_path!("dice_roller"), + )])?; + BuildResultBuilder::new().build() } } diff --git a/test-buildpacks/readonly-layer-files/src/layer.rs b/test-buildpacks/readonly-layer-files/src/layer.rs deleted file mode 100644 index 2f1e3402..00000000 --- a/test-buildpacks/readonly-layer-files/src/layer.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::TestBuildpack; -use libcnb::build::BuildContext; -use libcnb::data::layer_content_metadata::LayerTypes; -use libcnb::generic::GenericMetadata; -use libcnb::layer::{ExistingLayerStrategy, Layer, LayerData, LayerResult, LayerResultBuilder}; -use libcnb::Buildpack; -use std::fs; -use std::fs::Permissions; -use std::os::unix::fs::PermissionsExt; -use std::path::Path; - -pub(crate) struct TestLayer; - -impl Layer for TestLayer { - type Buildpack = TestBuildpack; - type Metadata = GenericMetadata; - - fn types(&self) -> LayerTypes { - LayerTypes { - launch: true, - build: true, - cache: true, - } - } - - fn create( - &mut self, - _context: &BuildContext, - layer_path: &Path, - ) -> Result, ::Error> { - let directory = layer_path.join("sub_directory"); - fs::create_dir_all(&directory).expect("Couldn't create subdirectory"); - - fs::write(directory.join("foo.txt"), "hello world!").expect("Couldn't write file"); - - // By making the sub-directory read-only, files inside it cannot be deleted. This would - // cause issues when libcnb.rs tries to delete a cached layer directory unless libcnb.rs - // handles this case explicitly. - fs::set_permissions(&directory, Permissions::from_mode(0o555)) - .expect("Couldn't set permissions to read-only"); - - LayerResultBuilder::new(GenericMetadata::default()).build() - } - - fn existing_layer_strategy( - &mut self, - _context: &BuildContext, - _layer_data: &LayerData, - ) -> Result::Error> { - // Even though this is (currently) the default, we explicitly declare it here to make sure - // the layer will be recreated, even if the default in libcnb changes. - Ok(ExistingLayerStrategy::Recreate) - } -} diff --git a/test-buildpacks/readonly-layer-files/src/main.rs b/test-buildpacks/readonly-layer-files/src/main.rs index 96b264fa..1d4d3f93 100644 --- a/test-buildpacks/readonly-layer-files/src/main.rs +++ b/test-buildpacks/readonly-layer-files/src/main.rs @@ -1,15 +1,12 @@ -// This test buildpack uses the older trait Layer API. It will be updated to the newer API -// before the next libcnb.rs release. -#![allow(deprecated)] - -mod layer; - -use crate::layer::TestLayer; use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder}; use libcnb::data::layer_name; use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; use libcnb::generic::{GenericMetadata, GenericPlatform}; +use libcnb::layer::{CachedLayerDefinition, InvalidMetadataAction, RestoredLayerAction}; use libcnb::{buildpack_main, Buildpack}; +use std::fs; +use std::fs::Permissions; +use std::os::unix::fs::PermissionsExt; // Suppress warnings due to the `unused_crate_dependencies` lint not handling integration tests well. #[cfg(test)] @@ -27,7 +24,27 @@ impl Buildpack for TestBuildpack { } fn build(&self, context: BuildContext) -> libcnb::Result { - context.handle_layer(layer_name!("test"), TestLayer)?; + let layer_ref = context.cached_layer( + layer_name!("test"), + CachedLayerDefinition { + build: true, + launch: true, + invalid_metadata_action: &|_| InvalidMetadataAction::DeleteLayer, + restored_layer_action: &|_: &GenericMetadata, _| RestoredLayerAction::DeleteLayer, + }, + )?; + + let directory = layer_ref.path().join("sub_directory"); + fs::create_dir_all(&directory).expect("Couldn't create subdirectory"); + + fs::write(directory.join("foo.txt"), "hello world!").expect("Couldn't write file"); + + // By making the sub-directory read-only, files inside it cannot be deleted. This would + // cause issues when libcnb.rs tries to delete a cached layer directory unless libcnb.rs + // handles this case explicitly. + fs::set_permissions(&directory, Permissions::from_mode(0o555)) + .expect("Couldn't set permissions to read-only"); + BuildResultBuilder::new().build() } } diff --git a/test-buildpacks/sbom/src/main.rs b/test-buildpacks/sbom/src/main.rs index f8543cf7..49f8a1ce 100644 --- a/test-buildpacks/sbom/src/main.rs +++ b/test-buildpacks/sbom/src/main.rs @@ -1,17 +1,11 @@ -// This test buildpack uses the older trait Layer API. It will be updated to the newer API -// before the next libcnb.rs release. -#![allow(deprecated)] - -mod test_layer; -mod test_layer_2; - -use crate::test_layer::TestLayer; -use crate::test_layer_2::TestLayer2; use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder}; use libcnb::data::layer_name; use libcnb::data::sbom::SbomFormat; use libcnb::detect::{DetectContext, DetectResult, DetectResultBuilder}; use libcnb::generic::{GenericMetadata, GenericPlatform}; +use libcnb::layer::{ + CachedLayerDefinition, InvalidMetadataAction, LayerState, RestoredLayerAction, +}; use libcnb::sbom::Sbom; use libcnb::{buildpack_main, Buildpack}; @@ -31,8 +25,64 @@ impl Buildpack for TestBuildpack { } fn build(&self, context: BuildContext) -> libcnb::Result { - context.handle_layer(layer_name!("test"), TestLayer)?; - context.handle_layer(layer_name!("test2"), TestLayer2)?; + let first_layer_ref = context.cached_layer( + layer_name!("test"), + CachedLayerDefinition { + build: true, + launch: true, + invalid_metadata_action: &|_| InvalidMetadataAction::DeleteLayer, + restored_layer_action: &|_: &GenericMetadata, _| RestoredLayerAction::KeepLayer, + }, + )?; + + match first_layer_ref.state { + LayerState::Restored { .. } => { + first_layer_ref.write_sboms(&[])?; + } + LayerState::Empty { .. } => { + first_layer_ref.write_sboms(&[ + Sbom::from_bytes( + SbomFormat::CycloneDxJson, + *include_bytes!("../etc/cyclonedx_3.sbom.json"), + ), + Sbom::from_bytes( + SbomFormat::SpdxJson, + *include_bytes!("../etc/spdx_3.sbom.json"), + ), + Sbom::from_bytes( + SbomFormat::SyftJson, + *include_bytes!("../etc/syft_3.sbom.json"), + ), + ])?; + } + } + + let second_layer_ref = context.cached_layer( + layer_name!("test2"), + CachedLayerDefinition { + build: true, + launch: true, + invalid_metadata_action: &|_| InvalidMetadataAction::DeleteLayer, + restored_layer_action: &|_: &GenericMetadata, _| RestoredLayerAction::KeepLayer, + }, + )?; + + if let LayerState::Empty { .. } = second_layer_ref.state { + second_layer_ref.write_sboms(&[ + Sbom::from_bytes( + SbomFormat::CycloneDxJson, + *include_bytes!("../etc/cyclonedx_2.sbom.json"), + ), + Sbom::from_bytes( + SbomFormat::SpdxJson, + *include_bytes!("../etc/spdx_2.sbom.json"), + ), + Sbom::from_bytes( + SbomFormat::SyftJson, + *include_bytes!("../etc/syft_2.sbom.json"), + ), + ])?; + } BuildResultBuilder::new() .launch_sbom(Sbom::from_bytes( diff --git a/test-buildpacks/sbom/src/test_layer.rs b/test-buildpacks/sbom/src/test_layer.rs deleted file mode 100644 index ce4154cb..00000000 --- a/test-buildpacks/sbom/src/test_layer.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::{SbomFormat, TestBuildpack}; -use libcnb::build::BuildContext; -use libcnb::data::layer_content_metadata::LayerTypes; -use libcnb::generic::GenericMetadata; -use libcnb::layer::{ExistingLayerStrategy, Layer, LayerData, LayerResult, LayerResultBuilder}; -use libcnb::sbom::Sbom; -use libcnb::Buildpack; -use std::path::Path; - -pub(crate) struct TestLayer; - -impl Layer for TestLayer { - type Buildpack = TestBuildpack; - type Metadata = GenericMetadata; - - fn types(&self) -> LayerTypes { - LayerTypes { - launch: true, - build: true, - cache: true, - } - } - - fn create( - &mut self, - _context: &BuildContext, - _layer_path: &Path, - ) -> Result, ::Error> { - LayerResultBuilder::new(GenericMetadata::default()) - .sbom(Sbom::from_bytes( - SbomFormat::CycloneDxJson, - *include_bytes!("../etc/cyclonedx_3.sbom.json"), - )) - .sbom(Sbom::from_bytes( - SbomFormat::SpdxJson, - *include_bytes!("../etc/spdx_3.sbom.json"), - )) - .sbom(Sbom::from_bytes( - SbomFormat::SyftJson, - *include_bytes!("../etc/syft_3.sbom.json"), - )) - .build() - } - - fn existing_layer_strategy( - &mut self, - _context: &BuildContext, - _layer_data: &LayerData, - ) -> Result::Error> { - Ok(ExistingLayerStrategy::Update) - } - - fn update( - &mut self, - _context: &BuildContext, - _layer_data: &LayerData, - ) -> Result, ::Error> { - LayerResultBuilder::new(GenericMetadata::default()).build() - } -} diff --git a/test-buildpacks/sbom/src/test_layer_2.rs b/test-buildpacks/sbom/src/test_layer_2.rs deleted file mode 100644 index bf244321..00000000 --- a/test-buildpacks/sbom/src/test_layer_2.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::{SbomFormat, TestBuildpack}; -use libcnb::build::BuildContext; -use libcnb::data::layer_content_metadata::LayerTypes; -use libcnb::generic::GenericMetadata; -use libcnb::layer::{ExistingLayerStrategy, Layer, LayerData, LayerResult, LayerResultBuilder}; -use libcnb::sbom::Sbom; -use libcnb::Buildpack; -use std::path::Path; - -pub(crate) struct TestLayer2; - -impl Layer for TestLayer2 { - type Buildpack = TestBuildpack; - type Metadata = GenericMetadata; - - fn types(&self) -> LayerTypes { - LayerTypes { - launch: true, - build: true, - cache: true, - } - } - - fn create( - &mut self, - _context: &BuildContext, - _layer_path: &Path, - ) -> Result, ::Error> { - LayerResultBuilder::new(GenericMetadata::default()) - .sbom(Sbom::from_bytes( - SbomFormat::CycloneDxJson, - *include_bytes!("../etc/cyclonedx_2.sbom.json"), - )) - .sbom(Sbom::from_bytes( - SbomFormat::SpdxJson, - *include_bytes!("../etc/spdx_2.sbom.json"), - )) - .sbom(Sbom::from_bytes( - SbomFormat::SyftJson, - *include_bytes!("../etc/syft_2.sbom.json"), - )) - .build() - } - - fn existing_layer_strategy( - &mut self, - _context: &BuildContext, - _layer_data: &LayerData, - ) -> Result::Error> { - Ok(ExistingLayerStrategy::Keep) - } -} diff --git a/test-buildpacks/sbom/tests/integration_test.rs b/test-buildpacks/sbom/tests/integration_test.rs index df5f35b9..1e28d364 100644 --- a/test-buildpacks/sbom/tests/integration_test.rs +++ b/test-buildpacks/sbom/tests/integration_test.rs @@ -113,8 +113,7 @@ fn test() { context.rebuild(&build_config, |context| { context.download_sbom_files(|sbom_files| { - // The 'test' layer does not return any SBOM files in its update implementation. This - // must result in no SBOM files being used from previous build. + // The buildpack removes restored SBOMs from the 'test' layer. assert!(!sbom_files .path_for( &buildpack_id,