Skip to content

Commit

Permalink
bib: add support for file/directory customizations
Browse files Browse the repository at this point in the history
This commit adds support for files/directories in blueprint
customizations.

This needs osbuild/images#1227

Closes: osbuild#834
  • Loading branch information
mvo5 committed Feb 26, 2025
1 parent e0d517b commit e2da1b3
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 16 deletions.
22 changes: 22 additions & 0 deletions bib/cmd/bootc-image-builder/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/pathpolicy"
"github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/policies"
"github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/images/pkg/runner"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -380,6 +381,27 @@ func manifestForDiskImage(c *ManifestConfig, rng *rand.Rand) (*manifest.Manifest
}
img.PartitionTable = pt

// Check Directory/File Customizations are valid
dc := customizations.GetDirectories()
fc := customizations.GetFiles()
if err := blueprint.ValidateDirFileCustomizations(dc, fc); err != nil {
return nil, err
}
if err := blueprint.CheckDirectoryCustomizationsPolicy(dc, policies.OstreeCustomDirectoriesPolicies); err != nil {
return nil, err
}
if err := blueprint.CheckFileCustomizationsPolicy(fc, policies.OstreeCustomFilesPolicies); err != nil {
return nil, err
}
img.Files, err = blueprint.FileCustomizationsToFsNodeFiles(fc)
if err != nil {
return nil, err
}
img.Directories, err = blueprint.DirectoryCustomizationsToFsNodeDirectories(dc)
if err != nil {
return nil, err
}

// For the bootc-disk image, the filename is the basename and the extension
// is added automatically for each disk format
img.Filename = "disk"
Expand Down
36 changes: 36 additions & 0 deletions bib/cmd/bootc-image-builder/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/osbuild/images/pkg/runner"

bib "github.com/osbuild/bootc-image-builder/bib/cmd/bootc-image-builder"
"github.com/osbuild/bootc-image-builder/bib/internal/buildconfig"
"github.com/osbuild/bootc-image-builder/bib/internal/source"
)

Expand Down Expand Up @@ -680,3 +681,38 @@ func TestGenPartitionTableDiskCustomizationSizes(t *testing.T) {
})
}
}

func TestManifestFilecustomizationsSad(t *testing.T) {
config := getBaseConfig()
config.ImageTypes = []string{"qcow2"}
config.Config = &buildconfig.BuildConfig{
Customizations: &blueprint.Customizations{
Files: []blueprint.FileCustomization{
{
Path: "/not/allowed",
Data: "some-data",
},
},
},
}

_, err := bib.Manifest(config)
assert.EqualError(t, err, `the following custom files are not allowed: ["/not/allowed"]`)
}

func TestManifestDirCustomizationsSad(t *testing.T) {
config := getBaseConfig()
config.ImageTypes = []string{"qcow2"}
config.Config = &buildconfig.BuildConfig{
Customizations: &blueprint.Customizations{
Directories: []blueprint.DirectoryCustomization{
{
Path: "/dir/not/allowed",
},
},
},
}

_, err := bib.Manifest(config)
assert.EqualError(t, err, `the following custom directories are not allowed: ["/dir/not/allowed"]`)
}
34 changes: 18 additions & 16 deletions bib/cmd/bootc-image-builder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,23 @@ func TestManifestGenerationUserConfig(t *testing.T) {
}
}

// Disk images require a container for the build/image pipelines
var containerSpec = container.Spec{
Source: "test-container",
Digest: "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
ImageID: "sha256:1111111111111111111111111111111111111111111111111111111111111111",
}

// diskContainers can be passed to Serialize() to get a minimal disk image
var diskContainers = map[string][]container.Spec{
"build": {
containerSpec,
},
"image": {
containerSpec,
},
}

// TODO: this tests at this layer is not ideal, it has too much knowledge
// over the implementation details of the "images" library and how an
// image.NewBootcDiskImage() works (i.e. what the pipeline names are and
Expand All @@ -208,23 +225,8 @@ func TestManifestSerialization(t *testing.T) {
// Tests that the manifest is generated without error and is serialized
// with expected key stages.

// Disk images require a container for the build/image pipelines
containerSpec := container.Spec{
Source: "test-container",
Digest: "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
ImageID: "sha256:1111111111111111111111111111111111111111111111111111111111111111",
}
diskContainers := map[string][]container.Spec{
"build": {
containerSpec,
},
"image": {
containerSpec,
},
}

// ISOs require a container for the bootiso-tree, build packages, and packages for the anaconda-tree (with a kernel).
isoContainers := map[string][]container.Spec{
var isoContainers = map[string][]container.Spec{
"bootiso-tree": {
containerSpec,
},
Expand Down
40 changes: 40 additions & 0 deletions test/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,43 @@ def test_iso_manifest_use_librepo(build_container, use_librepo):
assert "org.osbuild.librepo" in manifest["sources"]
else:
assert "org.osbuild.curl" in manifest["sources"]


def test_manifest_customization_custom_file_smoke(tmp_path, build_container):
# no need to parameterize this test, toml is the same for all containers
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

cfg = {
"blueprint": {
"customizations": {
"files": [
{
"path": "/etc/custom_file",
"data": "hello world"
},
],
"directories": [
{
"path": "/etc/custom_dir",
},
],
},
},
}

output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)
config_json_path = output_path / "config.json"
config_json_path.write_text(json.dumps(cfg), encoding="utf-8")

output = subprocess.check_output([
*testutil.podman_run_common,
"-v", f"{output_path}:/output",
build_container,
"manifest", f"{container_ref}",
"--config", "/output/config.json",
], stderr=subprocess.PIPE, encoding="utf8")
json.loads(output)
assert '"to":"tree:///etc/custom_file"' in output
assert '{"type":"org.osbuild.mkdir","options":{"paths":[{"path":"/etc/custom_dir","exist_ok":true}]}}' in output

0 comments on commit e2da1b3

Please sign in to comment.