Skip to content

Commit e5f7e4b

Browse files
Launcher sboms copy only sbom extensions (#984)
* fsutils FilesWithExtensions filters directory listings Signed-off-by: Joe Kimmel <jkimmel@vmware.com> * exporter: launcher sbom copy only copies sbom files Signed-off-by: Joe Kimmel <jkimmel@vmware.com> * exporter launcher sbom copy: more thorough test Signed-off-by: Joe Kimmel <jkimmel@vmware.com> Signed-off-by: Joe Kimmel <jkimmel@vmware.com>
1 parent ec4e8d3 commit e5f7e4b

9 files changed

Lines changed: 63 additions & 4 deletions

File tree

exporter.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,33 @@ func (e *Exporter) copyBuildpacksioSBOMs(opts ExportOptions) error {
181181
opts.LauncherConfig.SBOMDir == platform.DefaultBuildpacksioSBOMDir:
182182
return e.copyDefaultSBOMsForComponent("launcher", targetLaunchDir)
183183
default:
184-
// if provided a custom launcher SBOM directory, just copy everything in the directory
185-
return fsutil.Copy(opts.LauncherConfig.SBOMDir, targetLaunchDir)
184+
// if provided a custom launcher SBOM directory, copy all files that look like sboms in that directory
185+
return e.copyLauncherSBOMs(opts.LauncherConfig.SBOMDir, targetLaunchDir)
186186
}
187187
}
188188

189+
func (e *Exporter) copyLauncherSBOMs(srcDir string, dstDir string) error {
190+
sboms, err := fsutil.FilesWithExtensions(srcDir, SBOMExtensions())
191+
if err != nil {
192+
e.Logger.Warnf("Failed to list contents of directory %s", srcDir)
193+
return err
194+
}
195+
196+
if err := os.MkdirAll(dstDir, 0755); err != nil {
197+
return err
198+
}
199+
200+
for _, sbom := range sboms {
201+
dstPath := filepath.Join(dstDir, filepath.Base(sbom))
202+
err = fsutil.Copy(sbom, dstPath)
203+
if err != nil {
204+
e.Logger.Warnf("failed while copying SBOM from %s to %s", sbom, dstPath)
205+
return err
206+
}
207+
}
208+
return nil
209+
}
210+
189211
func (e *Exporter) copyDefaultSBOMsForComponent(component, dstDir string) error {
190212
for _, extension := range SBOMExtensions() {
191213
srcFilename := fmt.Sprintf("%s.%s", component, extension)

exporter_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,14 +1504,17 @@ version = "4.5.6"
15041504
when("custom launcher SBOM is provided", func() {
15051505
it.Before(func() {
15061506
h.RecursiveCopy(t, filepath.Join("testdata", "exporter", "launcher-sbom", "layers"), opts.LayersDir)
1507+
// later we'll assert that this file doesn't get copied, but that's only meaningful if it exists at the source
1508+
h.AssertPathExists(t, filepath.Join(opts.LayersDir, "some-launcher-sbom-dir", "a-regular-file.txt"))
15071509
opts.LauncherConfig.SBOMDir = filepath.Join(opts.LayersDir, "some-launcher-sbom-dir")
15081510
})
15091511

1510-
it("copies everything in the launcher SBOM directory", func() {
1512+
it("copies sboms from the launcher SBOM directory", func() {
15111513
_, err := exporter.Export(opts)
15121514
h.AssertNil(t, err)
15131515

1514-
h.AssertPathExists(t, filepath.Join(opts.LayersDir, "sbom", "launch", "buildpacksio_lifecycle", "launcher", "some-sbom-file"))
1516+
h.AssertPathExists(t, filepath.Join(opts.LayersDir, "sbom", "launch", "buildpacksio_lifecycle", "launcher", "some-sbom-file.sbom.spdx.json"))
1517+
h.AssertPathDoesNotExist(t, filepath.Join(opts.LayersDir, "sbom", "launch", "buildpacksio_lifecycle", "launcher", "a-regular-file.txt"))
15151518
})
15161519
})
15171520
})

testdata/exporter/launcher-sbom/layers/some-launcher-sbom-dir/some-sbom-file renamed to internal/fsutil/testdata/file2.txt

File renamed without changes.

internal/fsutil/testdata/file3.json

Whitespace-only changes.

internal/fsutil/testdata/unwanted_file.xml

Whitespace-only changes.

internal/fsutil/utils.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66
"path/filepath"
77
"runtime"
8+
"strings"
89
)
910

1011
func Copy(src, dst string) error {
@@ -52,6 +53,26 @@ func copyDir(src, dst string) error {
5253
return nil
5354
}
5455

56+
// FilesWithExtensions returns a list of all files in directory that end in any of the extensions provided.
57+
// top level only - does not recursively visit directories.
58+
func FilesWithExtensions(dir string, extensions []string) ([]string, error) {
59+
files, err := os.ReadDir(dir)
60+
if err != nil {
61+
return nil, err
62+
}
63+
matches := []string{}
64+
for _, f := range files {
65+
if !f.IsDir() {
66+
for _, extension := range extensions {
67+
if strings.HasSuffix(f.Name(), extension) {
68+
matches = append(matches, filepath.Join(dir, f.Name()))
69+
}
70+
}
71+
}
72+
}
73+
return matches, nil
74+
}
75+
5576
func copyFile(src, dst string) error {
5677
in, err := os.Open(src)
5778
if err != nil {

internal/fsutil/utils_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,17 @@ func testIO(t *testing.T, when spec.G, it spec.S) {
7979
})
8080
})
8181
})
82+
83+
when("#FilesWithExtensions", func() {
84+
when("called with directory and extensions", func() {
85+
it("filters the files", func() {
86+
src := "testdata"
87+
exts := []string{".txt", ".json"}
88+
files, err := fsutil.FilesWithExtensions(src, exts)
89+
h.AssertNil(t, err)
90+
h.AssertEq(t, len(files), 2)
91+
h.AssertContains(t, files, filepath.Join(src, "file2.txt"), filepath.Join(src, "file3.json"))
92+
})
93+
})
94+
})
8295
}

testdata/exporter/launcher-sbom/layers/some-launcher-sbom-dir/a-regular-file.txt

Whitespace-only changes.

testdata/exporter/launcher-sbom/layers/some-launcher-sbom-dir/some-sbom-file.sbom.spdx.json

Whitespace-only changes.

0 commit comments

Comments
 (0)