Skip to content

platforms: define selectors for platforms#1403

Merged
dmcgowan merged 3 commits intocontainerd:masterfrom
stevvooe:platform-selectors
Sep 13, 2017
Merged

platforms: define selectors for platforms#1403
dmcgowan merged 3 commits intocontainerd:masterfrom
stevvooe:platform-selectors

Conversation

@stevvooe
Copy link
Member

@stevvooe stevvooe commented Aug 19, 2017

For supporting selection of images and runtimes in the containerized
world, there is thin support for selecting objects by platform. This
package defines a syntax to display to users that can express specific
platforms in addition to wild cards for matching platforms.

The plan is to extend this to provide support for parsing flag
arguments and displaying platform types for images. This package will
also provide a configurable matcher to allow match of platforms against
arbitrary targets, invariant to the Go compilation.

The internals are based the OCI Image Spec model.

This changeset is being submitted for feedback on the approach before
this gets larger. Specifically, review the unit tests and raise any
concerns.

Signed-off-by: Stephen J Day stephen.day@docker.com

cc @jhowardmsft @darrenstahlmsft @tianon @estesp

@stevvooe stevvooe changed the title platforms: define selectors for platforms [WIP] platforms: define selectors for platforms Aug 19, 2017
Copy link
Member

Choose a reason for hiding this comment

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

if variant == "v8" { variant = ""}? (for better support for future non-v8 variants)

Copy link
Member Author

Choose a reason for hiding this comment

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

arm64 always defaults to v8. If there are future variants, they will be qualified as such.

Copy link
Member

Choose a reason for hiding this comment

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

I think we only need linux, windows, and solaris entries here.
At least, android, plan9, nacl, and zos are really unlikely to be supported in containerd.

Also, I think it is ok to use typed struct here, as the upstream godoc list won't be updated so frequently.

Copy link
Member Author

Choose a reason for hiding this comment

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

@AkihiroSuda We are going to support the full Go space for platform declaration. This does not imply actual support. This is just identification.

Copy link
Member

@tianon tianon left a comment

Choose a reason for hiding this comment

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

