Skip to content

Commit

Permalink
schema: Add schema and test for artifact manifest
Browse files Browse the repository at this point in the history
Signed-off-by: Sajay Antony <sajaya@microsoft.com>
  • Loading branch information
sajayantony committed Sep 29, 2022
1 parent f9ca252 commit 1760050
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 0 deletions.
29 changes: 29 additions & 0 deletions schema/artifact-manifest-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"description": "OpenContainer Artifact Manifest Specification",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://opencontainers.org/schema/artifact",
"type": "object",
"properties": {
"mediaType": {
"description": "the mediatype of the referenced object",
"$ref": "defs-descriptor.json#/definitions/mediaType"
},
"artifactType": {
"description": "The IANA mediatype of the referenced objects properties",
"$ref": "defs-descriptor.json#/definitions/mediaType"
},
"blobs": {
"type": "array",
"items": {
"$ref": "content-descriptor.json"
}
},
"subject": {
"$ref": "content-descriptor.json"
},
"annotations": {
"id": "https://opencontainers.org/schema/image/manifest/annotations",
"$ref": "defs-descriptor.json#/definitions/annotations"
}
}
}
148 changes: 148 additions & 0 deletions schema/artifact_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// Copyright 2016 The Linux Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package schema_test

import (
"fmt"
"strings"
"testing"

"github.com/opencontainers/image-spec/schema"
)

func TestArtifact(t *testing.T) {
for i, tt := range []struct {
manifest string
fail bool
}{
// expected failure: mediaType does not match pattern
{
manifest: `
{
"mediaType": "invalid",
"artifactType": "application/example",
"blobs": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 148,
"digest": "sha256:c57089565e894899735d458f0fd4bb17a0f1e0df8d72da392b85c9b35ee777cd"
}
]
}
`,
fail: true,
},

// expected failure: invalid artifact mediaType
{
manifest: `
{
"mediaType": "application/vnd.oci.artifact.manifest.v1+json",
"artifactType": "invalid",
"blobs": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": "148",
"digest": "sha256:c57089565e894899735d458f0fd4bb17a0f1e0df8d72da392b85c9b35ee777cd"
}
]
}
`,
fail: true,
},

// expected failure: blob[0].size is a string, expected integer
{
manifest: `
{
"mediaType": "application/vnd.oci.artifact.manifest.v1+json",
"artifactType": "application/example",
"blobs": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": "148",
"digest": "sha256:c57089565e894899735d458f0fd4bb17a0f1e0df8d72da392b85c9b35ee777cd"
}
]
}
`,
fail: true,
},

// expected failure: subject: size is required
{
manifest: `
{
"mediaType": "application/vnd.oci.artifact.manifest.v1+json",
"artifactType": "application/example",
"subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b"
},
"annotations": {
"key1": "value1",
"key2": "value2"
}
}
`,
fail: true,
},

// valid manifest with optional fields
{
manifest: `
{
"mediaType": "application/vnd.oci.artifact.manifest.v1+json",
"artifactType": "application/example",
"blobs": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 675598,
"digest": "sha256:9d3dd9504c685a304985025df4ed0283e47ac9ffa9bd0326fddf4d59513f0827"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 156,
"digest": "sha256:2b689805fbd00b2db1df73fae47562faac1a626d5f61744bfe29946ecff5d73d"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 148,
"digest": "sha256:c57089565e894899735d458f0fd4bb17a0f1e0df8d72da392b85c9b35ee777cd"
}
],
"subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 1470,
"digest": "sha256:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b"
},
"annotations": {
"key1": "value1",
"key2": "value2"
}
}
`,
fail: false,
},
} {
r := strings.NewReader(tt.manifest)
err := schema.ValidatorMediaTypeArtifact.Validate(r)

if got := err != nil; tt.fail != got {
t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err)
fmt.Println(tt.manifest)
}
}
}
2 changes: 2 additions & 0 deletions schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
ValidatorMediaTypeImageIndex Validator = v1.MediaTypeImageIndex
ValidatorMediaTypeImageConfig Validator = v1.MediaTypeImageConfig
ValidatorMediaTypeImageLayer unimplemented = v1.MediaTypeImageLayer
ValidatorMediaTypeArtifact Validator = v1.MediaTypeArtifactManifest
)

var (
Expand Down Expand Up @@ -68,6 +69,7 @@ var (
ValidatorMediaTypeManifest: "https://opencontainers.org/schema/image/image-manifest-schema.json",
ValidatorMediaTypeImageIndex: "https://opencontainers.org/schema/image/image-index-schema.json",
ValidatorMediaTypeImageConfig: "https://opencontainers.org/schema/image/config-schema.json",
ValidatorMediaTypeArtifact: "https://opencontainers.org/schema/artifact-manifest-schema.json",
}
)

Expand Down
4 changes: 4 additions & 0 deletions schema/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ func TestValidateConfig(t *testing.T) {
validate(t, "../config.md")
}

func TestValidateArtifactManifest(t *testing.T) {
validate(t, "../artifact.md")
}

func TestSchemaFS(t *testing.T) {
expectedSchemaFileNames, err := filepath.Glob("*.json")
if err != nil {
Expand Down
20 changes: 20 additions & 0 deletions schema/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var mapValidate = map[Validator]validateFunc{
ValidatorMediaTypeDescriptor: validateDescriptor,
ValidatorMediaTypeImageIndex: validateIndex,
ValidatorMediaTypeManifest: validateManifest,
ValidatorMediaTypeArtifact: validateArtifact,
}

// ValidationError contains all the errors that happened during validation.
Expand Down Expand Up @@ -250,3 +251,22 @@ func checkPlatform(OS string, Architecture string) {
}
fmt.Printf("warning: operating system %q of the bundle is not supported yet.\n", OS)
}

func validateArtifact(r io.Reader) error {
header := v1.Artifact{}

buf, err := io.ReadAll(r)
if err != nil {
return errors.Wrapf(err, "error reading the io stream")
}

err = json.Unmarshal(buf, &header)
if err != nil {
return errors.Wrap(err, "manifest format mismatch")
}

if header.MediaType != string(v1.MediaTypeArtifactManifest) {
fmt.Printf("warning: Artifact has an unknown media type: %s\n", header.MediaType)
}
return nil
}

0 comments on commit 1760050

Please sign in to comment.