def test_build_unencoded_unicode_manifest(): config_json = json.dumps( { "config": { "author": "Sômé guy", }, "rootfs": { "type": "layers", "diff_ids": [] }, "history": [ { "created": "2018-04-03T18:37:09.284840891Z", "created_by": "base", "author": "Sômé guy", }, ], }, ensure_ascii=False, ) schema2_config = DockerSchema2Config( Bytes.for_string_or_unicode(config_json)) builder = DockerSchema2ManifestBuilder() builder.set_config(schema2_config) builder.add_layer("sha256:abc123", 123) builder.build()
def test_valid_config(): config = DockerSchema2Config(Bytes.for_string_or_unicode(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(history_entry, 'somev1id', 'someparentid', index == 3) 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 ] assert config.labels == {}
def build_schema2(self, images, blobs, options): builder = DockerSchema2ManifestBuilder() 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("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", "rootfs": {"type": "layers", "diff_ids": []}, "history": [history_for_image(image) for image in images], } if options.with_broken_manifest_config: # NOTE: We are missing the history entry on purpose. config = { "os": "linux", "rootfs": {"type": "layers", "diff_ids": []}, } if images and images[-1].config: config["config"] = images[-1].config config_json = json.dumps(config, ensure_ascii=options.ensure_ascii) schema2_config = DockerSchema2Config( Bytes.for_string_or_unicode(config_json), skip_validation_for_testing=options.with_broken_manifest_config, ) builder.set_config(schema2_config) blobs[schema2_config.digest] = schema2_config.bytes.as_encoded_str() return builder.build(ensure_ascii=options.ensure_ascii)
def build_schema2(self, images, blobs, options): builder = DockerSchema2ManifestBuilder() 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( '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", "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) schema2_config = DockerSchema2Config( Bytes.for_string_or_unicode(config_json)) builder.set_config(schema2_config) blobs[schema2_config.digest] = schema2_config.bytes.as_encoded_str() return builder.build(ensure_ascii=options.ensure_ascii)
def _get_built_config(self, content_retriever): 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 MalformedSchema2Manifest("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 MalformedSchema2Manifest(msg) self._cached_built_config = DockerSchema2Config(Bytes.for_string_or_unicode(config_bytes)) return self._cached_built_config
def test_malformed_configs(json_data): with pytest.raises(MalformedSchema2Config): DockerSchema2Config(Bytes.for_string_or_unicode(json_data))