Overall I really like the idea of creating a standard "specifier" for these things, but I'm a little confused about the intended usage of this as-is, and how it's expected to work (which I've expanded on a little in my further line comments).

For example, on 32-bit ARM, alpine supports v6, which would be the appropriate image choice for a v7 machine, but debian only support v5 and v7, so for a v6 chip, v5 is the only option unless one switches to Raspbian.

Do you think you could lay out a few of your intended scenarios to help clear up how you imagine this being used? 😇

Copy link
Member

Choose a reason for hiding this comment

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

Won't these also match substrings like fly, c64, or 64p32?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, needs to be fixed.

Copy link
Member

Choose a reason for hiding this comment

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

Why is v6 the implied default? Isn't arm always ambiguous?

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 have to choose a default because there are a lot of images that are just "arm".

Blame "arm", not the messenger.

Copy link
Member

Choose a reason for hiding this comment

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

Right, so shouldn't this go the other way in that case? ie, if there isn't a variant, then v6 is implied?

Copy link
Member Author

Choose a reason for hiding this comment

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

Uh no, v6 doesn't need to be qualified, so we are "normalizing" it.

Copy link
Member

Choose a reason for hiding this comment

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

This seems bizarre to me -- is the intended usage of this PR for something like a --platform flag to docker pull and friends?

I'd personally be very surprised to find that docker pull --platform linux/arm/v6 xxx ended up getting converted to simply linux/arm, and likewise, I'd be surprised if --platform linux/arm implied only v6. I'd honestly want linux/arm to throw an explicit specificity error, or to imply linux/arm/* (and thus choose the first image which is compatible with my current platform).

Copy link
Member Author

Choose a reason for hiding this comment

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

@tianon This is kind of the de facto standard for unqualified arm. Go's runtime defaults to 6 and we kind of need to choose a common denominator that makes this easy. armhf seems to have a default of v6, as well. If you can show evidence or documentation showing

The idea is not to make this too strict and too have some reasonable defaults.

Copy link
Contributor

Choose a reason for hiding this comment

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

In Debian armhf is v7 with hardfloat see this (this is the reason for the existence of Rasbian which rebuilds as v6 for compat with RPi hardware). I believe at the time there was cross distro agreement on that as a baseline (at least Ubuntu and Fedora IIRC) for the ARM distros of the day.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think this default might need to change based on where it's being used -- for ARM-based images that don't specify a variant, I think v7 would be the safer choice/assumption, but for a user pulling images, they probably want to allow v6 if all they specify is "ARM".

Copy link
Member Author

Choose a reason for hiding this comment

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

@ijc @tianon Fair enough. I'll see if I can work out that detail correctly.

Copy link
Member Author

Choose a reason for hiding this comment

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

@tianon @ijc PTAL

@stevvooe stevvooe force-pushed the platform-selectors branch from e48c018 to f42ac4c Compare August 21, 2017 18:06
Copy link
Contributor

Choose a reason for hiding this comment

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

linux/s390x should also be in here, I'm not sure why it's not listed here on the go page.

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 am not sure if we'll even enforce this list. These are effectively the officially supported Go platforms, which is a subset of the platforms that might run containers. I'm not sure that this is necessary to maintain in this package.

Copy link
Member Author

Choose a reason for hiding this comment

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

@tophj-ibm I've added a few test cases for linux/s390x to ensure its covered. I'm going to structure this database a little more carefully to avoid these kinds of problems. I don't want this package to become an impediment to wider platform support!

@stevvooe stevvooe force-pushed the platform-selectors branch 2 times, most recently from 3a6de93 to 395c9b3 Compare August 22, 2017 20:58
@codecov-io
Copy link

codecov-io commented Aug 22, 2017

Codecov Report

Merging #1403 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1403   +/-   ##
=======================================
  Coverage   40.82%   40.82%           
=======================================
  Files          23       23           
  Lines        2920     2920           
=======================================
  Hits         1192     1192           
  Misses       1451     1451           
  Partials      277      277

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 52fbc5f...775f7ce. Read the comment docs.

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: slightly

Copy link
Contributor

Choose a reason for hiding this comment

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

minor nit, but should this be marked as TODO?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes.

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 not sure one wants to do this matching above of commonly used but not part of the OCI spec names for architectures.

I would suggest to simply just use the names from the spec and that's it. Otherwise you'd have to do the same of OSes too. darwin is now officially called macOS, for example. If you translate x86-64 to amd64 why not translate macOS to darwin?

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 can add a translation for macOS.

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'm not sure one wants to do this matching above of commonly used but not part of the OCI spec names for architectures.

I'd prefer a strict approach, but I think we can make everyone happy here because the sets (os/arch) are disjoint. To keep this nice property across projects, the normalization needs to be centralized.

Do you see an issue with this in the future?

Copy link
Contributor

Choose a reason for hiding this comment

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

I have to say that at time I find the mismatch between uname -m and Go architectures (and therefor OCI architectures) quite annoying, so I can see an argument for tools to accept both (and then internally translate to the canonical GOARCH/GOOS format). But I can also see an argument for keeping it simple and just use OCI names and leave it to the user to translate.

For now I don't see any issues in the future (I left my crystal ball at home) so if the general desire is to allow commonly used alternative arch/OS names to be used, centralising it in one place like this PR tries certainly a good idea.

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: syste -> system

Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence does not end

@stevvooe stevvooe force-pushed the platform-selectors branch 2 times, most recently from bfeeba3 to 26f88fd Compare August 30, 2017 23:07
Copy link
Contributor

Choose a reason for hiding this comment

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

We normalise (below) linux/arm into linux/arm/v7 but here we are normalizing linux/armhf into just linux/arm, which seems a bit non-normalysed to me.

IOW if the result of normalizeArch was actually normative (as I think it should be) then the assertion in the following should always be true:

foo := normalizeArch(input)
assert(foo == normalizeArch(foo))

but that doesn't appear to be the case when input == "linux/armhf"

Copy link
Contributor

Choose a reason for hiding this comment

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

TL;DR: I think you can ignore my previous comment.

I think I misread the code handling the "arm" case, that switch doesn't actually have the default case I thought it did so normalizeArch("arm") == "arm" as required.

(I'm also aware I was taking some liberties with the actual arguments, there should be split("/", foo) stuff sprinkled around in my examples to make them closer to actually working examples)

Copy link
Member Author

Choose a reason for hiding this comment

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

Just added a test case to ensure the round trip.

@stevvooe stevvooe force-pushed the platform-selectors branch from 26f88fd to 517b25b Compare August 31, 2017 23:35
Copy link
Member

@estesp estesp left a comment

Choose a reason for hiding this comment

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

this is looking good, IMO. The make vet error is the only CI issue.

Copy link
Member

Choose a reason for hiding this comment

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

the round trip addition has an issue from make vet:

platforms/platforms_test.go:198: wrong number of args for format in Fatalf call: 1 needed but 2 args

@stevvooe stevvooe force-pushed the platform-selectors branch 2 times, most recently from 58b29dc to 1a05466 Compare September 1, 2017 21:50
@stevvooe stevvooe added this to the containerd 1.0.0 milestone Sep 6, 2017
Copy link

Choose a reason for hiding this comment

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

architecture

Copy link

Choose a reason for hiding this comment

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

Why include the v7 case, since it doesn't change? Is it just for clarity, to assign variant in all non-default cases?

Copy link
Member Author

Choose a reason for hiding this comment

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

Mostly to prevent it going down other control flow paths.

Copy link

Choose a reason for hiding this comment

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

Since variant can also contain letters (e.g. v7), should you also normalize it to lowercase?

Copy link

Choose a reason for hiding this comment

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

Nit: platform's

Copy link

Choose a reason for hiding this comment

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

Nit: Closing ) after slashes

Copy link

Choose a reason for hiding this comment

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

One comment says the minimum requirement for a platform selector is the operating system, but the next paragraph says operating system or architecture, which matches the format specification. Remove the incorrect sentence and probably combine the two paragraphs into one.

Copy link

Choose a reason for hiding this comment

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

I think this needs a * for allowing multiple characters: ^[A-Za-z0-9_-]*$

Copy link
Member Author

Choose a reason for hiding this comment

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

... This was completely broken ...

For supporting selection of images and runtimes in the containerized
world, there is thin support for selecting objects by platform. This
package defines a syntax to display to users that can express specific
platforms in addition to wild cards for matching platforms.

The plan is to extend this to provide support for parsing flag
arguments and displaying platform types for images. This package will
also provide a configurable matcher to allow match of platforms against
arbitrary targets, invariant to the Go compilation.

The internals are based the OCI Image Spec model.

This changeset is being submitted for feedback on the approach before
this gets larger. Specifically, review the unit tests and raise any
concerns.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
@stevvooe stevvooe changed the title [WIP] platforms: define selectors for platforms platforms: define selectors for platforms Sep 9, 2017
@stevvooe
Copy link
Member Author

stevvooe commented Sep 9, 2017

Matcher support has been added and the tests have been updated accordingly.

PTAL

Copy link
Member

@estesp estesp left a comment

Choose a reason for hiding this comment

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

LGTM with two minor typos in comments and a comment that seems incorrect

Copy link
Member

Choose a reason for hiding this comment

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

minor typo: s/uxe/use

Copy link
Member

Choose a reason for hiding this comment

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

wouldn't if ok actually be a match? Unless I'm misunderstanding either the ok should be !ok or the comment should be "does match"

Copy link
Member

Choose a reason for hiding this comment

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

minor typo: s/mayn/many

Matching support is now implemented in the platforms package. The
`Parse` function now returns a matcher object that can be used to
match OCI platform specifications. We define this as an interface to
allow the creation of helpers oriented around platform selection.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
// While the OCI platform specifications provide a tool for components to
// specify structured information, user input typically doesn't need the full
// context and much can be inferred. To solve this problem, we introduced
// "specifiers". A specifier has the format `<os|arch>[/<arch>[/<variant>]]`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be <os[/<arch>[/<variant>]]|arch[/<variant>]>?

Unless I'm reading it incorrectly, it would currently match something like amd64/arm.

Copy link
Member Author

Choose a reason for hiding this comment

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

This isn't really an official grammar. The variant can never be expressed without OS and Arch. I think maybe this would work:

<os>|<arch>|<os>/<arch>/<variant>

Copy link
Contributor

Choose a reason for hiding this comment

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

Is variant optional in the last case?

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated.

Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM


// Parse parses the platform specifier syntax into a platform declaration.
//
// Platform specifiers are in the format <os|arch>[/<arch>[/<variant>]]. The
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above.

@crosbymichael
Copy link
Member

LGTM

Signed-off-by: Stephen J Day <stephen.day@docker.com>
@dmcgowan
Copy link
Member

LGTM

platform.OS = normalizeOS(platform.OS)
platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant)

// these fields are deprecated, remove them
Copy link
Member

Choose a reason for hiding this comment

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

@stevvooe I just noticed this comment (we were discussing these fields last week in context for Windows images (which may need an OSVersion to match the correct variant); Do you have a reference where these fields are marked deprecated? The spec doesn't mention that; https://github.com/opencontainers/image-spec/blob/v1.0.1/specs-go/v1/descriptor.go#L53-L59 (if they're deprecated, I can open a PR to mark them as such in the spec)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.