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
cmd/build: add support for --push
#4677
base: main
Are you sure you want to change the base?
Conversation
I was thinking this would just be added to the client and not the service side. buildah build --push Would internally do buildah build followed by buildah push. |
What do you think @nalind @flouthoc @vrothberg |
That would be simpler; API callers already have a For the "output=registry" case, setting |
And just in case, we'll need updates to the man page and additional test added for the final PR. From a quick flyby review, it LGTM other than other comments. |
I am no fan of mixing multiple commands as it breaks separation of concerns. But I leave the decision up to the core maintainers of Buildah. |
I see this for compatibility with buildx I don't think we have to add other options for push, and potentially could have just done this in podman build, but the --output=type calls are handled within buildah. |
I concur should we just do this at podman, and only add |
07d26e5
to
f934001
Compare
I honestly didn't think that is how we'd want to push. On the outset,
You're right, that was an oversight. |
So adding the |
internal/util/util.go
Outdated
|
||
image := opts.Attrs["name"] | ||
destSpec := opts.Attrs["name"] | ||
dest, err := alltransports.ParseImageName(destSpec) |
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 am not sure this code is correct, or necessary. I know that @mtrmac and @vrothberg frown on parsing specs outside of github.com/containers/image or github.com/containers/common/libimage
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; as a general principle I think the CLI layer, or something as close to it as possible, should be responsible for turning strings into a unique types.ImageReference
.
Admittedly that’s not always possible, but it’s the thing to strive for.
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.
Does it help if it's moved to util? #4677 (comment)
define/types.go
Outdated
@@ -100,6 +100,8 @@ type Secret struct { | |||
|
|||
// BuildOutputOptions contains the the outcome of parsing the value of a build --output flag | |||
type BuildOutputOption struct { | |||
Type string | |||
Attrs map[string]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 is this adding an untyped map instead simple Go fields that exactly represent what we need?
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 was referenced from buildx but the idea remains the same, for every type, there are (and would be in the future) multiple arguments/options which are consolidated under attributes here. It's possible for us to have individual fields here but those would eventually proliferate into a heterogenous struct type and I'm not sure how ideal that would be.
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 ultimately up to Buildah maintainers, not me.
IMHO individual fields, or individual types, is much better than Attrs
, because Attrs
is equally heterogenous, just with much worse compiler / linter support.
We can do interfaces, type checks, wrappers, …
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.
That's a good point. Perhaps we can have embedded structs here for individual Types as and when the situation arises? Looking for inputs
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.
Up to Buildah maintainers.
(My personal style would be:
Type
field first- Then separate sections for individual subtypes, separated by blank lines and with a comment “valid if Type == … ”
so that future maintainers can just look at the type definition and don’t have to chase individual field uses in an IDE.
I agree that separate structs, or even type checks, might be overkill for this small scope.)
internal/util/util.go
Outdated
libimageOptions.Writer = os.Stdout | ||
runtime, err := libimage.RuntimeFromStore(store, &libimage.RuntimeOptions{SystemContext: &types.SystemContext{}}) | ||
destString := fmt.Sprintf("%s:%s", dest.Transport().Name(), dest.StringWithinTransport()) | ||
_, err = runtime.Push(context.Background(), image, destString, libimageOptions) |
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.
(Eventually, could libImage
have an API that accepts type.ImageReference
directly?)
e22f351
to
d6925cd
Compare
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’s quite likely I don’t have a full context of the goals / constraints of the Buildx feature set or compatibility; I’m looking basically only at this PR in isolation.
I’ll fully defer to actual Buildah maintainers.
util/util.go
Outdated
@@ -50,6 +51,31 @@ func StringInSlice(s string, slice []string) bool { | |||
return util.StringInSlice(s, slice) | |||
} | |||
|
|||
func StringToImageReference(image string) (types.ImageReference, error) { |
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.
UIArgumentToImageReference
? HeuristicUserInputToImageReference
? Something along those lines? (Up to Buildah maintainers.)
I, fairly desperately, don’t want this code to be used to “round-trip” between ImageReference
and string
[there already are other functions for that], and this plain naming of the function suggests that it could be used for that purpose.
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, fairly desperately, don’t want this code to be used to “round-trip” between ImageReference and string
Sorry but would you mind explaining what you mean? Some sort of abuse this function would get by being used in unintended places?
Also, how about ImageStringToImageReference
?
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.
Some sort of abuse this function would get by being used in unintended places?
Yes. The function is a heuristic that can parse the input using several different format/semantics, depending on what happens to work.
A failure case I’ve seen fairly frequently in this space is finding some pre-existing function like that, similarly targeted at the UI and heuristically doing “what the user meant”, and embedding it somewhere deeper in the call stack, calling it with a string produced from a Go value, without accounting for the details of the heuristics, or possibly the CLI-level heuristics being expanded to add new user-level features. The outcome is that the Go value → string → Go value transformation (which might, sometimes, be unavoidable, e.g. for multi-machine operations) becomes inexact, hard to predict, and possibly even leads to security issues.
Hence all of the concern about not using strings as an internal representation if at all possible, as the easiest preventative measure.
Secondarily, using the right string representation / API. The types.ImageReference
values already have an API for producing a string representation, and for creating one from a string representation. That one (alltransports.ParseImageName
) should be used anywhere below the CLI heuristic layers, and the new function should be named so that it isn’t accidentally used instead.
So that’s why I would like some mention of UI, and preferably “heuristics” in the name.
“Image string” does not help because it does not disambiguate “a lossy heuristic subject to change” from “a stable round-trip-safe value conversion”, either would apply to images and strings.
d6925cd
to
bd7e5cf
Compare
Hi, I just created containers/podman#18642 It looks related to this PR.
I agree but a good reason to combine them is to enable parallelism. |
bd7e5cf
to
4b19451
Compare
@danishprakash Are you still working on this? |
Yes, @rhatdan. Will try to address the remaining comments and the tests by early next week. |
4b19451
to
aca3866
Compare
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: danishprakash 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 |
aca3866
to
684d7ae
Compare
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.
(FWIW the code right now fails a test.)
IsDir: false, | ||
IsStdout: true}, nil | ||
} | ||
if !strings.Contains(buildOutput, ",") { |
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 case is now completely removed? Isn’t that a breaking change for existing users?
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 looks like a catch-call, I believe this is being handled by the switch case below, now that we expect extended attributes for types, we shouldn't be returning early here.
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.
Isn‘t that confirming my impression that existing syntax stops working?
Why is that acceptable? (It might well be, I’m not that familiar with Buildah. But I definitely want this to be a conscious decision by Buildah maintainers.)
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.
Fair enough, but now that we are handling extended attributes, it'd make little sense for us to still handle this case, and besides, it's going to be counterintuitive for the user to use this. But then again, i think it's better if someone who has more context on this piece comment once.
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.
that existing syntax stops working
Not entirely though, you can still go ahead and use --output=type=image
and it'll do the right thing instead of defaulting to a preset condition as before.
out.Push = true | ||
} | ||
|
||
if !typeSelected && !pathSelected { |
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 seems to need more nuance. Isn’t the path still required for local destinations, just not for the type …Image
case?
And, for the type …Image
case, isn’t specifying a path an error?
imagebuildah/stage_executor.go
Outdated
@@ -2071,7 +2071,15 @@ func (s *StageExecutor) commit(ctx context.Context, createdBy string, emptyLayer | |||
return imgID, ref, nil | |||
} | |||
|
|||
func (s *StageExecutor) generateBuildOutput(buildOutputOpts define.BuildOutputOption) error { | |||
func (s *StageExecutor) generateBuildOutput(ops define.BuildOutputOption) error { | |||
if ops.Push { |
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.
AFAICS type=image
will go down the ExportFromReader
path below, and fail because …Image
is not handled there.
That’s just not implemented at all?
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.
internal/util/util.go
Outdated
// ExportImage copies contents of the image to a new location | ||
func ExportImage(store storage.Store, opts define.BuildOutputOption) error { | ||
if !opts.Push { | ||
return nil |
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 silently succeed? If the only caller only calls this with .Push
, this function should either not check, or fail with an “internal inconsistency” error.
(Or, alternatively, is type=image
implemented by doing nothing? If so, the caller would have to steer the control flow down this path. But it seems simpler to me to have a top=level dispatcher based on opts.Type
, calling various functions, and not calling a function only for that function to do nothing as a special case.)
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're right, type=image
on its own doesn't require anything additional since the image is built locally before we get to exports. So now, I'm handling a situation where we have type=image,push=true
and if not, then proceed further down.
internal/util/util.go
Outdated
libimageOptions := &libimage.PushOptions{} | ||
libimageOptions.Writer = os.Stdout |
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.
Up to buildah maintainers:
I rather suspect quite a few other options could be set here, but I don’t know to what extent the infrastructure for that 1) already exists, or 2) should be built.
Implementation-wise, at a first glance it seems to me cleaner to delegate this to the existing buildah.Push
code, even if with possibly fewer options; that would minimize drift.
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.
Implementation-wise, at a first glance it seems to me cleaner to delegate this to the existing buildah.Push
That'd be great, right now the contract is a little too much for anyone else to make use of it. On the other hand, if we can abstract out the "push" functionality out of both for better extensibility, that might be ideal.
9989786
to
47f85d4
Compare
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 needs few tests in bud.bats
, we already have some tests for pushing there ( you can take help from there )
A friendly reminder that this PR had no activity for 30 days. |
@danishprakash still working on this? |
Yes, going to get back to this end of this week. |
0036033
to
f9d20a2
Compare
f9d20a2
to
61ed32a
Compare
Ephemeral COPR build failed. @containers/packit-build please check. |
61ed32a
to
7a1ef03
Compare
* pass systemCtx to push util * fix test Signed-off-by: danishprakash <danish.prakash@suse.com>
7a1ef03
to
b2c313d
Compare
What type of PR is this?
/kind feature
Which issue(s) this PR fixes:
Closes #4671
Special notes for your reviewer:
Extremely WIP draft.
Does this PR introduce a user-facing change?