-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
[POC] Provisioner for SBOM #13171
base: main
Are you sure you want to change the base?
[POC] Provisioner for SBOM #13171
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a bunch of comments on the code, I think we can simplify the download to have it done once only, technically once we've copied the file locally for Packer, we can copy it to the user-specified destination (if specified). That or we can factorise the code for downloading since it's very similar.
I'll let you address those comments and do another pass of review after that.
packer/provisioner.go
Outdated
// press before the provisioner is actually run. | ||
type SBOMInternalProvisioner struct { | ||
Provisioner packersdk.Provisioner | ||
TempFileLoc string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why we keep this as part of the provisioner? Since we only create the file during Prepare
and wipe it by the end, it doesn't seem that we need it here
packer/provisioner.go
Outdated
if err != nil { | ||
return fmt.Errorf("failed to create internal temporary file for Packer SBOM: %s", err) | ||
} | ||
defer tmpFile.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the underlying provisioner writes to this file, we should not defer its closure I'd think, typically on Windows this might fail depending on the kind of Handle we've received from CreateTemp
packer/provisioner.go
Outdated
if fileRemoveErr != nil { | ||
log.Printf("Error removing SBOM temporary file %s: %s", name, fileRemoveErr) | ||
} | ||
}(p.TempFileLoc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point p.TempFileLoc
was not set, so this won't work I'd think, since the parameter will be empty when the function executes?
packer/provisioner.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
defer sourceFile.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a function like os.ReadFile
here instead of manually opening/reading/closing it.
packer/provisioner.go
Outdated
|
||
compressedData := encoder.EncodeAll(data, nil) | ||
|
||
fmt.Printf(fmt.Sprintf("SBOM file compressed successfully. Size: %d bytes", len(compressedData))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should become a log.Printf
, if not removed completely imho
packer/build.go
Outdated
if !ok { | ||
continue | ||
} | ||
b.SBOMFilesCompressed = append(b.SBOMFilesCompressed, sbomInternalProvisioner.CompressedData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the alternative has only one instruction, you can probably invert this logic here
if !ok { | |
continue | |
} | |
b.SBOMFilesCompressed = append(b.SBOMFilesCompressed, sbomInternalProvisioner.CompressedData) | |
if ok { | |
b.SBOMFilesCompressed = append(b.SBOMFilesCompressed, sbomInternalProvisioner.CompressedData) | |
} |
provisioner/hcp_sbom/provisioner.go
Outdated
return | ||
} | ||
|
||
if info.IsDir() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't that fail if the directory doesn't exist? Since we create the hierarchy below if not existing, we should assume that the directory doesn't already exists before attempting to create it, so failing here feels off.
provisioner/hcp_sbom/provisioner.go
Outdated
|
||
// downloadSBOMForUser downloads a SBOM from a specified source to a local | ||
// destination given by user. It works with all communicators from packersdk. | ||
func (p *Provisioner) downloadSBOMForUser( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is suspiciously similar to the downloadSBOMForPacker
function's code, we might be able to factorise the implementation I'd think, if only to avoid unnecessary repetition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ping on this one @devashish-patel, we talked about this out-of-band, just want to kickstart a conversation on this line of work
provisioner/hcp_sbom/provisioner.go
Outdated
} | ||
|
||
// Download the file for user | ||
p.downloadSBOMForUser(ui, comm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should report errors here, the function should return an error if something went wrong, as the user requests the SBOM be kept somewhere else, if it fails for some reason, so should the provisioner
provisioner/hcp_sbom/provisioner.go
Outdated
return | ||
} | ||
|
||
if strings.HasSuffix(dst, "/") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This heuristic seems brittle, the output can be a directory even if the path doesn't end with /
, we should rely on os.Stat
regardless to know if this is a directory, irrespective of what the path looks like
Example templates:
JSON:
HCL: