-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check for existence of layers in cache before returning cached base image #3767
Changes from 11 commits
3caa0ab
c1d1d4d
ecb4575
0d70c29
c9a51ec
755dcfc
b231d79
6ee16e0
ac8a2c7
cd2070f
7e89ea7
3445f77
1456e95
099c0ce
ab53ec2
05097fb
d891281
4971ee9
4ecb92f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,38 @@ static void verifyImageMetadata(ImageMetadataTemplate metadata, Path metadataCac | |
this.cacheStorageFiles = cacheStorageFiles; | ||
} | ||
|
||
/** | ||
* Returns {@code true} if all image layers described in a manifest have a corresponding file | ||
* entry in the cache. | ||
* | ||
* @param manifest the image manifest | ||
* @return a boolean | ||
*/ | ||
boolean areAllLayersCached(ManifestTemplate manifest) { | ||
elefeint marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
List<DescriptorDigest> layerDigests; | ||
|
||
if (manifest instanceof V21ManifestTemplate) { | ||
layerDigests = ((V21ManifestTemplate) manifest).getLayerDigests(); | ||
} else if (manifest instanceof BuildableManifestTemplate) { | ||
layerDigests = | ||
((BuildableManifestTemplate) manifest) | ||
.getLayers().stream() | ||
.map(BuildableManifestTemplate.ContentDescriptorTemplate::getDigest) | ||
.collect(Collectors.toList()); | ||
} else { | ||
throw new IllegalArgumentException("Unknown manifest type: " + manifest); | ||
} | ||
Comment on lines
+103
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this would break current behavior for those doing multi-platform image building? For context #2730, we also do caching for manifest lists in addition to single manifests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That’s a good callout, and please let me know if I'm misunderstanding anything here! Right now the added logic in But, do you think there is value here to have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah thanks for the detailed explanation! You're right, it is called for the individual manifests in the manifest list.
Hm that's a good question. I was initially thinking about this too but looking at the code for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good! |
||
|
||
for (DescriptorDigest layerDigest : layerDigests) { | ||
Path layerDirectory = cacheStorageFiles.getLayerDirectory(layerDigest); | ||
if (!Files.exists(layerDirectory)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* Retrieves the cached image metadata (a manifest list and a list of manifest/container | ||
* configuration pairs) for an image reference. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -638,4 +638,52 @@ public void testVerifyImageMetadata_validOciImageIndex() throws CacheCorruptedEx | |
CacheStorageReader.verifyImageMetadata(metadata, Paths.get("/cache/dir")); | ||
// should pass without CacheCorruptedException | ||
} | ||
|
||
@Test | ||
public void testAllLayersCached_v21SingleManifest() | ||
throws IOException, CacheCorruptedException, DigestException, URISyntaxException { | ||
|
||
emmileaf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
setupCachedMetadataV21(cacheDirectory); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor suggestion: If possible, let's format the test into three blocks: arrange, act and assert, with a space between each of these blocks. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion, this makes a lot of sense! Tried to follow this idea though with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about we store these calls in variables? For example:
This is just an example so you can pick a name you think works better. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ohh apologies I completely misunderstood earlier! Thank you for the explanation, I see what is meant by having separate |
||
ImageMetadataTemplate metadata = | ||
cacheStorageReader.retrieveMetadata(ImageReference.of("test", "image", "tag")).get(); | ||
|
||
V21ManifestTemplate manifest = | ||
(V21ManifestTemplate) metadata.getManifestsAndConfigs().get(0).getManifest(); | ||
Assert.assertEquals(2, manifest.getLayerDigests().size()); | ||
emmileaf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ManifestAndConfigTemplate manifestAndConfig = | ||
new ManifestAndConfigTemplate(manifest, new ContainerConfigurationTemplate()); | ||
|
||
// Create only one of the layer directories. | ||
DescriptorDigest firstLayerDigest = | ||
DescriptorDigest.fromHash(manifest.getLayerDigests().get(0).getHash()); | ||
Files.createDirectories(cacheStorageFiles.getLayerDirectory(firstLayerDigest)); | ||
Assert.assertFalse(cacheStorageReader.areAllLayersCached(manifestAndConfig.getManifest())); | ||
|
||
// Create the other layer directory. | ||
DescriptorDigest secondLayerDigest = | ||
DescriptorDigest.fromHash(manifest.getLayerDigests().get(1).getHash()); | ||
Files.createDirectories(cacheStorageFiles.getLayerDirectory(secondLayerDigest)); | ||
Assert.assertTrue(cacheStorageReader.areAllLayersCached(manifestAndConfig.getManifest())); | ||
} | ||
|
||
@Test | ||
public void testAllLayersCached_v22SingleManifest() | ||
throws IOException, CacheCorruptedException, DigestException, URISyntaxException { | ||
|
||
setupCachedMetadataV22(cacheDirectory); | ||
ImageMetadataTemplate metadata = | ||
cacheStorageReader.retrieveMetadata(ImageReference.of("test", "image", "tag")).get(); | ||
|
||
V22ManifestTemplate manifest = | ||
(V22ManifestTemplate) metadata.getManifestsAndConfigs().get(0).getManifest(); | ||
Assert.assertEquals(1, manifest.getLayers().size()); | ||
ManifestAndConfigTemplate manifestAndConfig = | ||
new ManifestAndConfigTemplate(manifest, new ContainerConfigurationTemplate()); | ||
|
||
Assert.assertFalse(cacheStorageReader.areAllLayersCached(manifestAndConfig.getManifest())); | ||
// Create the layer directory. | ||
DescriptorDigest layerDigest = manifest.getLayers().get(0).getDigest(); | ||
Files.createDirectories(cacheStorageFiles.getLayerDirectory(layerDigest)); | ||
Assert.assertTrue(cacheStorageReader.areAllLayersCached(manifestAndConfig.getManifest())); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(optional) there was quite a bit of code duplication in this method even in the past between the section that deals with general and platform-based manifest processing. Could there be an opportunity for refactoring common logic out into a helper method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah this is a great suggestion - will refactor this and see if I can make the methods cleaner to read.