Skip to content
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

Implement new manifest cache fully capable of multi-platform image building #2730

Merged
merged 42 commits into from
Aug 31, 2020

Conversation

chanseokoh
Copy link
Member

@chanseokoh chanseokoh commented Aug 26, 2020

Follow-up to #2711 to complete the new cache design to support multi-platform image building.

  • Adds UnlistedPlatformInManifestListException.
  • No platform verification of a cached manifest any more. getCachedBaseImages() returns cached images only when Jib has cached all the manifests matching the configured platforms.
  • When caching a manifest list and manifests, PullBaseImageStep also stores additional information of manifest digests. This is to enable looking up a manifest from a manifest list by digest. For example,
{
  "manifestList": {  # manifest list content
    "manifests": [
      {  # manifest descriptor 1
        "digest": "sha256:a157906...",
        "platform": { ... },
        ...
      },
      {
        "digest": "sha256:...",
        "platform": { ... },
        ...
      }
    ]
  },

  "manifestsAndConfigs": [
    {
      "manifestDigest": "sha256:a1579064....",  <-- manifest digest for lookup
      "manifest": { ... },
      "config": { ... }
    },
    { ... },
    ...
  ]     

@chanseokoh chanseokoh requested a review from a team August 27, 2020 16:38
@chanseokoh chanseokoh marked this pull request as ready for review August 27, 2020 16:38
@chanseokoh
Copy link
Member Author

Ready for review. See the PR description for high-level changes.

+ "Jib online once to re-cache the right image manifest.");
}
return new ImagesAndRegistryClient(Collections.singletonList(image.get()), null);
List<Image> images = getCachedBaseImages();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we could still run into an issue where we don't have all the necessary platform information for an image/platform that wasn't previously referenced?

I assume downloading all the image layers for all the images is impractical?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where we don't have all the necessary platform information for an image/platform that wasn't previously referenced?

In this case, the getCachedBaseImages() in this PR returns an empty list (i.e., cache miss). Offline building will fail and suggest to re-run online once. The digest reference case will fall through to normal operation (contacting the base image repository).

Comment on lines +360 to +370
if (manifestList == null) {
Verify.verify(manifestsAndConfigs.size() == 1);
ManifestTemplate manifest = manifestsAndConfigs.get(0).getManifest();
if (manifest instanceof V21ManifestTemplate) {
return Collections.singletonList(
JsonToImageTranslator.toImage((V21ManifestTemplate) manifest));
}
return Collections.singletonList(
JsonToImageTranslator.toImage(
(BuildableManifestTemplate) Verify.verifyNotNull(manifest),
Verify.verifyNotNull(manifestsAndConfigs.get(0).getConfig())));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this section is for when the base image reference is a single manifest?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. When the image reference is an image manifest and not a manifest list. In the cache metadata, manifestList is null in this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah gotcha, is there a particular reason why we chose null instead of an empty list for manifestList?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. A "manifest list" is not a List in Java but a class called ManifestTemplate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right my bad, thanks for clarifying:)

Comment on lines +334 to +335
* single image (if cached). If a manifest list, returns all the images matching the configured
* platforms in the manifest list but only when all of the images are cached.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we make sure to return the images matching the configured platforms in the manifest list only if all the images are cached?

Copy link
Member Author

@chanseokoh chanseokoh Aug 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have cached only a subset of what we really need (i.e., Jib needs to build, say, three Images, but the cache has only two Images), then it's not a cache hit as a whole, thus a cache miss.

Theoretically you could say, Jib could re-download only the missing Images, but note that performance is not the reason for caching. It's about whether we can completely avoid accessing the Internet or not. So, if any image is missing in the cache, I am saying "cache miss" for simplicity.

Comment on lines +388 to +390
ManifestTemplate manifest = Verify.verifyNotNull(manifestAndConfigFound.get().getManifest());
ContainerConfigurationTemplate containerConfig =
Verify.verifyNotNull(manifestAndConfigFound.get().getConfig());
Copy link
Contributor

@mpeddada1 mpeddada1 Aug 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something here but what's the reasoning behind checking if these values are null?/ When would they be null?

Copy link
Member Author

@chanseokoh chanseokoh Aug 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's our assumption and how we designed the cache to work. If any ManifestAndConfig entry (which is just a pair of a manifest and a config) is saved (cached), their values should never be null; otherwise, something got terribly wrong.

Now, we then use Verify.verifyNotNull() to signal the NullAway check (it's a check we set up in our repo to catch potential NPE) that manifest and containerConfig are not supposed to be null. Otherwise, because JsonToImageTranslator.toImage() doesn't accept @Nullable parameters, NullAway will complain that you're passing potentially null parameters.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see! Makes sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants