Skip to content

Conversation

@runcom
Copy link
Member

@runcom runcom commented May 23, 2017

Moby-side stuff of #26369

/cc @stevvooe @thaJeztah @cpuguy83 @vbatts

client side is docker/cli#122

Signed-off-by: Antonio Murdaca [email protected]

@runcom
Copy link
Member Author

runcom commented May 23, 2017

well, I guess I need to rewrite integration tests :)

@vdemeester
Copy link
Member

@runcom right, only api 👼 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have tests for index.json?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you look at my comment above it says I need to rewrite tests because test API changed AND current integration tests are testing the old refs directory from image-spec. So yes, I'll do that by adapting the existing ones.

@runcom
Copy link
Member Author

runcom commented May 24, 2017

waiting for opencontainers/image-spec#681 (I'll revendor and fix tests afterwards)

@runcom
Copy link
Member Author

runcom commented May 24, 2017

vendored [email protected], will work to fix tests now.

@thaJeztah
Copy link
Member

@runcom can you re-run vendoring with the latest version of vndr? There was a change not too long ago that changed what's vendored by that tool (nested vendor.conf files are now preserved);

14:21:13 The result of vndr differs
14:21:13 
14:21:13 ?? vendor/github.com/docker/distribution/vendor.conf
14:21:13 ?? vendor/github.com/docker/libnetwork/vendor.conf
14:21:13 ?? vendor/github.com/docker/swarmkit/vendor.conf
14:21:13 ?? vendor/github.com/opencontainers/runc/vendor.conf
14:21:13 
14:21:13 Please vendor your package with github.com/LK4D4/vndr.

Also looks like some tests need to be updated;

14:18:18 ++ go test -c -o /go/src/github.com/docker/docker/bundles/17.06.0-dev/test-integration-cli/test.main -ldflags -w -tags 'autogen netgo static_build apparmor pkcs11 seccomp selinux daemon journald libdm_no_deferred_remove' -installsuffix netgo -a
14:19:17 # github.com/docker/docker/integration-cli
14:19:17 ./docker_cli_save_load_test.go:391: cannot use "FROM busybox\nENV oci=true" (type string) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:391: cannot use true (type bool) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:391: assignment count mismatch: 2 = 1
14:19:17 ./docker_cli_save_load_test.go:395: cannot use "FROM busybox\nENV oci=true\nENV oci=false" (type string) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:395: cannot use true (type bool) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:395: assignment count mismatch: 2 = 1
14:19:17 ./docker_cli_save_load_test.go:440: cannot use "FROM busybox\nENV oci=true" (type string) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:440: cannot use true (type bool) as type "github.com/docker/docker/integration-cli/cli".CmdOperator in argument to buildImage
14:19:17 ./docker_cli_save_load_test.go:440: assignment count mismatch: 2 = 1

@thaJeztah thaJeztah added the status/failing-ci Indicates that the PR in its current state fails the test suite label May 30, 2017
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check the platform here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a check

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're already doing that when actually loading the image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to hold over into the next name's tags in the for loop below if more than one image is saved at once. e.g.

./build/docker-linux-amd64 -D save -f oci.v1 hello-world nginx -o multi-image-bundle.tar \
Error response from daemon: unable to include unique references "latest" in OCI image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both your nginx and hello-world image have indeed the latest tag, thus you can't save it uniquely

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you can't save two different images, like:
docker image save ubuntu:latest busybox:latest -o image-latest-save.tar
(which works today)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, that's one of the assumption in the design #25779 - you need to use --ref

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah! i was using ref wrong. thanks @runcom

@stevvooe
Copy link
Contributor

@runcom Do you mind rebasing? I'd like to kick the tires on this again.

@runcom
Copy link
Member Author

runcom commented Jul 20, 2017

I will work on this tomorrow and on the weekend, I'll update this by next week no worry

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more clear would be "cannot load with both name and refs"

