Add schema2 manifest and schema2 config, along with tests

This commit is contained in:
Joseph Schorr 2018-04-16 15:38:13 +03:00
parent 4bd70eab3c
commit 52b12131f7
6 changed files with 642 additions and 0 deletions

View file

View file

@ -0,0 +1,129 @@
import json
import pytest
from image.docker.schema2.config import MalformedSchema2Config, DockerSchema2Config
@pytest.mark.parametrize('json_data', [
'',
'{}',
"""
{
"unknown": "key"
}
""",
])
def test_malformed_configs(json_data):
with pytest.raises(MalformedSchema2Config):
DockerSchema2Config(json_data)
CONFIG_BYTES = json.dumps({
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": False,
"AttachStdout": False,
"AttachStderr": False,
"Tty": False,
"OpenStdin": False,
"StdinOnce": False,
"Env": [
"HTTP_PROXY=http:\/\/localhost:8080",
"http_proxy=http:\/\/localhost:8080",
"PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin"
],
"Cmd": [
"sh"
],
"Image": "",
"Volumes": None,
"WorkingDir": "",
"Entrypoint": None,
"OnBuild": None,
"Labels": {
}
},
"container": "b7a43694b435c8e9932615643f61f975a9213e453b15cd6c2a386f144a2d2de9",
"container_config": {
"Hostname": "b7a43694b435",
"Domainname": "",
"User": "",
"AttachStdin": True,
"AttachStdout": True,
"AttachStderr": True,
"Tty": True,
"OpenStdin": True,
"StdinOnce": True,
"Env": [
"HTTP_PROXY=http:\/\/localhost:8080",
"http_proxy=http:\/\/localhost:8080",
"PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin"
],
"Cmd": [
"sh"
],
"Image": "jschorr\/somerepo",
"Volumes": None,
"WorkingDir": "",
"Entrypoint": None,
"OnBuild": None,
"Labels": {
}
},
"created": "2018-04-16T10:41:19.079522722Z",
"docker_version": "17.09.0-ce",
"history": [
{
"created": "2018-04-03T18:37:09.284840891Z",
"created_by": "\/bin\/sh -c #(nop) ADD file:9e4ca21cbd24dc05b454b6be21c7c639216ae66559b21ba24af0d665c62620dc in \/ "
},
{
"created": "2018-04-03T18:37:09.613317719Z",
"created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
"empty_layer": True
},
{
"created": "2018-04-16T10:37:44.418262777Z",
"created_by": "sh"
},
{
"created": "2018-04-16T10:41:19.079522722Z",
"created_by": "sh"
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:3e596351c689c8827a3c9635bc1083cff17fa4a174f84f0584bd0ae6f384195b",
"sha256:4552be273c71275a88de0b8c8853dcac18cb74d5790f5383d9b38d4ac55062d5",
"sha256:1319c76152ca37fbeb7fb71e0ffa7239bc19ffbe3b95c00417ece39d89d06e6e"
]
}
})
def test_valid_config():
config = DockerSchema2Config(CONFIG_BYTES)
history = list(config.history)
assert len(history) == 4
assert not history[0].is_empty
assert history[1].is_empty
assert history[0].created_datetime.year == 2018
assert history[1].command == '/bin/sh -c #(nop) CMD ["sh"]'
assert history[2].command == 'sh'
for index, history_entry in enumerate(history):
v1_compat = config.build_v1_compatibility(index, 'somev1id', 'someparentid')
assert v1_compat['id'] == 'somev1id'
assert v1_compat['parent'] == 'someparentid'
if index == 3:
assert v1_compat['container_config'] == config._parsed['container_config']
else:
assert 'Hostname' not in v1_compat['container_config']
assert v1_compat['container_config']['Cmd'] == history_entry.command

View file

@ -0,0 +1,87 @@
import json
import pytest
from app import docker_v2_signing_key
from image.docker.schema1 import DockerSchema1ManifestBuilder
from image.docker.schema2.manifest import MalformedSchema2Manifest, DockerSchema2Manifest
from image.docker.schema2.test.test_config import CONFIG_BYTES
@pytest.mark.parametrize('json_data', [
'',
'{}',
"""
{
"unknown": "key"
}
""",
])
def test_malformed_manifests(json_data):
with pytest.raises(MalformedSchema2Manifest):
DockerSchema2Manifest(json_data)
MANIFEST_BYTES = json.dumps({
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip",
"size": 1234,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736",
"urls": ['http://some/url'],
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 32654,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
},
],
})
def test_valid_manifest():
manifest = DockerSchema2Manifest(MANIFEST_BYTES)
assert manifest.config.size == 7023
assert str(manifest.config.digest) == 'sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7'
assert len(manifest.layers) == 4
assert manifest.layers[0].is_remote
assert manifest.layers[0].size == 1234
assert str(manifest.layers[0].digest) == 'sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736'
assert manifest.layers[0].urls
assert manifest.leaf_layer == manifest.layers[3]
assert not manifest.leaf_layer.is_remote
assert manifest.leaf_layer.size == 73109
def test_build_schema1():
manifest = DockerSchema2Manifest(MANIFEST_BYTES)
builder = DockerSchema1ManifestBuilder('somenamespace', 'somename', 'sometag')
manifest.populate_schema1_builder(builder, lambda digest: CONFIG_BYTES)
schema1 = builder.build(docker_v2_signing_key)
assert len(schema1.layers) == len(manifest.layers)
assert set(schema1.image_ids) == set([l.v1_id for l in manifest.layers_with_v1_ids])
assert set(schema1.parent_image_ids) == set([l.v1_parent_id for l in manifest.layers_with_v1_ids if l.v1_parent_id])
manifest_layers = list(manifest.layers_with_v1_ids)
for index, layer in enumerate(schema1.layers):
assert layer.digest == manifest_layers[index].layer.digest
assert layer.v1_metadata.image_id == manifest_layers[index].v1_id
assert layer.v1_metadata.parent_image_id == manifest_layers[index].v1_parent_id