-
Notifications
You must be signed in to change notification settings - Fork 27
[sha512] storage: Get/Set digest #374
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
Conversation
✅ A new PR has been created in buildah to vendor these changes: containers/buildah#6411 |
No other changes to storage for now. This will get used in other repos that depend on storage. |
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.
What is the precise semantics of the “current” value? “digests to use when creating new things”? “the expected level of collision-resistance when pulling”? “digests to convert to when pushing”?
@mtrmac This. Let me know if I need to account for anything additionally here itself, unless it can wait for future work. |
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.
- Per the Podman PR, “digest to use when creating new objects” is conceptually more of a per-operation parameter. It’s not at all clear to me that we should have a c/storage-scoped per-process global for this. (E.g. perhaps we do need a global default for this, set in
containers.conf
orstorage.conf
, but the decision which algorithm to use might plausibly be best placed into the Podman CLI layer, and be passed as an explicit parameter. Also consider podman-remote, client-side vs. server-side configs) - Although not as pedantic about it as c/image, c/storage is generally promising to have a stable API. In that sense,
supporteddigests.Get
is not quite an explanatory name for ”digests to use when creating new things”, and I’d like the long-term-committed name to be more specific (and less confusing, “supported digests” vs. “digests for new things”)
Ultimately, I appreciate that we need to start somewhere, and that building a digest parameter passing infrastructure all over the codebase before we understand the semantics really well would be a lot of tedious work with uncertain payoff.
WDYT about:
- very explicitly documenting that these functions are a WIP API and should not be called outside of Podman+friends, even if they ship in a stable release
- (absolutely optional) perhaps, even, naming them
TemporaryGet
/TemporarySet
, or, I don’t know,TemporaryDigestForNewObjects
/TemporarySetDigestForNewObjects
?
?
The implementation LGTM other than concurrency.
94df9c1
to
58c51d2
Compare
58c51d2
to
79f1c23
Compare
PTAL. |
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.
Thanks!
With the explicit non-promise of API stability, I’m much less worried about getting this perfect.
Some of the new parts seem unnecessary and not a clear improvement compared to using go-digest
directly. Let me know if you want this merge as is anyway.
[Man the AI is verbose…]
// calls from multiple goroutines. It is typically used for validation before | ||
// calling TmpSetDigestForNewObjects(). |
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.
I don’t know why anything would (“typically”) call this prior to …TmpSetDigest…
, it can just call the setter and handle an error.
|
||
// Check against the list of supported algorithms | ||
supportedAlgorithms := GetSupportedDigestAlgorithms() | ||
for _, supported := range supportedAlgorithms { |
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.
(slices.Contains
)
// This is a pure function with no side effects and is thread-safe for concurrent | ||
// calls from multiple goroutines. It is typically used for logging and user-facing | ||
// display purposes. | ||
func GetDigestAlgorithmName(algorithm digest.Algorithm) 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.
Why does this need to exist, distinctly from algorithm.String()
? Also see below about the “canonical” code path.
Having a go-digest
format that uses lowercase, and this function that uses uppercase, seems potentially confusing. I mean, if we do need to have two distinct string types, then making the two string sets distinct / incompatible is better than making strings ambiguous, but, still…
(I can, sort of, see a case for a logging/debugging utility that formats values specifically for error texts, maybe highlighting unsupported algorithms with an extra text. But I think "%q", algo.String()
is good enough and adding an extra utility is not clearly necessary.)
case "sha512": | ||
return "SHA512" | ||
default: | ||
if algorithm == digest.Canonical { |
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 digest.Canonical == digest.SHA256
, AFAICS this is never reachable; so if the primary purpose of this function is this code path, that doesn’t work.
// This is a pure function with no side effects and is thread-safe for concurrent | ||
// calls from multiple goroutines. It is typically used for validation and algorithm | ||
// detection from hex string lengths. | ||
func GetDigestAlgorithmExpectedLength(algorithm digest.Algorithm) (int, bool) { |
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.
Algorithm.Size()
exists — do we need to hard-code a table, or even have this at all?
{"Unknown", digest.Digest("unknown:invalid").Algorithm(), "unknown"}, | ||
// Case-insensitive tests | ||
{"sha256 lowercase", digest.Algorithm("sha256"), "SHA256"}, | ||
{"SHA256 uppercase", digest.Algorithm("SHA256"), "SHA256"}, |
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.
I don’t know why this should silently work - any operations on digest.Algorithm("SHA256")
is going to fail (or panic if not checked via Available
); in that sense at least, such a value of a digest.Algorithm
is simply invalid.
|
||
// Validate the digest type | ||
switch algorithm { | ||
case digest.SHA256, digest.SHA512: |
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.
(It might be valuable for this to rely on GetSupportedDigestAlgorithm
, or for the two functions to refer to the same data.)
I would prefer a merge to get the other parts moving forward. If you'd prefer a |
Sure, I think some kind of a TODO marker pointing back here would be nice. |
79f1c23
to
50b724f
Compare
Added a FIXME at the top of |
- TmpDigestForNewObjects() and TmpSetDigestForNewObjects() for global state - IsSupportedDigestAlgorithm() and GetSupportedDigestAlgorithms() for validation - GetDigestAlgorithmName() with case-insensitive support - GetDigestAlgorithmExpectedLength() for algorithm-to-length mapping - DetectDigestAlgorithmFromLength() for length-based algorithm detection Signed-off-by: Lokesh Mandvekar <lsm5@redhat.com>
50b724f
to
0d11523
Compare
updated the FIXME with a note saying it's a blocker for WIP removal. |
Adds Get and Set methods for configuring digest. Currently, only sha256 and sha512 are supported, but should make future additions easier.
Defaults to sha256.
(cursor assisted)
Will create separate PRs for image and common.