@runcom runcom force-pushed the oci-save-load-moby branch from b293169 to bb21673 Compare August 7, 2017 07:41
@runcom runcom requested a review from dnephin as a code owner August 7, 2017 07:41
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI tests -> API ones?

@cyphar
Copy link
Contributor

cyphar commented Aug 19, 2017

@runcom I can carry this if you're too busy working on cri-o. 😸

@runcom
Copy link
Member Author

runcom commented Aug 19, 2017

I can work on this this weekend, I'll ping you if I can't make it :)

@runcom
Copy link
Member Author

runcom commented Aug 19, 2017

To begin with, I just rebased this 😛

@runcom runcom force-pushed the oci-save-load-moby branch from bb21673 to 6d830ee Compare August 19, 2017 18:11
@runcom runcom requested a review from vdemeester as a code owner August 19, 2017 18:11
@runcom
Copy link
Member Author

runcom commented Aug 21, 2017

I'm porting integration-cli to integration and/or unit tests now, @stevvooe @cyphar et all could you guys review code meanwhile?

@runcom
Copy link
Member Author

runcom commented Jan 8, 2018

ping @AkihiroSuda @vdemeester @dnephin

Copy link
Member

@AkihiroSuda AkihiroSuda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM if green

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too familiar with the conversion/format changes itself, but left some comments for the API side of things 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this blank line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this blank line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this blank line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this adds name, refs options to POST /images/load; these should be documented in the swagger.yml, and in the api version history

The refs option looks like it needs some documentation (what's the format, and how is it used?); IIUC, it's a mapping from image:tag(s) to name(s) (OCI)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add doc around that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a swagger/api version doc for experimental as well? (this is experimental)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed on Slack, no real need for swagger API for experimental

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here for format and refs options for GET /images/get) to the API; these should be documented in the swagger.yml, and in the api version history

Be sure to document what accepted values are for format (and if there's a default / what's the default)

Same here for documenting the refs option as well; what's the format? what's the purpose?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no swagger for experimental

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new options should be ignored on older API versions, and a default should be set (if needed) for older API versions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably need to ignore new options then

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default is already set

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: the new options should be ignored on older API versions, and a default should be set (if needed) for older API versions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already defaulted

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@runcom shouldn't they still be ignored on older API versions (and if experimental is disabled?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a != "" below this line which should make sure to ignore this

Copy link
Member

@thaJeztah thaJeztah Feb 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, what I meant was that if I do;

/v1.25/images/load?refs=something&name=something

It should ignore those options, even though it's set, because API v1.25 doesn't support it

Signed-off-by: Antonio Murdaca <[email protected]>
@runcom runcom force-pushed the oci-save-load-moby branch from 8f6a743 to 1276f74 Compare January 22, 2018 10:23
@runcom
Copy link
Member Author

runcom commented Jan 22, 2018

@thaJeztah took care of your comment, @vdemeester @dnephin PTAL

Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🐻
but somehow, the vendor is wrong..

10:31:39  M vendor/github.com/xeipuuv/gojsonschema/README.md
10:31:39  M vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
10:31:39  M vendor/go4.org/LICENSE
10:31:39  M vendor/go4.org/README.md

github.com/xeipuuv/gojsonschema 212d8a0df7acfab8bdd190a7a69f0ab7376edcc8
github.com/xeipuuv/gojsonreference e02fc20de94c78484cd5ffb007f8af96be030a45
github.com/xeipuuv/gojsonpointer 6fe8760cad3569743d51ddbb243b26f8456742dc
go4.org 034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e https://github.com/camlistore/go4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need this alternative source for go4.org. vndr seems to work fine with just the canonical url.

