Skip to content

Commit

Permalink
Merge pull request #809 from cpuguy83/image-platform
Browse files Browse the repository at this point in the history
Embed platform fields in Image spec
  • Loading branch information
vbatts committed Jul 29, 2021
2 parents 91bc345 + 170393e commit fe0a249
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 36 deletions.
18 changes: 18 additions & 0 deletions config.md
Expand Up @@ -110,6 +110,24 @@ Note: Any OPTIONAL field MAY also be set to null, which is equivalent to being a
The name of the operating system which the image is built to run on.
Configurations SHOULD use, and implementations SHOULD understand, values listed in the Go Language document for [`GOOS`][go-environment].

- **os.version** *string*, OPTIONAL

This OPTIONAL property specifies the version of the operating system targeted by the referenced blob.
Implementations MAY refuse to use manifests where `os.version` is not known to work with the host OS version.
Valid values are implementation-defined. e.g. `10.0.14393.1066` on `windows`.

- **os.features** *array of strings*, OPTIONAL

This OPTIONAL property specifies an array of strings, each specifying a mandatory OS feature.
When `os` is `windows`, image indexes SHOULD use, and implementations SHOULD understand the following values:

- `win32k`: image requires `win32k.sys` on the host (Note: `win32k.sys` is missing on Nano Server)

- **variant** *string*, OPTIONAL

