def test_lookup_manifest_child_tag(initialized_db): repository = create_repository("devtable", "newrepo", None) manifest, manifest_impl = create_manifest_for_testing(repository) # Mark the hidden tag as dead. hidden_tag = Tag.get(manifest=manifest, hidden=True) hidden_tag.lifetime_end_ms = hidden_tag.lifetime_start_ms hidden_tag.save() # Ensure the manifest cannot currently be looked up, as it is not pointed to by an alive tag. assert lookup_manifest(repository, manifest.digest) is None assert lookup_manifest(repository, manifest.digest, allow_dead=True) is not None # Populate a manifest list. list_builder = DockerSchema2ManifestListBuilder() list_builder.add_manifest(manifest_impl, "amd64", "linux") manifest_list = list_builder.build() # Write the manifest list, which should also write the manifests themselves. created_tuple = get_or_create_manifest(repository, manifest_list, storage) assert created_tuple is not None # Since the manifests are not yet referenced by a tag, they cannot be found. assert lookup_manifest(repository, manifest.digest) is None assert lookup_manifest(repository, manifest_list.digest) is None # Unless we ask for "dead" manifests. assert lookup_manifest(repository, manifest.digest, allow_dead=True) is not None assert lookup_manifest(repository, manifest_list.digest, allow_dead=True) is not None
def test_builder(): existing = DockerSchema2ManifestList(Bytes.for_string_or_unicode(MANIFESTLIST_BYTES)) builder = DockerSchema2ManifestListBuilder() for index, manifest in enumerate(existing.manifests(retriever)): builder.add_manifest(manifest.manifest_obj, "amd64", "os") built = builder.build() assert len(built.manifests(retriever)) == 2
def test_invalid_manifestlist(): # Build a manifest list with a schema 1 manifest of the wrong architecture. builder = DockerSchema1ManifestBuilder("foo", "bar", "baz") builder.add_layer("sha:2356", '{"id": "foo"}') manifest = builder.build().unsigned() listbuilder = DockerSchema2ManifestListBuilder() listbuilder.add_manifest(manifest, "amd32", "linux") manifestlist = listbuilder.build() retriever = ContentRetrieverForTesting() retriever.add_digest(manifest.digest, manifest.bytes.as_encoded_str()) with pytest.raises(MismatchManifestException): manifestlist.validate(retriever)
def test_derived_image_for_manifest_list(oci_model): # Clear all existing derived storage. DerivedStorageForImage.delete().execute() # Create a config blob for testing. config_json = json.dumps({ 'config': {}, "rootfs": { "type": "layers", "diff_ids": [] }, "history": [ { "created": "2018-04-03T18:37:09.284840891Z", "created_by": "do something", }, ], }) app_config = {'TESTING': True} repository_ref = oci_model.lookup_repository('devtable', 'simple') with upload_blob(repository_ref, storage, BlobUploadSettings(500, 500, 500)) as upload: upload.upload_chunk(app_config, BytesIO(config_json)) blob = upload.commit_to_blob(app_config) # Create the manifest in the repo. builder = DockerSchema2ManifestBuilder() builder.set_config_digest(blob.digest, blob.compressed_size) builder.add_layer(blob.digest, blob.compressed_size) amd64_manifest = builder.build() oci_model.create_manifest_and_retarget_tag(repository_ref, amd64_manifest, 'submanifest', storage) # Create a manifest list, pointing to at least one amd64+linux manifest. builder = DockerSchema2ManifestListBuilder() builder.add_manifest(amd64_manifest, 'amd64', 'linux') manifestlist = builder.build() oci_model.create_manifest_and_retarget_tag(repository_ref, manifestlist, 'listtag', storage) manifest = oci_model.get_manifest_for_tag( oci_model.get_repo_tag(repository_ref, 'listtag')) assert manifest assert manifest.get_parsed_manifest().is_manifest_list # Ensure the squashed image doesn't exist. assert oci_model.lookup_derived_image(manifest, 'squash', storage, {}) is None # Create a new one. squashed = oci_model.lookup_or_create_derived_image( manifest, 'squash', 'local_us', storage, {}) assert squashed.unique_id assert oci_model.lookup_or_create_derived_image(manifest, 'squash', 'local_us', storage, {}) == squashed # Perform lookup. assert oci_model.lookup_derived_image(manifest, 'squash', storage, {}) == squashed
def test_get_or_create_manifest_list_duplicate_child_manifest(initialized_db): repository = create_repository("devtable", "newrepo", None) expected_labels = { "Foo": "Bar", "Baz": "Meh", } layer_json = json.dumps({ "id": "somelegacyid", "config": { "Labels": expected_labels, }, "rootfs": { "type": "layers", "diff_ids": [] }, "history": [ { "created": "2018-04-03T18:37:09.284840891Z", "created_by": "do something", }, ], }) # Create a legacy image. find_create_or_link_image("somelegacyid", repository, "devtable", {}, "local_us") # Add a blob containing the config. _, config_digest = _populate_blob(layer_json) # Add a blob of random data. random_data = "hello world" _, random_digest = _populate_blob(random_data) # Build the manifest. v2_builder = DockerSchema2ManifestBuilder() v2_builder.set_config_digest(config_digest, len(layer_json.encode("utf-8"))) v2_builder.add_layer(random_digest, len(random_data.encode("utf-8"))) v2_manifest = v2_builder.build() # Write the manifest. v2_created = get_or_create_manifest(repository, v2_manifest, storage) assert v2_created assert v2_created.manifest.digest == v2_manifest.digest # Build the manifest list, with the child manifest repeated. list_builder = DockerSchema2ManifestListBuilder() list_builder.add_manifest(v2_manifest, "amd64", "linux") list_builder.add_manifest(v2_manifest, "amd32", "linux") manifest_list = list_builder.build() # Write the manifest list, which should also write the manifests themselves. created_tuple = get_or_create_manifest(repository, manifest_list, storage) assert created_tuple is not None created_list = created_tuple.manifest assert created_list assert created_list.media_type.name == manifest_list.media_type assert created_list.digest == manifest_list.digest # Ensure the child manifest links exist. child_manifests = { cm.child_manifest.digest: cm.child_manifest for cm in ManifestChild.select().where( ManifestChild.manifest == created_list) } assert len(child_manifests) == 1 assert v2_manifest.digest in child_manifests assert child_manifests[ v2_manifest.digest].media_type.name == v2_manifest.media_type # Try to create again and ensure we get back the same manifest list. created2_tuple = get_or_create_manifest(repository, manifest_list, storage) assert created2_tuple is not None assert created2_tuple.manifest == created_list
def test_get_or_create_manifest_list(initialized_db): repository = create_repository('devtable', 'newrepo', None) expected_labels = { 'Foo': 'Bar', 'Baz': 'Meh', } layer_json = json.dumps({ 'id': 'somelegacyid', 'config': { 'Labels': expected_labels, }, "rootfs": { "type": "layers", "diff_ids": [] }, "history": [ { "created": "2018-04-03T18:37:09.284840891Z", "created_by": "do something", }, ], }) # Create a legacy image. find_create_or_link_image('somelegacyid', repository, 'devtable', {}, 'local_us') # Add a blob containing the config. _, config_digest = _populate_blob(layer_json) # Add a blob of random data. random_data = 'hello world' _, random_digest = _populate_blob(random_data) # Build the manifests. v1_builder = DockerSchema1ManifestBuilder('devtable', 'simple', 'anothertag') v1_builder.add_layer(random_digest, layer_json) v1_manifest = v1_builder.build(docker_v2_signing_key).unsigned() v2_builder = DockerSchema2ManifestBuilder() v2_builder.set_config_digest(config_digest, len(layer_json)) v2_builder.add_layer(random_digest, len(random_data)) v2_manifest = v2_builder.build() # Write the manifests. v1_created = get_or_create_manifest(repository, v1_manifest, storage) assert v1_created assert v1_created.manifest.digest == v1_manifest.digest v2_created = get_or_create_manifest(repository, v2_manifest, storage) assert v2_created assert v2_created.manifest.digest == v2_manifest.digest # Build the manifest list. list_builder = DockerSchema2ManifestListBuilder() list_builder.add_manifest(v1_manifest, 'amd64', 'linux') list_builder.add_manifest(v2_manifest, 'amd32', 'linux') manifest_list = list_builder.build() # Write the manifest list, which should also write the manifests themselves. created_tuple = get_or_create_manifest(repository, manifest_list, storage) assert created_tuple is not None created_list = created_tuple.manifest assert created_list assert created_list.media_type.name == manifest_list.media_type assert created_list.digest == manifest_list.digest # Ensure the child manifest links exist. child_manifests = { cm.child_manifest.digest: cm.child_manifest for cm in ManifestChild.select().where( ManifestChild.manifest == created_list) } assert len(child_manifests) == 2 assert v1_manifest.digest in child_manifests assert v2_manifest.digest in child_manifests assert child_manifests[ v1_manifest.digest].media_type.name == v1_manifest.media_type assert child_manifests[ v2_manifest.digest].media_type.name == v2_manifest.media_type