Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cmd/oci-image-tool/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ func (v *validateCmd) validatePath(name string) error {
return err
}

return nil
case typeConfig:
if err := schema.MediaTypeImageSerializationConfig.Validate(f); err != nil {
return err
}

return nil
}

Expand Down
33 changes: 33 additions & 0 deletions schema/config-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"description": "OpenContainer Config Specification",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://opencontainers.org/schema/image/config",
"type": "object",
"properties": {
"created": {
"type": "string",
"format": "date-time"
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 format too strict for "2015-10-31T22:22:56.015925234Z"?

Copy link
Contributor

Choose a reason for hiding this comment

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

On Mon, May 23, 2016 at 01:51:33PM -0700, Vincent Batts wrote:

  • "created": {
  •  "type": "string",
    
  •  "format": "date-time"
    

is this format too strict for "2015-10-31T22:22:56.015925234Z"?

The v4 JSON Schema RFC doesn't mention date-time 1, but it's listed
here 2 referencing RFC 3339, section 5.6. And your string is
compatible with that 3.

},
"author": {
"type": "string"
},
"architecture": {
"type": "string"
},
"os": {
"type": "string"
},
"config": {
"$ref": "defs-config.json#/definitions/config"
Copy link
Contributor

Choose a reason for hiding this comment

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

This is probably outside the scope of this PR: let's make sure we have some negative examples of the config to ensure that the validation is working with these recursively definitions. I know I had some issues with this when I first started experimenting with the validators.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍 I have this on my radar, as well as the support for providing the erroneous line number in case of validation failure.

Copy link
Contributor

Choose a reason for hiding this comment

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

@s-urbaniak I've filed #83. Feel free to expand on anything I've missed.

Copy link
Member

Choose a reason for hiding this comment

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

what is recursive here?

Copy link
Contributor

Choose a reason for hiding this comment

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

@vbatts config-schema.json pulls in defs-config.json. During my experimentation, I was not convinced this was working correctly. Either way, we should have negative examples to confirm this and ensure that bad schemas are actually being rejected.

Copy link
Member

Choose a reason for hiding this comment

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

ah, so. Not working is an understandable concern. I just did not see recursion. :-)

},
"rootfs": {
"$ref": "defs-config.json#/definitions/rootfs"
},
"history": {
"type": "array",
"items": {
"$ref": "defs-config.json#/definitions/history"
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I was about to comment on the lack of an array of requires, but then the ./serialization.md doesn't show much for required fields ...

}
}
84 changes: 84 additions & 0 deletions schema/defs-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"description": "Definitions particular to OpenContainer Config Specification",
"definitions": {
"config": {
"type": "object",
"properties": {
"User": {
"type": "string"
},
"Memory": {
"$ref": "defs.json#/definitions/int64"
},
"MemorySwap": {
"$ref": "defs.json#/definitions/int64"
},
"CpuShares": {
"$ref": "defs.json#/definitions/int64"
},
"ExposedPorts": {
"$ref": "defs.json#/definitions/mapStringObject"
},
"Env": {
"type": "array",
"items": {
"type": "string"
}
},
"Entrypoint": {
"type": "array",
"items": {
"type": "string"
}
},
"Cmd": {
"type": "array",
"items": {
"type": "string"
}
},
"Volumes": {
"$ref": "defs.json#/definitions/mapStringObject"
},
"WorkingDir": {
"type": "string"
}
}
},
"rootfs": {
"type": "object",
"properties": {
"diff_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"layers": {
"type": "string"
}
}
},
"history": {
"type": "object",
"properties": {
"created": {
"type": "string",
"format": "date-time"
},
"author": {
"type": "string"
},
"created_by": {
"type": "string"
},
"comment": {
"type": "string"
},
"empty_layer": {
"type": "boolean"
}
}
}
}
}
8 changes: 8 additions & 0 deletions schema/defs.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@
}
}
},
"mapStringObject": {
"type": "object",
"patternProperties": {
".{1,}": {
"type": "object"
}
}
},
"UID": {
"$ref": "#/definitions/uint32"
},
Expand Down
54 changes: 41 additions & 13 deletions schema/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,34 @@ func _escFSMustString(useLocal bool, name string) string {

var _escData = map[string]*_escFile{

"/config-schema.json": {
local: "config-schema.json",
size: 707,
modtime: 1463700693,
compressed: `
H4sIAAAJbogA/5SRPW7DMAyF5/oUhpOxjjp0ytoDdOgJVJmKGcCiQDJDUPju1U/c2kvhLobx+L73JOqr
adtuAHGMUZFCd2679wjhjYJaDMBt+vN4aT8iOPTobHE9Z+woboTJZmRUjWdjrkKhr+qJ+GIGtl77l1dT
tUPlcFgQSQylNre0ScGq2+BkL2Bc6a+k3iNklj6v4LRqkVMCK4KkSb5O0hyDVRh+hBUqyhhqXNE98WQ1
T4aE9IoTdGU2V0tnbzoS/xG1dbMbUdPhbgx7GZK9zscuVu4jgy+HBy99HZ/yKxxMUjBgfi1ZdrjJYiL1
8v+sB7fJGlGU+F7CnlZ3sMz2/rvrtJhp3bi7c8l/cHOzfOdmbr4DAAD//1EkCUvDAgAA
`,
},

"/defs-config.json": {
local: "defs-config.json",
size: 1755,
modtime: 1463700704,
compressed: `
H4sIAAAJbogA/7xUzc7TMBA8N09hBY6BXhAHri1HVKQIOFZusm63xF5rvQEi1HfHSauS/qRKKV8PVeOx
Z2bXY/t3olRaQigYvSC59INK52DQYTsKymsWLOpKsxJSCw9uRk40OmAVvwyuVe6hQIOF7vjZXvCoEAVb
jwgW3fLjOCLSeGgNabWFQjpqh3smD9EXQm91xL8E4BOkpxGE0a3T49Qu+8v7BJa4OWe+ZjAtMxYb3m4D
uVfTXt1TdPL+3S29/Kf2/09z5ut8o/ms5YckP/7yFKD8TCz3qlrt825DF/toruu7H0NpaGbdpFl/CgXs
eRk38otWA6bCjafY9vO9Z7Z8vulXqmp797EYFeA34u9xyRzH36qk/3/QSplITHjkZpdozBLLiy5ffnsr
3QAP+o7rf4NBTh+YuzegYNACg8frUEeWTCYRNcRWS5d+JL0RtHA9YF3Lhv7pyTzUs1xdPJuj2GQtDN/Q
W1SwXppll8oQfUVUgXaDqSTtb5f8CQAA//8Cok052wYAAA==
`,
},

"/defs-image.json": {
local: "defs-image.json",
size: 3100,
Expand All @@ -221,20 +249,20 @@ dwN3Or48T12UYhfH478BrlWPMiuzfgUAAP//VjUNyBwMAAA=

"/defs.json": {
local: "defs.json",
size: 3044,
modtime: 1463695223,
size: 3193,
modtime: 1463700693,
compressed: `
H4sIAAAJbogA/6xWT3PaPhC98yk8/H5H2tiybENvnaZ/csiEmUxPnR5cs4BakFRZ7jTN8N0rGWMse3Ew
5QBYu9r3dt+usJ5HnjdeQJ4pJjUTfPzGG9/CknFmV7lX5LDw9FqJYrUWhTaP4D1I4O8E1ynjoLxHCRlb
siwtwyd7vBrA4FkKY2RcT+uVWesnCZbN2GEFqowsHVsTuy22xvcqINOjOf1dmQOSlMbdpEYO4qHQIUli
DNzaO/AhGQpPAprQaRhTjKN2dohiOpRoRkgYJsQP42lEkyT2fR9hRHY51MUF3cF4SBR1cAf3BgOOoyjs
Qg/uCwZNyYzO4oTMuviD24HhB1NK44RSPwkTfxZFBBM/iOfC4qomoeDwsDSGL5XBq12l+38F1jv+76Zx
4G4qyeuNuwkefaiGF5tNY3f19BXR4poZGmWvmmGuFeOr4RkeOPbx181pm8rHEnb/jY2S+PYdMn2cJJlq
kz+fKyFBaQZ5I8i4Xz8Hk51j6ith1Pw9JPX57raZyOkOmbPlBH68NPCtUunTw9LE55gEqXUfFWAatq2q
cSqbD1phxbcX/UJKXFOX5wPbwDzVa4yhGXfY/57/elnAVvIOwCchfjQR5IkpkW5SPWx1CdjcG5lW+Xk4
WNZtNHDK7wGzOr0wxBWfFeSqM1UqjDLe3d6nUrZO8akGrEWundPSQ9k8MW3JssMl6xpgOfsDF6KgityL
gutz1MhFobIzqfsH0txTNeNpdU/9Zzgh3StqL9Q5I16N37B/53pKFfwsmIKF87Jyap50RG2Tu++hkf3s
Rn8DAAD//2VgiEzkCwAA
H4sIAAAJbogA/7RWTXPaMBC98ys8tEfa2PIX9NYp/cghAzOZnjo9uGYBtSCpstxpmuG/VzLGWPZiMKWH
JPau9r23T6tYzwPHGS4gSyUVinI2fOMMp7CkjJq3zMkzWDhqLXm+WvNc6UdwZgLYO85UQhlI51FASpc0
TYry0R6vAtB4hkIHKVPj6k2/qycBhk3HYQWyqCwSW127zbc698oj42M4+V2GPRIXwd2oQvaivtA+iSMM
3MRb8D7pC0+8IA7GfhRgHFWyRRQFfYkmhPh+TFw/GodBHEeu6yKMyCqLOr9idzAeEoYt3N57gwFHYei3
oXvvCwYdkEkwiWIyaeP33g4M3xsHQRQHgRv7sTsJQ4KZ70VzbnBlnZAzmC114EsZcKpUkX4pwWSHL+5q
B+6utLxauBvh1YduWL7Z1FaXT18RL26pUDt7U4WZkpSt+is8cOzrb6tpm4jHAnb/Gxsl/u07pOo4SSJR
Wj+bSy5AKgpZrUinXz97o50V6mphUP/bEjXbU/9nUSXWGVGf76d1IafHRh94q/DjtYVvpUyeZktdn2EW
JCZ9dIAq2Da6xqmMHrTDkm9v/ZWU+EbbPB/oBuaJWmMM9brD+vfs13kDG+ItgE+c/6gjiBNTImxRHWxV
C9hh1DatsstwMNVNNLDa7wAzPp0Z4pLPGHLTmSocRhnvpw+JEI1/Lac2YM0zZZ2WDsr6iWlalh5ufrcA
y+gfuBIFdeSB50xd4kbGc5leSN09kPryrChLysvzP8NxYd+bO6EuGfFy/Pp9MqoplfAzpxIW1hfU6nnU
MrVJbn8cB+ZnN/gbAAD//0JyEpx5DAAA
`,
},

Expand Down
7 changes: 4 additions & 3 deletions schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
MediaTypeManifest Validator = `application/vnd.oci.image.manifest.v1+json`
MediaTypeManifestList Validator = `application/vnd.oci.image.manifest.list.v1+json`
MediaTypeImageSerialization unimplemented = `application/vnd.oci.image.serialization.rootfs.tar.gzip`
MediaTypeImageSerializationConfig unimplemented = `application/vnd.oci.image.serialization.config.v1+json`
MediaTypeImageSerializationConfig Validator = `application/vnd.oci.image.serialization.config.v1+json`
MediaTypeImageSerializationCombined unimplemented = `application/vnd.oci.image.serialization.combined.v1+json`
)

Expand All @@ -32,8 +32,9 @@ var (

// specs maps OCI schema media types to schema files.
specs = map[Validator]string{
MediaTypeManifest: "image-manifest-schema.json",
MediaTypeManifestList: "manifest-list-schema.json",
MediaTypeManifest: "image-manifest-schema.json",
MediaTypeManifestList: "manifest-list-schema.json",
MediaTypeImageSerializationConfig: "config-schema.json",
}
)

Expand Down
16 changes: 14 additions & 2 deletions schema/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,17 @@ var (
errFormatInvalid = errors.New("format: invalid")
)

func TestValidateManifest(t *testing.T) {
validate(t, "../manifest.md")
}

func TestValidateSerialization(t *testing.T) {
validate(t, "../serialization.md")
}

// TODO(sur): include examples from all specification files
func TestSpecExamples(t *testing.T) {
m, err := os.Open("../manifest.md")
func validate(t *testing.T, name string) {
m, err := os.Open(name)
if err != nil {
t.Fatal(err)
}
Expand All @@ -46,6 +54,10 @@ func TestSpecExamples(t *testing.T) {
}

for _, example := range examples {
if example.Err == errFormatInvalid && example.Mediatype == "" { // ignore
continue
}

if example.Err != nil {
printFields(t, "error", example.Mediatype, example.Title, example.Err)
t.Error(err)
Expand Down
2 changes: 1 addition & 1 deletion serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ This specification uses the following terms:

Here is an example image JSON file:

```
```json,title=Image%20JSON&mediatype=application/vnd.oci.image.serialization.config.v1%2Bjson
{
"created": "2015-10-31T22:22:56.015925234Z",
"author": "Alyssa P. Hacker &[email protected]&gt",
Expand Down