Skip to content
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

Adds support for oci manifests and manifestlists #2076

Merged
merged 21 commits into from
Jul 20, 2018

Conversation

mikebrow
Copy link
Contributor

Here is a draft of the oci manifest/manifest lists that addresses @stevvooe 's request in pr #2021 for oci manifest to be it's own schema.

Also fixes some test case failure issues.

Signed-off-by: Mike Brown [email protected]

isAnOCIManifest := isSchema2 && (schema2Manifest.MediaType == ocischema.MediaTypeManifest)
isAnOCIManifestList := isManifestList && (manifestList.MediaType == manifestlist.MediaTypeOCIManifestList)

badCombinations := [][]bool{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Classic example of why to avoid bools to ascertain support.

Please refactor this method to handle these different cases in a way that is maintainable in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

aight.. yeah was one of the things I didn't refactor from 2021 bit ugly ..

Copy link
Collaborator

Choose a reason for hiding this comment

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

@mikebrow I see. 🐹 🎈

May want to refactor this before we do a big change...

I don't have a better suggestion for this yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can replace the bad combo list with easier to read/update error checks.. like this:

if (isSchema2 && !isAnOCIManifest) && (supportsOCISchema && !supportsSchema2) {
		fmt.Printf("\n\nmanifest is schema2 but accept header only supports OCISchema \n\n")
		w.WriteHeader(http.StatusNotFound)
		return
	}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this comment will be addressed with update

MediaTypeManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
// MediaTypeOCIManifestList specifies the mediaType for OCI compliant manifest
// lists.
MediaTypeOCIManifestList = "application/vnd.oci.image.manifest.list.v1+json"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure that these packages should do duel-OCI-docker support, as it may make subtle differences hard to manage for future contributors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I should hope there are never any differences in functionality between OCIManifestList and docker ManifestList... Since it's currently in synch.. there is a bit of good karma here in keeping it the same package :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

OCI has added fields that Docker's format does not have.

@codecov-io
Copy link

codecov-io commented Nov 21, 2016

Codecov Report

Merging #2076 into master will decrease coverage by 9.25%.
The diff coverage is 71.48%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2076      +/-   ##
==========================================
- Coverage    60.8%   51.55%   -9.26%     
==========================================
  Files         129      132       +3     
  Lines       11901    12122     +221     
==========================================
- Hits         7236     6249     -987     
- Misses       3764     5092    +1328     
+ Partials      901      781     -120
Impacted Files Coverage Δ
blobs.go 62.5% <ø> (ø) ⬆️
manifest/schema2/manifest.go 87.8% <100%> (+6.22%) ⬆️
registry/storage/manifeststore.go 84.05% <100%> (+2.7%) ⬆️
registry/storage/registry.go 90.54% <100%> (+0.39%) ⬆️
registry/handlers/manifests.go 53.64% <50%> (-1.64%) ⬇️
registry/storage/ocimanifesthandler.go 67.79% <67.79%> (ø)
manifest/ocischema/builder.go 73.8% <73.8%> (ø)
manifest/manifestlist/manifestlist.go 76.71% <80%> (+1.71%) ⬆️
manifest/ocischema/manifest.go 80.48% <80.48%> (ø)
registry/storage/driver/gcs/gcs.go 0.39% <0%> (-68.67%) ⬇️
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 749f6af...20aecf1. Read the comment docs.

}

