-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add OCI source #2827
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
Add OCI source #2827
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "context" | ||
| _ "crypto/sha256" // for opencontainers/go-digest | ||
| "encoding/json" | ||
| "fmt" | ||
| "os" | ||
| "strconv" | ||
| "strings" | ||
|
|
@@ -132,8 +133,9 @@ func Image(ref string, opts ...ImageOption) State { | |
| p = c.Platform | ||
| } | ||
| _, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{ | ||
| Platform: p, | ||
| ResolveMode: info.resolveMode.String(), | ||
| Platform: p, | ||
| ResolveMode: info.resolveMode.String(), | ||
| ResolverType: ResolverTypeRegistry, | ||
| }) | ||
| if err != nil { | ||
| return State{}, err | ||
|
|
@@ -147,8 +149,9 @@ func Image(ref string, opts ...ImageOption) State { | |
| p = c.Platform | ||
| } | ||
| dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{ | ||
| Platform: p, | ||
| ResolveMode: info.resolveMode.String(), | ||
| Platform: p, | ||
| ResolveMode: info.resolveMode.String(), | ||
| ResolverType: ResolverTypeRegistry, | ||
| }) | ||
| if err != nil { | ||
| return State{}, err | ||
|
|
@@ -452,6 +455,57 @@ func Differ(t DiffType, required bool) LocalOption { | |
| }) | ||
| } | ||
|
|
||
| func OCILayout(contentStoreID string, dig digest.Digest, opts ...OCILayoutOption) State { | ||
| gi := &OCILayoutInfo{} | ||
|
|
||
| for _, o := range opts { | ||
| o.SetOCILayoutOption(gi) | ||
| } | ||
| attrs := map[string]string{} | ||
| if gi.sessionID != "" { | ||
| attrs[pb.AttrOCILayoutSessionID] = gi.sessionID | ||
| addCap(&gi.Constraints, pb.CapSourceOCILayoutSessionID) | ||
| } | ||
|
|
||
| if ll := gi.layerLimit; ll != nil { | ||
| attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*ll), 10) | ||
| addCap(&gi.Constraints, pb.CapSourceOCILayoutLayerLimit) | ||
| } | ||
|
|
||
| addCap(&gi.Constraints, pb.CapSourceOCILayout) | ||
|
|
||
| source := NewSource(fmt.Sprintf("oci-layout://%s@%s", contentStoreID, dig), attrs, gi.Constraints) | ||
| return NewState(source.Output()) | ||
| } | ||
|
|
||
| type OCILayoutOption interface { | ||
| SetOCILayoutOption(*OCILayoutInfo) | ||
| } | ||
|
|
||
| type ociLayoutOptionFunc func(*OCILayoutInfo) | ||
|
|
||
| func (fn ociLayoutOptionFunc) SetOCILayoutOption(li *OCILayoutInfo) { | ||
| fn(li) | ||
| } | ||
|
|
||
| func OCISessionID(id string) OCILayoutOption { | ||
| return ociLayoutOptionFunc(func(oi *OCILayoutInfo) { | ||
| oi.sessionID = id | ||
| }) | ||
| } | ||
|
|
||
| func OCILayerLimit(limit int) OCILayoutOption { | ||
| return ociLayoutOptionFunc(func(oi *OCILayoutInfo) { | ||
| oi.layerLimit = &limit | ||
| }) | ||
| } | ||
|
|
||
| type OCILayoutInfo struct { | ||
| constraintsWrapper | ||
| sessionID string | ||
| layerLimit *int | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a reason one is public and other private?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. I will make them both private if |
||
| } | ||
|
|
||
| type DiffType string | ||
|
|
||
| const ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package build | ||
|
|
||
| import ( | ||
| "strings" | ||
|
|
||
| "github.com/containerd/containerd/content" | ||
| "github.com/containerd/containerd/content/local" | ||
| "github.com/pkg/errors" | ||
| ) | ||
|
|
||
| // ParseOCILayout parses --oci-layout | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you update
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CC @deitch 👀 Sorry to bump this PR, but was trying to use this earlier and struggled to work out the right flags 🎉
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't be sorry @jedevc ; if it needs addressing, it should be raised. FWIW, I wrote this PR, and I still need to look back to recall what flags should be used where. @AkihiroSuda I am fine opening a PR to update the README, but I am not sure where to put it. I don't see a section in the README that shows "here is where you add source contexts". I also (despite having written this) don't remember the magical invocation. I think it was something like this. For Dockerfile: FROM akihiro/abc:123but something doesn't look right to me. Something is missing about mapping Help me remember how to do this, and where it goes, and I am happy to add it to the README.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Doesn't look like we have anywhere for it atm, ideally we'd have a new section on "contexts" maybe right before Outputs? (so we'd cover
No idea 😄 I'm at a bit of a loss. I imagine something like this to work: I imagine this isn't working since it doesn't look like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't mind doing that. Why don't you get the others in, and then I can add, maybe on your PR for that?
Haha! That makes both of us.
I don't think it ever was; wasn't it just for The docker buildx extensions have a straight mapping of "image name" -> context, e.g. here, so I can do: FROM akihiro/abc:123and then But as I recall, the
The
I really do not recall. Tonis had us do the server-side logic first along with frontend, then buildx. I had though buildctl had the support, since it doesn't need to be explicitly listed (part 1 already works, and part 2 just gets passed to buildkitd), but maybe I am missing something? I really thought we had run it back when this went in.
Can you post a sample? Here or on a gist? Let's have a common base to work with?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To create the OCI folder: $ rm -rf dump; echo "FROM alpine:3.14" | buildx build -f - --output type=oci,dest=./out.tar .; mkdir dump; (cd dump; tar xf ../out.tar)With the following FROM foo
RUN apk add gitAnd the following command with the appropriate sha (assuming a running buildkit built off of master listening on port 1234): $ buildctl --addr tcp://localhost:1234 build --frontend=dockerfile.v0 --local context=. --local dockerfile=. --opt context:foo=oci-layout://dump@sha256:79a06bdbfbf27b365be61ca38646b07b451681475c284ad79deed506ab192917
...
------
> [context foo] load metadata for dump@sha256:79a06bdbfbf27b365be61ca38646b07b451681475c284ad79deed506ab192917:
------
Dockerfile:1
--------------------
1 | >>> FROM foo
2 | RUN apk add git
3 |
--------------------
error: failed to solve: unable to get info about digest: Unimplemented: unknown service containerd.services.content.v1.Content: unknownReading through the PR, it looks like we should need to pass
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cool, will comment there. |
||
| func ParseOCILayout(layouts []string) (map[string]content.Store, error) { | ||
| contentStores := make(map[string]content.Store) | ||
| for _, idAndDir := range layouts { | ||
| parts := strings.SplitN(idAndDir, "=", 2) | ||
| if len(parts) != 2 { | ||
| return nil, errors.Errorf("oci-layout option must be 'id=path/to/layout', instead had invalid %s", idAndDir) | ||
| } | ||
| cs, err := local.NewStore(parts[1]) | ||
| if err != nil { | ||
| return nil, errors.Wrapf(err, "oci-layout context at %s failed to initialize", parts[1]) | ||
| } | ||
| contentStores[parts[0]] = cs | ||
| } | ||
|
|
||
| return contentStores, 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.
I don't see a way to pass layer limit in this mode. Maybe it is possible to share the
ImageOptionsin here. Not all imageoptions are supported in here andSessionIDis not supported for regular images. But some are the same(layerlimit etc) and want to make sure we don't drop any.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.
If they don't quite overlap, then I can copy them over. It doesn't hurt.
What others are relevant? ImageInfo looks like:
We already have
constraintsWrapper(as all do) and nowlayerLimit. Which others?