The variant of the specified CPU architecture.
Configurations SHOULD use, and implementations SHOULD understand, `variant` values listed in the [Platform Variants](image-index.md#platform-variants) table.

- **config** *object*, OPTIONAL

The execution parameters which SHOULD be used as a base when running a container using the image.
Expand Down
18 changes: 12 additions & 6 deletions conversion.md
Expand Up @@ -46,17 +46,23 @@ These fields all affect the `annotations` of the runtime configuration, and are
| ------------------- | --------------- | ----- |
| `os` | `annotations` | 1,2 |
| `architecture` | `annotations` | 1,3 |
| `author` | `annotations` | 1,4 |
| `created` | `annotations` | 1,5 |
| `variant` | `annotations` | 1,4 |
| `os.version` | `annotations` | 1,5 |
| `os.features` | `annotations` | 1,6 |
| `author` | `annotations` | 1,7 |
| `created` | `annotations` | 1,8 |
| `Config.Labels` | `annotations` | |
| `Config.StopSignal` | `annotations` | 1,6 |
| `Config.StopSignal` | `annotations` | 1,9 |

1. If a user has explicitly specified this annotation with `Config.Labels`, then the value specified in this field takes lower [precedence](#annotations) and the converter MUST instead use the value from `Config.Labels`.
2. The value of this field MUST be set as the value of `org.opencontainers.image.os` in `annotations`.
3. The value of this field MUST be set as the value of `org.opencontainers.image.architecture` in `annotations`.
4. The value of this field MUST be set as the value of `org.opencontainers.image.author` in `annotations`.
5. The value of this field MUST be set as the value of `org.opencontainers.image.created` in `annotations`.
6. The value of this field MUST be set as the value of `org.opencontainers.image.stopSignal` in `annotations`.
4. The value of this field MUST be set as the value of `org.opencontainers.image.variant` in `annotations`.
5. The value of this field MUST be set as the value of `org.opencontainers.image.os.version` in `annotations`.
6. The value of this field MUST be set as the value of `org.opencontainers.image.os.features` in `annotations`.
7. The value of this field MUST be set as the value of `org.opencontainers.image.author` in `annotations`.
8. The value of this field MUST be set as the value of `org.opencontainers.image.created` in `annotations`.
9. The value of this field MUST be set as the value of `org.opencontainers.image.stopSignal` in `annotations`.

## Parsed Fields

Expand Down
21 changes: 12 additions & 9 deletions image-index.md
Expand Up @@ -76,15 +76,7 @@ For the media type(s) that this document is compatible with, see the [matrix][ma
- **`variant`** *string*

This OPTIONAL property specifies the variant of the CPU.
Image indexes SHOULD use, and implementations SHOULD understand, values listed in the following table.
When the variant of the CPU is not listed in the table, values are implementation-defined and SHOULD be submitted to this specification for standardization.

| ISA/ABI | `architecture` | `variant` |
|-----------------|----------------|-------------|
| ARM 32-bit, v6 | `arm` | `v6` |
| ARM 32-bit, v7 | `arm` | `v7` |
| ARM 32-bit, v8 | `arm` | `v8` |
| ARM 64-bit, v8 | `arm64` | `v8` |
Image indexes SHOULD use, and implementations SHOULD understand, `variant` values listed in the [Platform Variants](#platform-variants) table.

- **`features`** *array of strings*

Expand All @@ -97,6 +89,17 @@ For the media type(s) that this document is compatible with, see the [matrix][ma

See [Pre-Defined Annotation Keys](annotations.md#pre-defined-annotation-keys).

## Platform Variants

When the variant of the CPU is not listed in the table, values are implementation-defined and SHOULD be submitted to this specification for standardization.

| ISA/ABI | `architecture` | `variant` |
|-----------------|----------------|-------------|
| ARM 32-bit, v6 | `arm` | `v6` |
| ARM 32-bit, v7 | `arm` | `v7` |
| ARM 32-bit, v8 | `arm` | `v8` |
| ARM 64-bit, v8 | `arm64` | `v8` |

## Example Image Index

*Example showing a simple image index pointing to image manifests for two platforms:*
Expand Down
12 changes: 12 additions & 0 deletions schema/config-schema.json
Expand Up @@ -14,9 +14,21 @@
"architecture": {
"type": "string"
},
"variant": {
"type": "string"
},
"os": {
"type": "string"
},
"os.version": {
"type": "string"
},
"os.features": {
"type": "array",
"items": {
"type": "string"
}
},
"config": {
"type": "object",
"properties": {
Expand Down
20 changes: 19 additions & 1 deletion schema/config_test.go
Expand Up @@ -39,6 +39,23 @@ func TestConfig(t *testing.T) {
"type": "layers"
}
}
`,
fail: true,
},
// expected failure: field "variant" has numeric value, must be string
{
config: `
{
"architecture": "arm64",
"variant": 123,
"os": "linux",
"rootfs": {
"diff_ids": [
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
],
"type": "layers"
}
}
`,
fail: true,
},
Expand Down Expand Up @@ -140,7 +157,8 @@ func TestConfig(t *testing.T) {
{
"created": "2015-10-31T22:22:56.015925234Z",
"author": "Alyssa P. Hacker <alyspdev@example.com>",
"architecture": "amd64",
"architecture": "arm64",
"variant": "v8",
"os": "linux",
"config": {
"User": "1:1",
Expand Down
36 changes: 18 additions & 18 deletions schema/fs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 29 additions & 2 deletions schema/validator.go
Expand Up @@ -23,7 +23,7 @@ import (
"regexp"

digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/xeipuuv/gojsonschema"
)
Expand Down Expand Up @@ -168,6 +168,7 @@ func validateIndex(r io.Reader) error {
}
if manifest.Platform != nil {
checkPlatform(manifest.Platform.OS, manifest.Platform.Architecture)
checkArchitecture(manifest.Platform.Architecture, manifest.Platform.Variant)
}

}
Expand All @@ -189,6 +190,7 @@ func validateConfig(r io.Reader) error {
}

checkPlatform(header.OS, header.Architecture)
checkArchitecture(header.Architecture, header.Variant)

envRegexp := regexp.MustCompile(`^[^=]+=.*$`)
for _, e := range header.Config.Env {
Expand All @@ -200,6 +202,31 @@ func validateConfig(r io.Reader) error {
return nil
}

func checkArchitecture(Architecture string, Variant string) {
validCombins := map[string][]string{
"arm": {"", "v6", "v7", "v8"},
"arm64": {"", "v8"},
"386": {""},
"amd64": {""},
"ppc64": {""},
"ppc64le": {""},
"mips64": {""},
"mips64le": {""},
"s390x": {""},
}
for arch, variants := range validCombins {
if arch == Architecture {
for _, variant := range variants {
if variant == Variant {
return
}
}
fmt.Printf("warning: combination of architecture %q and variant %q is not valid.\n", Architecture, Variant)
}
}
fmt.Printf("warning: architecture %q is not supported yet.\n", Architecture)
}

func checkPlatform(OS string, Architecture string) {
validCombins := map[string][]string{
"android": {"arm"},
Expand All @@ -219,7 +246,7 @@ func checkPlatform(OS string, Architecture string) {
return
}
}
fmt.Printf("warning: combination of %q and %q is invalid.\n", OS, Architecture)
fmt.Printf("warning: combination of os %q and architecture %q is invalid.\n", OS, Architecture)
}
}
fmt.Printf("warning: operating system %q of the bundle is not supported yet.\n", OS)
Expand Down
11 changes: 11 additions & 0 deletions specs-go/v1/config.go
Expand Up @@ -89,9 +89,20 @@ type Image struct {
// Architecture is the CPU architecture which the binaries in this image are built to run on.
Architecture string `json:"architecture"`

// Variant is the variant of the specified CPU architecture which image binaries are intended to run on.
Variant string `json:"variant,omitempty"`

// OS is the name of the operating system which the image is built to run on.
OS string `json:"os"`

// OSVersion is an optional field specifying the operating system
// version, for example on Windows `10.0.14393.1066`.
OSVersion string `json:"os.version,omitempty"`

// OSFeatures is an optional field specifying an array of strings,
// each listing a required OS feature (for example on Windows `win32k`).
OSFeatures []string `json:"os.features,omitempty"`

// Config defines the execution parameters which should be used as a base when running a container using the image.
Config ImageConfig `json:"config,omitempty"`

Expand Down

0 comments on commit fe0a249

Please sign in to comment.