// Manifest defines a schema2 manifest.
type Manifest struct {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there any way we can better leverage opencontainers/image-spec/specs-go?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about we vendor it, import it, and refactor this code after they have an approved v1.0.0?

Otherwise, yes I can do that.

Side note: I see we are missing OCI manifest annotations support...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As an aside would have to do the split ocimanifest list out as a separate package if we're to bring in opencontainers/image-spec/specs-go.

Copy link

Choose a reason for hiding this comment

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

@mikebrow annotations support, is that lacking on this PR or something needed on the OCi-side?

Copy link
Contributor Author

@mikebrow mikebrow Dec 8, 2016

Choose a reason for hiding this comment

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

Lacking in the PR.. the field wasn't in the manifest struct.. was probably added to the oci spec after you guys started this code. Will pick it up when vendoring in the oci spec go code. Not sure what we'll need to do, if anything, to make it first class or if we should just store and retrieve.

@stevvooe
Copy link
Collaborator

@mikebrow This seems like a reasonable start.

Where does this sit vs #2021?

@stevvooe
Copy link
Collaborator

Where does this sit vs #2021?

For example, should we close it or just take it as a proposed change?

@@ -110,7 +110,7 @@ type FileWriter interface {
// number of path components separated by slashes, where each component is
// restricted to alphanumeric characters or a period, underscore, or
// hyphen.
var PathRegexp = regexp.MustCompile(`^(/[A-Za-z0-9._-]+)+$`)
var PathRegexp = regexp.MustCompile(`^(/[A-Za-z0-9._:-]+)+$`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What new paths are we storing? This addition of : will break the registry on windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From Vince's notes: "Added : to the regexp used to determine valid paths, which is necessary for the prepending of oci:"

This is for prepending "oci:" for all tags applied to oci manifests to keep the oci: tags separate from the docker tags for docker images.

Copy link
Contributor Author

@mikebrow mikebrow Nov 30, 2016

Choose a reason for hiding this comment

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

Guess windows has ":" reserved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will change the prepending to "oci." instead of "oci:"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changing to oci. with the update

Copy link
Collaborator

Choose a reason for hiding this comment

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

No, we simply don't use schemes and namespaces in tags. This is a horrid hack and not really workable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wish I new that before I tried to make it work :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this change still needs to be removed.


// Add config to the blob store
m.Config, err = mb.bs.Put(ctx, MediaTypeConfig, mb.configJSON)
// Override MediaType, since Put always replaces the specified media
Copy link
Collaborator

@stevvooe stevvooe Nov 21, 2016

Choose a reason for hiding this comment

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

`since Put always replaces the specified media

  • // type with application/octet-stream in the descriptor it returns.`

This behavior is not fixed. We can change that, if necessary.

Either way, this code should not make assumptions about what config is pointed to. It should really take this as an argument to the constructor.

Copy link
Contributor Author

@mikebrow mikebrow Dec 8, 2016

Choose a reason for hiding this comment

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

So I took a look at changing this and that led me to the blobStore.Put code which states the following at line 77 of registry/storage/blobstore.go:

	// TODO(stevvooe): Write out mediatype here, as well.
	return distribution.Descriptor{
		Size: int64(len(p)),

		// NOTE(stevvooe): The central blob store firewalls media types from
		// other users. The caller should look this up and override the value
		// for the specific repository.
		MediaType: "application/octet-stream",
		Digest:    dgst,
	}, bs.driver.PutContent(ctx, bp, p)

Simple enough to change this to use the passed in mediaType.. but not sure what you meant by it's supposed to firewall the media types.. :-) Just confirming.. do you want me to change this code in blobstore to use the passed in mediaType and go remove all the overwrites being done after puts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

or should this change coincide with some sort of filter/approver being added for puts coming in through the blobServiceListener?

@mikebrow
Copy link
Contributor Author

I recoded 2021 (starting mostly from scratch)... to fix some testing bugs in #2021, and more importantly to move it from the design in 2021 where the docker schema2 was overloaded to also have oci support in it, to a design with a new schema type. You didn't like the design in 2021 so I started it over :-) This can be merged on top of 2021 or we can just start from here.

@stevvooe
Copy link
Collaborator

@mikebrow This approach looks like a good start.

Mostly, we would like to make this as simple as using distribution.UnmarshalManifest. I am seeing a few interface fixes we need to address to make this work in all cases. I wonder if we refactor the tests from there, if we can get a better gauge on the quality of the package structure.

@vbatts
Copy link

vbatts commented Nov 22, 2016

Thanks for doing this @mikebrow !

@stevvooe
Copy link
Collaborator

@vbatts Should we close #2021?

@vbatts
Copy link

vbatts commented Nov 24, 2016 via email

@vbatts
Copy link

vbatts commented Apr 5, 2017

What's next here?

@dmcgowan
Copy link
Collaborator

dmcgowan commented Apr 5, 2017

@vbatts v1.0 spec hopefully :)

Discussed this a little bit yesterday. Given the current timeline we should aim for having this in the 2.8 registry release. We can possibly time such a release around the release of v1.0 image spec as well. The 2.7 release should probably be done sooner and not wait for this change.

Would it be helpful if we milestoned this? Maybe we can consider merging this using the image spec release candidate after we cut a 2.7 release branch.

@vbatts
Copy link

vbatts commented Apr 5, 2017 via email

@vbatts
Copy link

vbatts commented Jul 8, 2017

@mikebrow ready to rebase this??? 🤓

@stevvooe
Copy link
Collaborator

@mikebrow Pretty please? It is time... 💯 🥇

@mikebrow
Copy link
Contributor Author

cool.. I'm on it..

@vbatts
Copy link

vbatts commented Jul 10, 2017

👾 ✨

@mikebrow
Copy link
Contributor Author

mikebrow commented Jul 10, 2017

PR rebased.. and nit comments addressed.

@mikebrow
Copy link
Contributor Author

mikebrow commented Jul 10, 2017

The only comment I didn't address (I believe) is vendoring the image spec and refactoring this code to use it. Want to do that on a subsequent PR or this one? Oh yeah and it's missing annotations support.

@mikebrow
Copy link
Contributor Author

I see two commits went into schema2 that we might want put into ocischema as well.. 8867e8f
9ab7b0e

OCI Image manifests and indexes are supported both with and without
an embeded MediaType (the field is reserved according to the spec).
Test storing and retrieving both types from the manifest store.

Signed-off-by: Owen W. Taylor <[email protected]>
@owtaylor owtaylor mentioned this pull request Jun 19, 2018
@GordonTheTurtle
Copy link

Please sign your commits following these rules:
https://github.com/moby/moby/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

$ git clone -b "ocitype" [email protected]:mikebrow/distribution.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842354379640
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f

Amending updates the existing PR. You DO NOT need to open a new one.

Handle OCI manifests and image indexes without a media type

Signed-off-by: Mike Brown <[email protected]>
@mikebrow
Copy link
Contributor Author

@dmcgowan @crosbymichael FYI.. this is the PR for OCI support in the registry that we discussed at the dockercon containerd maintainer face to face.

@crosbymichael
Copy link

Thanks for the ping @mikebrow

@sargun sargun mentioned this pull request Jun 25, 2018
}

// SetMediaType is for testing purposes, we want to be able to create an OCI image with
// either an MediaType either empty, or with the OCI image value
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be reworded

Copy link
Contributor Author

Choose a reason for hiding this comment

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

reworded...

@crosbymichael
Copy link

I was testing this with containerd and pushes work but on a pull i get an error

registry logs:

time="2018-07-19T20:10:24.236940177Z" level=error msg="response completed with error" err.code=unknown err.detail="unrecognized manifest schema version 0" err.message="unknown error" go.version=go1.10.3 http.request.host="127.0.0.1:5000" http.request.id=3886b765-a36d-48a5-973c-bc5fc60c6bf9 http.request.method=HEAD http.request.remoteaddr="127.0.0.1:40058" http.request.uri="/v2/redis/manifests/latest" http.request.useragent="Go-http-client/1.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=6.019726ms http.response.status=500 http.response.written=70 vars.name=redis vars.reference=latest

ctr

sudo ctr images pull --plain-http 127.0.0.1:5000/redis:latest
ctr: failed to resolve reference "127.0.0.1:5000/redis:latest": unexpected status code http://127.0.0.1:5000/v2/redis/manifests/latest: 500 Internal Server Error

// valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json"
func (mb *Builder) SetMediaType(mediaType string) {
if mediaType != "" && mediaType != v1.MediaTypeImageManifest {
panic("Invalid media type for OCI image manifest")

Choose a reason for hiding this comment

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

Are we sure we want a panic here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Addressed.

}
)

func init() {

Choose a reason for hiding this comment

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

is this how distribution handles things or can this be moved out of an init?

Copy link
Contributor Author

@mikebrow mikebrow Jul 19, 2018

Choose a reason for hiding this comment

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

it's how distribution registers the manifest media types (schema types), see:
https://github.com/docker/distribution/blob/master/manifest/schema2/manifest.go#L56
for the example that registers docker's schema2 manifest.

In this case we're setting up to handle "application/vnd.oci.image.manifest.v1+json"

@mikebrow
Copy link
Contributor Author

I was testing this with containerd and pushes work but on a pull i get an error
registry logs:

..."unrecognized manifest schema version 0" err.message="

@crosbymichael

Initially I was thinking it made sense, given oci schema's near identical alignment with docker schema2 manifests to go with version 2 as the initial oci schema manifest version number.

WDYT make it 0, 1, or stick with 2?

@jonjohnsonjr
Copy link
Contributor

@mikebrow

This REQUIRED property specifies the image manifest schema version. For this version of the specification, this MUST be 2 to ensure backward compatibility with older versions of Docker. The value of this field will not change. This field MAY be removed in a future version of the specification.

https://github.com/opencontainers/image-spec/blob/master/manifest.md#image-manifest-property-descriptions

@crosbymichael
Copy link

LGTM

@dmcgowan
Copy link
Collaborator

LGTM

Thanks everyone for testing this and your patience. Note to use the OCI manifests with Docker you will need to update to a newer version which has support for these media types. Support is being backported to all supported version of Docker released in the last year.

@dmcgowan dmcgowan merged commit 0dae095 into distribution:master Jul 20, 2018
@vbatts
Copy link

vbatts commented Jul 20, 2018 via email

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

Successfully merging this pull request may close these issues.