Add caching of retrieved config in manifest class

This commit is contained in:
Joseph Schorr 2018-11-25 20:03:57 +02:00
parent adccdd30ca
commit 38f68f81f2

View file

@ -128,6 +128,7 @@ class DockerSchema2Manifest(ManifestInterface):
def __init__(self, manifest_bytes): def __init__(self, manifest_bytes):
self._layers = None self._layers = None
self._payload = manifest_bytes self._payload = manifest_bytes
self._cached_built_config = None
try: try:
self._parsed = json.loads(manifest_bytes) self._parsed = json.loads(manifest_bytes)
@ -212,11 +213,11 @@ class DockerSchema2Manifest(ManifestInterface):
def child_manifests(self, content_retriever): def child_manifests(self, content_retriever):
return None return None
def _manifest_image_layers(self, content_retriever, schema2_config=None): def _manifest_image_layers(self, content_retriever):
assert not self.has_remote_layer assert not self.has_remote_layer
# Retrieve the configuration for the manifest. # Retrieve the configuration for the manifest.
config = schema2_config or self._get_built_config(content_retriever) config = self._get_built_config(content_retriever)
history = list(config.history) history = list(config.history)
if len(history) < len(self.layers): if len(history) < len(self.layers):
raise MalformedSchema2Manifest('Found less history than layer blobs') raise MalformedSchema2Manifest('Found less history than layer blobs')
@ -236,7 +237,7 @@ class DockerSchema2Manifest(ManifestInterface):
compressed_size = EMPTY_LAYER_SIZE if blob_layer is None else blob_layer.compressed_size compressed_size = EMPTY_LAYER_SIZE if blob_layer is None else blob_layer.compressed_size
# Create a new synthesized V1 ID for the history layer by hashing its content and # Create a new synthesized V1 ID for the history layer by hashing its content and
# the blob associated withn it. # the blob associated with it.
digest_history.update(json.dumps(history_entry.raw_entry)) digest_history.update(json.dumps(history_entry.raw_entry))
digest_history.update("|") digest_history.update("|")
digest_history.update(str(history_index)) digest_history.update(str(history_index))
@ -307,7 +308,8 @@ class DockerSchema2Manifest(ManifestInterface):
""" """
assert not self.has_remote_layer assert not self.has_remote_layer
schema2_config = self._get_built_config(content_retriever) schema2_config = self._get_built_config(content_retriever)
layers = list(self._manifest_image_layers(content_retriever, schema2_config)) layers = list(self._manifest_image_layers(content_retriever))
for index, layer in enumerate(reversed(layers)): # Schema 1 layers are in reverse order for index, layer in enumerate(reversed(layers)): # Schema 1 layers are in reverse order
v1_compatibility = schema2_config.build_v1_compatibility(layer.history, v1_compatibility = schema2_config.build_v1_compatibility(layer.history,
layer.v1_id, layer.v1_id,
@ -319,6 +321,9 @@ class DockerSchema2Manifest(ManifestInterface):
return v1_builder return v1_builder
def _get_built_config(self, content_retriever): 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) config_bytes = content_retriever.get_blob_bytes_with_digest(self.config.digest)
if config_bytes is None: if config_bytes is None:
raise MalformedSchema2Manifest('Could not load config blob for manifest') raise MalformedSchema2Manifest('Could not load config blob for manifest')
@ -327,7 +332,8 @@ class DockerSchema2Manifest(ManifestInterface):
raise MalformedSchema2Manifest('Size of config does not match that retrieved: %s vs %s', raise MalformedSchema2Manifest('Size of config does not match that retrieved: %s vs %s',
len(config_bytes), self.config.size) len(config_bytes), self.config.size)
return DockerSchema2Config(config_bytes) self._cached_built_config = DockerSchema2Config(config_bytes)
return self._cached_built_config
def _generate_layers(self): def _generate_layers(self):
for index, layer in enumerate(self._parsed[DOCKER_SCHEMA2_MANIFEST_LAYERS_KEY]): for index, layer in enumerate(self._parsed[DOCKER_SCHEMA2_MANIFEST_LAYERS_KEY]):