opts := &tarexport.Options{
Format: format,
Refs: refs,
Experimental: daemon.HasExperimental(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tarexport shouldn't need to know about experimental. I think that needs to be handled in this Daemon method (same below for Load).

That looks like it's easy to do for save (just check format), but for load I guess it's a bit more involved. I think it can be handled by changing the tarexporter interface to return the Loader instead of Load(). Then you can check the type by adding tarexport.IsOCILoader(loader).

// when exporting to the OCI format.
// format is the format of the resulting tar ball.
func (daemon *Daemon) ExportImage(names []string, format string, refs map[string]string, outStream io.Writer) error {
opts := &tarexport.Options{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These options are being used as a dependency of tarexport, but they are specific to the operation, not re-usable dependencies.

They are also not used by all operations (save uses Format, load uses Name).
I think they should be split into SaveOptions and LoadOptions, and should be args to save/load (not the constructor).

index ociv1.Index
}

func (l *tarexporter) getRefs() (map[string]string, map[string]reference.NamedTagged, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method really has nothing to do with tarexporter, and with my proposed change of removing Options from tarexporter this will need to move somewhere else.

I think this can be split into two functions:

func normalizeOCIRefs(refs map[string]string) error {
   ...
}

func refsToTaggedRefs(refs map[string]string) (map[string]reference.NamedTagged, error) {
   ...
}

parseOCINames can call normalizeOCIRefs since it doesn't need the tagged, and load can call refsToTaggedRefs.

return errors.New("no OCI name mapping provided")
}

// FIXME(runcom): validate and check version of "oci-layout" file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this FIXME still relevant?

if !ok {
return fmt.Errorf("no ref name annotation")
}
if ol.tr.name != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing in both name and refs I think the validation at the top of this function and this if/else block could be extracted into a function for resolving refNameToTag(string) string, and passed in as a dependency to Load.

That helps keep the different responsibilities separate, and reduces the number of dependencies.


var ociRefRegexp = regexp.MustCompile(`^([A-Za-z0-9._-]+)+$`)

func (l *tarexporter) parseOCINames(names []string) (desc map[image.ID]*imageDescriptor, rErr error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably makes more sense as a method on ociSaveSession

@AkihiroSuda
Copy link
Member

@runcom Could you update PR 🙏

@runcom
Copy link
Member Author

runcom commented Feb 13, 2018

@runcom Could you update PR

Yup, I'm working on it!

@AkihiroSuda
Copy link
Member

@runcom Sorry could you please rebase again 🙏

}
}
var tag string
refName, ok := md.Annotations[ociv1.AnnotationRefName]
Copy link
Member

@thaJeztah thaJeztah May 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussing in the maintainers session with @tonistiigi @dmcgowan @cpuguy83 @tianon if we should make this customisable, so that a different annotation can be used as name instead of the standard one.

Basically thought is: if a custom annotation is specified (e.g. com.docker.image.refname, which could be used as a default), we take an annotation with that name, and use it as name/reference for the image.

Providing custom names, or loading an image without tagging it could then be done in a follow up pr (as extra feature)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would we ever differ from what OCI states by introducing/reading a custom docker annotation for an OCI image?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's current status?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with @runcom -- this doesn't make any sense and would just lead to fragmentation among OCI image users. The main proponent of the org.opencontainers.ref.name setup was @stevvooe -- and I'm sure he had considered integration into Docker as part of the design.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyphar I have always been against having naming in OCI, as it causes these kinds of problems. I've only been around to contain the damage. Please stop harassing people with nonsense.

There are two considerations to make with ref.name:

  1. It should express a reference to the granularity of a tag.
  2. It is only valid on index.json to express tags with an archive.

The problem is that the contents of OCI ref.name may differ from what can be supported by docker. To avoid conflict between Docker and whatever OCI decided to put in ref.name, one can define a vendor specific field that has a more restrictive format that is compatible with docker.

If you want compatibility, you either need to lock ref.name down to what docker supports or support vendor-specific tags.

Copy link
Contributor

@vbatts vbatts Sep 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please stop harassing people with nonsense.

Woah, simmer. I didn't see anything harassing.

Copy link
Contributor

@cyphar cyphar Sep 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have always been against having naming in OCI, as it causes these kinds of problems. I've only been around to contain the damage. Please stop harassing people with nonsense.

It wasn't my intention to harass you at all, sorry if I made you feel that way. The reason why I mentioned you is because you did quite a bit of the work on ref.name as well as the main person I remember being a major voice in the ref.name discussions was you (hence as far as I'm aware you are the resident expert on it). I wanted to hear your opinion on it in this context.

For the record, I agree with you that naming is something that generally should've been ironed out a bit more (though I don't really agree it should've been excluded entirely, as that would have caused usability issues in my humble opinion) -- but we now have ref.name and I had always assumed the background of the design had considered how containerd/Docker would interact with it. If I'm mistaken in that assumption, please let me know.

If you want compatibility, you either need to lock ref.name down to what docker supports or support vendor-specific tags.

I don't mind supporting vendor specific tags, but if the idea of docker save --format=oci is to be compatible with other tools then I think compatibility of the "entrypoint" to the image with other tools needs to be considered. Most major OCI image tools (umoci, skopeo, and containerd as far as I know) use ref.name -- so if Docker starts outputting things not using ref.name then it will have compatibility issues (if you recall this was part of one of the longer discussions we had last year -- "how do we make sure name compatibility works among different implementations?").

I understand the concern with Docker putting stuff in ref.name that is incompatible -- maybe we should have some way of telling Docker to remap the image names for OCI images so that they are compatible with ref.name? Or maybe Docker should output both ref.name (in an encoded format to avoid the character set issue -- so that at least it's usable out-of-the-box with other tools) and also a "canonical" docker.ref.name which is vendor-specific and thus tools can grow support for it organically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyphar The concern is really in the other direction. If other tools place stuff in ref.name that is incompatible, docker won't be able to import those without munging the names. The scope of what can be done in ref.name is greater than the scope of what docker can or will support.

While it would have been nice to specify OCI ref.name, there were too many requests for changes to make it work without changing docker. I'll also concede that the grammar is pretty bonkers, so specifying it formally would have been problematic.

I would say that as long as people adhere to what docker supports, there won't be a problem. If there are systems that want to use their own naming and be compatible with docker, the vendor specific ref.name would be an avenue of support.

As far as naming containers in the future goes, you can see some of my latest opinions in https://github.com/containerd/containerd/blob/master/reference/reference.go#L39. This creates a docker-compatible super-set based on schema-less URIs. The host becomes a namespace or authority and registry lookup is done out of band. This is what containerd implements but it defers interpretation of the url up to the actual subsystem that locates the image, rather than relying on microformat details.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevvooe

What if docker load --format=oci took a flag that told it what the in-Docker image name should be and what ref.name to source it from should be -- so that at the very least you didn't have to add Docker-specific tags in order to use the OCI import?

Speaking personally, I would prefer having to manually do docker load --format=oci --output cyphar/blah:foo --input some_oci_image:foo rather than having to modify every image I generate so that they can be imported into Docker.

And there is the obvious question of if we already have this issue with just docker load -- how will this problem shake out when (if?) Docker supports OCI images through docker pull? I will be honest that I'm not familiar how the OCI distribution-spec has changed since it was copied from the Docker one -- but I imagine that ref.name is something that we would want to have some sort of unity over? Or will the naming on the distribution-spec level be entirely separate to the naming on the image-spec level?

(As for naming, I think that there should be some even more drastic discussions about naming but I think those are way out of scope here.)

@olljanat
Copy link
Contributor

@runcom this one needs to be rebased

@derek derek bot added the status/failing-ci Indicates that the PR in its current state fails the test suite label Dec 22, 2018
@marek-obuchowicz
Copy link

Hey... just a friendly ping :) Is there any way to get this feature soon finalised?

@AkihiroSuda
Copy link
Member

This is being replaced by #38738

@crosbymichael
Copy link
Contributor

As @AkihiroSuda said, we should close this one as it's being implemented in the containerd update in #38738 to use the existing oci import/export code that lives in the containerd project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/distribution Image Distribution impact/changelog kind/experimental status/failing-ci Indicates that the PR in its current state fails the test suite status/2-code-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.