def _generate_layers(self, allow_missing_ids=False): """ Returns a generator of objects that have the blobSum and v1Compatibility keys in them, starting from the base image and working toward the leaf node. """ for blob_sum_obj, history_obj in reversed( list( zip( self._parsed[DOCKER_SCHEMA1_FS_LAYERS_KEY], self._parsed[DOCKER_SCHEMA1_HISTORY_KEY], ) ) ): try: image_digest = digest_tools.Digest.parse_digest( blob_sum_obj[DOCKER_SCHEMA1_BLOB_SUM_KEY] ) except digest_tools.InvalidDigestException: raise MalformedSchema1Manifest( "could not parse manifest digest: %s" % blob_sum_obj[DOCKER_SCHEMA1_BLOB_SUM_KEY] ) metadata_string = history_obj[DOCKER_SCHEMA1_V1_COMPAT_KEY] try: v1_metadata = json.loads(metadata_string) except (ValueError, TypeError): raise MalformedSchema1Manifest( "Could not parse metadata string: %s" % metadata_string ) v1_metadata = v1_metadata or {} container_config = v1_metadata.get("container_config") or {} command_list = container_config.get("Cmd", None) command = to_canonical_json(command_list) if command_list else None if not allow_missing_ids and not "id" in v1_metadata: raise MalformedSchema1Manifest("id field missing from v1Compatibility JSON") labels = v1_metadata.get("config", {}).get("Labels", {}) or {} extracted = Schema1V1Metadata( image_id=v1_metadata.get("id"), parent_image_id=v1_metadata.get("parent"), created=v1_metadata.get("created"), comment=v1_metadata.get("comment"), author=v1_metadata.get("author"), command=command, labels=labels, ) compressed_size = v1_metadata.get("Size") yield Schema1Layer( image_digest, extracted, metadata_string, compressed_size, False, None )
def _updated_v1_metadata(v1_metadata_json, updated_id_map): """ Updates v1_metadata with new image IDs. """ parsed = json.loads(v1_metadata_json) parsed["id"] = updated_id_map[parsed["id"]] if parsed.get("parent") and parsed["parent"] in updated_id_map: parsed["parent"] = updated_id_map[parsed["parent"]] if parsed.get("container_config", {}).get("Image"): existing_image = parsed["container_config"]["Image"] if existing_image in updated_id_map: parsed["container_config"]["image"] = updated_id_map[existing_image] return to_canonical_json(parsed)
def test_to_canonical_json(input, expected_output): result = to_canonical_json(input) assert result == expected_output # Ensure the result is utf-8. assert isinstance(result, str)