-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
images/create: handle tag/digest if Tag specified #24184
base: main
Are you sure you want to change the base?
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: inknos The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
pkg/api/handlers/compat/images.go
Outdated
// if both name and tagOrDigest are defined we try to use the tagOrDigest image part and override the tag/digest | ||
if len(name) > 0 && len(tagOrDigest) > 0 && strings.Contains(name, separator) { | ||
parts := strings.Split(name, separator) | ||
return fmt.Sprintf("%s%s%s", strings.Join(parts[:len(parts)-1], ""), separator, tagOrDigest) | ||
} |
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.
checking len(tagOrDigest) > 0
is unnecessary as the function returns early if that is empty so we know it cannot be empty here
Then using string.Contains() and strings.Split() adds more overhead then needed here. You can use
strings.LastIndex(name, separator)
once and then when the index is > 0 you can trim the name with name[:index]
However more important speaking string parsing registry references like this does not look correct to me. In particular this will fail when a registry host includes a port number, i.e. 127.0.0.1:5000/myimage
as this would cause the code to cut at the wrong place. I am not super familiar with c/image but assume we should have some "proper" parsing code there to deal with that already so maybe we could resuse that?
cc @mtrmac
If there is no such code we can use then we must at least ensure the :
is after the first /
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.
right, I'll fix it
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.
Yes, things like this should definitely use c/image/v5/docker/reference
; around here, before pkg/shortnames
/ PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub
is used, probably .Parse
, but very carefully — have unit tests for busybox
, docker.io/busybox
, docker.io/library/busybox
.
(As a general principle, I think strings should be parsed into Go values as close to the surface of the app as possible, and then only turned back into strings for I/O or interaction with other processes. But it seems that would be a large restructuring — and we don’t have distinct Go types for “possibly a short name” vs. “a name which certainly contains a host name”. And, anyway, Go makes it very tedious to write bulletproof encapsulation.)
Compare e.g. https://github.com/containers/common/blob/acfcaabd70744222dfcaf962850531c640774d67/libimage/normalize.go#L105 for a very rough shape of things — parse, type check, use TrimNamed
/WithTag
/WithDigest
.
(For the record, I didn’t investigate the motivating API request / behavior at this point.)
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.
would url parsing 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.
No no no no no :)
That would introduce a lot of syntax (like %
escapes, and /
vs //
vs ///
) that we actively don’t want.
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.
127.0.0.1:5000/myimage
is a valid image reference (i.e. not tag default to latest). In this case you would join the tag at the wrong place for name=127.0.0.1:5000/myimage
and tagOrDigest=mytag
will result in a broken 127.0.0.1:mytag
AFAICS
I think it would be really good to add unit tests for this function to check these corner cases properly
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.
yup, to be honest, I would split this functionality into a separate function and unit test that
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 mean you could test the entire mergeNameAndTagOrDigest(), I don't think it needs to be split smaller than that but I would not be opposed either
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 really strongly want this to use the standard c/image/docker/reference
parser and not custom code.
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.
E.g. consider that we’ve had a request for IPv6 addresses (with their embedded :
s) for years, and for all I know, it might actually happen some day.
Podman handles /images/create better when fromImage and Tag are specified. Now the tag/digest value provided in Tag will replace the one in fromImage Fixes: containers#23938 Signed-off-by: Nicola Sella <[email protected]>
@@ -45,6 +45,11 @@ func mergeNameAndTagOrDigest(name, tagOrDigest string) string { | |||
// We have a digest, so let's change the separator. | |||
separator = "@" | |||
} | |||
// if both name and tagOrDigest are defined we try to use the tagOrDigest image part and override the tag/digest | |||
if len(name) > 0 && strings.Contains(name, separator) { |
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.
the contains is unnecessary, LastIndex already tells you if it contains or not so we only need to walk the string once not twice
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.
Oops, the review was left as pending comments. Sorry about that.
pkg/api/handlers/compat/images.go
Outdated
@@ -45,6 +45,12 @@ func mergeNameAndTagOrDigest(name, tagOrDigest string) string { | |||
// We have a digest, so let's change the separator. | |||
separator = "@" | |||
} | |||
|
|||
// if both name and tagOrDigest are defined we try to use the tagOrDigest image part and override the tag/digest | |||
if len(name) > 0 && len(tagOrDigest) > 0 && strings.Contains(name, separator) { |
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 happens if name
contains a tag and tagOrDigest
contains a digest, or vice versa?
pkg/api/handlers/compat/images.go
Outdated
// if both name and tagOrDigest are defined we try to use the tagOrDigest image part and override the tag/digest | ||
if len(name) > 0 && len(tagOrDigest) > 0 && strings.Contains(name, separator) { | ||
parts := strings.Split(name, separator) | ||
return fmt.Sprintf("%s%s%s", strings.Join(parts[:len(parts)-1], ""), separator, tagOrDigest) | ||
} |
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.
Yes, things like this should definitely use c/image/v5/docker/reference
; around here, before pkg/shortnames
/ PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub
is used, probably .Parse
, but very carefully — have unit tests for busybox
, docker.io/busybox
, docker.io/library/busybox
.
(As a general principle, I think strings should be parsed into Go values as close to the surface of the app as possible, and then only turned back into strings for I/O or interaction with other processes. But it seems that would be a large restructuring — and we don’t have distinct Go types for “possibly a short name” vs. “a name which certainly contains a host name”. And, anyway, Go makes it very tedious to write bulletproof encapsulation.)
Compare e.g. https://github.com/containers/common/blob/acfcaabd70744222dfcaf962850531c640774d67/libimage/normalize.go#L105 for a very rough shape of things — parse, type check, use TrimNamed
/WithTag
/WithDigest
.
(For the record, I didn’t investigate the motivating API request / behavior at this point.)
pkg/api/handlers/compat/images.go
Outdated
// if both name and tagOrDigest are defined we try to use the tagOrDigest image part and override the tag/digest | ||
if len(name) > 0 && len(tagOrDigest) > 0 && strings.Contains(name, separator) { | ||
parts := strings.Split(name, separator) | ||
return fmt.Sprintf("%s%s%s", strings.Join(parts[:len(parts)-1], ""), separator, tagOrDigest) | ||
} |
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.
No no no no no :)
That would introduce a lot of syntax (like %
escapes, and /
vs //
vs ///
) that we actively don’t want.
A friendly reminder that this PR had no activity for 30 days. |
Podman handles /images/create better when fromImage and Tag are specified. Now the tag/digest value provided in Tag will replace the one in fromImage
Fixes: #23938
Does this PR introduce a user-facing change?