Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor image pulling to use goroutines for concurrency #1868

Merged
merged 25 commits into from
Sep 21, 2023
Merged
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 49 additions & 20 deletions src/internal/packager/sbom/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,59 @@ func Catalog(componentSBOMs map[string]*types.ComponentSBOM, imgList []string, t
}
builder.jsonList = json

// Generate SBOM for each image
currImage := 1
for _, tag := range imgList {
builder.spinner.Updatef("Creating image SBOMs (%d of %d): %s", currImage, imageCount, tag)
// Generate SBOM for all images at once using goroutines

// Get the image that we are creating an SBOM for
img, err := utils.LoadOCIImage(tmpPaths.Images, tag)
if err != nil {
builder.spinner.Errorf(err, "Unable to load the image to generate an SBOM")
return err
}
// Create channel for letting us know when an image's SBOM is done
imageProgress := make(chan string, len(imgList))

jsonData, err := builder.createImageSBOM(img, tag)
if err != nil {
builder.spinner.Errorf(err, "Unable to create SBOM for image %s", tag)
return err
}
type errorWithMessage struct {
err error
message string
}
corang marked this conversation as resolved.
Show resolved Hide resolved

if err = builder.createSBOMViewerAsset(tag, jsonData); err != nil {
builder.spinner.Errorf(err, "Unable to create SBOM viewer for image %s", tag)
return err
}
// Create channel for letting us know when there was an error generating an SBOM
imageError := make(chan errorWithMessage, len(imgList))

currImage++
// Call a goroutine for each image
for _, tag := range imgList {
currentTag := tag
go func() {
// Get the image that we are creating an SBOM for
img, err := utils.LoadOCIImage(tmpPaths.Images, currentTag)
if err != nil {
imageError <- errorWithMessage{err, "Unable to load the image to generate an SBOM"}
return
}

// Generate the SBOM JSON for the given image
jsonData, err := builder.createImageSBOM(img, currentTag)
if err != nil {
imageError <- errorWithMessage{err, fmt.Sprintf("Unable to create SBOM for image %s", currentTag)}
return
}

// Create the SBOM viewer HTML for the given image
if err = builder.createSBOMViewerAsset(currentTag, jsonData); err != nil {
imageError <- errorWithMessage{err, fmt.Sprintf("Unable to create SBOM viewer for image %s", currentTag)}
return
}
// Call the imageProgress channel to let us know that the SBOM generation is done for this image
imageProgress <- currentTag
}()
}

// Wait for all images to be done generating SBOMs
for i := 0; i < len(imgList); i++ {
select {
// If there was an error generating an SBOM, write the error to the spinner
case err := <-imageError:
builder.spinner.Errorf(err.err, err.message)
return err.err
// If there is a string in the imageProgress channel we know that an SBOM
// was generated for an image and we can update the spinner
case tag := <-imageProgress:
builder.spinner.Updatef("Creating image SBOMs (%d of %d): %s", i, len(imgList), tag)
}
corang marked this conversation as resolved.
Show resolved Hide resolved
}

currComponent := 1
Expand Down