diff --git a/pkg/manifest/os.go b/pkg/manifest/os.go index 6f0f5a7247..8f058460ff 100644 --- a/pkg/manifest/os.go +++ b/pkg/manifest/os.go @@ -406,28 +406,13 @@ func (p *OS) serialize() osbuild.Pipeline { } if len(p.containerSpecs) > 0 { - images := osbuild.NewContainersInputForSources(p.containerSpecs) - localImages := osbuild.NewLocalContainersInputForSources(p.containerSpecs) - var storagePath string - if containerStore := p.OSCustomizations.ContainersStorage; containerStore != nil { storagePath = *containerStore - storageConf := "/etc/containers/storage.conf" - - containerStoreOpts := osbuild.NewContainerStorageOptions(storageConf, storagePath) - pipeline.AddStage(osbuild.NewContainersStorageConfStage(containerStoreOpts)) } - if len(images.References) > 0 { - manifests := osbuild.NewFilesInputForManifestLists(p.containerSpecs) - skopeo := osbuild.NewSkopeoStageWithContainersStorage(storagePath, images, manifests) - pipeline.AddStage(skopeo) - } - - if len(localImages.References) > 0 { - skopeo := osbuild.NewSkopeoStageWithContainersStorage(storagePath, localImages, nil) - pipeline.AddStage(skopeo) + for _, stage := range osbuild.GenContainerStorageStages(storagePath, p.containerSpecs) { + pipeline.AddStage(stage) } } diff --git a/pkg/osbuild/containers.go b/pkg/osbuild/containers.go new file mode 100644 index 0000000000..475b8ca140 --- /dev/null +++ b/pkg/osbuild/containers.go @@ -0,0 +1,29 @@ +package osbuild + +import ( + "github.com/osbuild/images/pkg/container" +) + +func GenContainerStorageStages(storagePath string, containerSpecs []container.Spec) (stages []*Stage) { + if storagePath != "" { + storageConf := "/etc/containers/storage.conf" + + containerStoreOpts := NewContainerStorageOptions(storageConf, storagePath) + stages = append(stages, NewContainersStorageConfStage(containerStoreOpts)) + } + + images := NewContainersInputForSources(containerSpecs) + localImages := NewLocalContainersInputForSources(containerSpecs) + + if len(images.References) > 0 { + manifests := NewFilesInputForManifestLists(containerSpecs) + stages = append(stages, NewSkopeoStageWithContainersStorage(storagePath, images, manifests)) + } + + if len(localImages.References) > 0 { + stages = append(stages, NewSkopeoStageWithContainersStorage(storagePath, localImages, nil)) + + } + + return stages +} diff --git a/pkg/osbuild/containers_test.go b/pkg/osbuild/containers_test.go new file mode 100644 index 0000000000..f6d9d85635 --- /dev/null +++ b/pkg/osbuild/containers_test.go @@ -0,0 +1,150 @@ +package osbuild_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/osbuild/images/pkg/container" + "github.com/osbuild/images/pkg/osbuild" +) + +func TestGenContainerStorageStagesTrivial(t *testing.T) { + storagePath := "" + var containerSpecs []container.Spec + stages := osbuild.GenContainerStorageStages(storagePath, containerSpecs) + assert.Equal(t, len(stages), 0) +} + +func TestGenContainerStorageStagesSkopeoOnly(t *testing.T) { + storagePath := "" + containerSpecs := []container.Spec{ + { + LocalName: "some-name", + ImageID: "sha256:1851d5f64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + }, + } + stages := osbuild.GenContainerStorageStages(storagePath, containerSpecs) + assert.Equal(t, len(stages), 1) + assert.Equal(t, stages[0].Type, "org.osbuild.skopeo") + assert.Equal(t, stages[0].Inputs.(osbuild.SkopeoStageInputs).Images.Type, "org.osbuild.containers") +} + +func TestGenContainerStorageStagesSkopeoMixed(t *testing.T) { + storagePath := "" + containerSpecs := []container.Spec{ + { + LocalName: "some-name", + ImageID: "sha256:1851d5f64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + }, + { + LocalName: "other-name", + ImageID: "sha256:aabbccf64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + LocalStorage: true, + }, + } + stages := osbuild.GenContainerStorageStages(storagePath, containerSpecs) + assert.Equal(t, len(stages), 2) + assert.Equal(t, stages[0].Type, "org.osbuild.skopeo") + assert.Equal(t, stages[0].Inputs.(osbuild.SkopeoStageInputs).Images.Type, "org.osbuild.containers") + assert.Equal(t, stages[1].Type, "org.osbuild.skopeo") + assert.Equal(t, stages[1].Inputs.(osbuild.SkopeoStageInputs).Images.Type, "org.osbuild.containers-storage") +} + +func TestGenContainerStorageStagesSkopeoWithStoragePath(t *testing.T) { + storagePath := "/some/storage/path" + containerSpecs := []container.Spec{ + { + LocalName: "some-name", + ImageID: "sha256:1851d5f64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + }, + { + LocalName: "other-name", + ImageID: "sha256:aabbccf64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + LocalStorage: true, + }, + } + stages := osbuild.GenContainerStorageStages(storagePath, containerSpecs) + assert.Equal(t, len(stages), 3) + assert.Equal(t, stages[0].Type, "org.osbuild.containers.storage.conf") + assert.Equal(t, stages[1].Type, "org.osbuild.skopeo") + assert.Equal(t, stages[1].Inputs.(osbuild.SkopeoStageInputs).Images.Type, "org.osbuild.containers") + assert.Equal(t, stages[2].Type, "org.osbuild.skopeo") + assert.Equal(t, stages[2].Inputs.(osbuild.SkopeoStageInputs).Images.Type, "org.osbuild.containers-storage") +} + +func TestGenContainerStorageStagesIntegration(t *testing.T) { + storagePath := "/some/storage/path.conf" + containerSpecs := []container.Spec{ + { + LocalName: "some-name", + ImageID: "sha256:1851d5f64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + }, + { + LocalName: "local-name", + ImageID: "sha256:aabbccf64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db", + LocalStorage: true, + }, + } + stages := osbuild.GenContainerStorageStages(storagePath, containerSpecs) + jsonOutput, err := json.MarshalIndent(stages, "", " ") + assert.NoError(t, err) + assert.Equal(t, string(jsonOutput), `[ + { + "type": "org.osbuild.containers.storage.conf", + "options": { + "filename": "/etc/containers/storage.conf", + "config": { + "storage": { + "options": { + "additionalimagestores": [ + "/some/storage/path.conf" + ] + } + } + } + } + }, + { + "type": "org.osbuild.skopeo", + "inputs": { + "images": { + "type": "org.osbuild.containers", + "origin": "org.osbuild.source", + "references": { + "sha256:1851d5f64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db": { + "name": "some-name" + } + } + } + }, + "options": { + "destination": { + "type": "containers-storage", + "storage-path": "/some/storage/path.conf" + } + } + }, + { + "type": "org.osbuild.skopeo", + "inputs": { + "images": { + "type": "org.osbuild.containers-storage", + "origin": "org.osbuild.source", + "references": { + "sha256:aabbccf64ebaeac67c5c2d9e4adc1e73aa6433b44a167268a3510c3d056062db": { + "name": "local-name" + } + } + } + }, + "options": { + "destination": { + "type": "containers-storage", + "storage-path": "/some/storage/path.conf" + } + } + } +]`) +}