def test_parse_basic_config(): config = OCIConfig(Bytes.for_string_or_unicode(SAMPLE_CONFIG)) assert ( config.digest == "sha256:b8410e43166c4e6b11cc0db4ede89539f206d5c9bb43d31d5b37f509b78d3f01" ) assert config.size == 1582 history = list(config.history) assert config.has_empty_layer assert len(history) == 2 expected = [ LayerHistory( created=u"2015-10-31T22:22:54.690851953Z", created_datetime=datetime.datetime(2015, 10, 31, 22, 22, 54, 690851, tzinfo=tzutc()), command= u"/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /", is_empty=False, author=None, comment=None, raw_entry={ u"created_by": u"/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /", u"created": u"2015-10-31T22:22:54.690851953Z", }, ), LayerHistory( created=u"2015-10-31T22:22:55.613815829Z", created_datetime=datetime.datetime(2015, 10, 31, 22, 22, 55, 613815, tzinfo=tzutc()), command=u'/bin/sh -c #(nop) CMD ["sh"]', is_empty=True, author=None, comment=None, raw_entry={ u"empty_layer": True, u"created_by": u'/bin/sh -c #(nop) CMD ["sh"]', u"created": u"2015-10-31T22:22:55.613815829Z", }, ), ] assert history == expected
def build_oci(self, images, blobs, options): builder = OCIManifestBuilder() for image in images: checksum = "sha256:" + hashlib.sha256(image.bytes).hexdigest() if image.urls is None: blobs[checksum] = image.bytes # If invalid blob references were requested, just make it up. if options.manifest_invalid_blob_references: checksum = "sha256:" + hashlib.sha256( b"notarealthing").hexdigest() if not image.is_empty: builder.add_layer(checksum, len(image.bytes), urls=image.urls) def history_for_image(image): history = { "created": "2018-04-03T18:37:09.284840891Z", "created_by": (("/bin/sh -c #(nop) ENTRYPOINT %s" % image.config["Entrypoint"]) if image.config and image.config.get("Entrypoint") else "/bin/sh -c #(nop) %s" % image.id), } if image.is_empty: history["empty_layer"] = True return history config = { "os": "linux", "architecture": "amd64", "rootfs": { "type": "layers", "diff_ids": [] }, "history": [history_for_image(image) for image in images], } if images[-1].config: config["config"] = images[-1].config config_json = json.dumps(config, ensure_ascii=options.ensure_ascii) oci_config = OCIConfig(Bytes.for_string_or_unicode(config_json)) builder.set_config(oci_config) blobs[oci_config.digest] = oci_config.bytes.as_encoded_str() return builder.build(ensure_ascii=options.ensure_ascii)
def _get_built_config(self, content_retriever): assert self.is_image_manifest if self._cached_built_config: return self._cached_built_config config_bytes = content_retriever.get_blob_bytes_with_digest(self.config.digest) if config_bytes is None: raise MalformedOCIManifest("Could not load config blob for manifest") if len(config_bytes) != self.config.size: msg = "Size of config does not match that retrieved: %s vs %s" % ( len(config_bytes), self.config.size, ) raise MalformedOCIManifest(msg) self._cached_built_config = OCIConfig(Bytes.for_string_or_unicode(config_bytes)) return self._cached_built_config
def test_invalid_config(): with pytest.raises(MalformedConfig): OCIConfig(Bytes.for_string_or_unicode("{}"))
def test_config_missing_required(): valid_config = json.loads(SAMPLE_CONFIG) valid_config.pop("os") with pytest.raises(MalformedConfig): OCIConfig(Bytes.for_string_or_unicode(json.dumps(valid_config)))