ImagePull takes an image name and ensures that the image manifest or index to which it refers exists in local cache and, if not, pulls it from the registry and writes it locally. It should be efficient and only write missing blobs, based on their content hash. If the ref and all of the content for t
(ref *reference.Spec, platforms []imagespec.Platform, alwaysPull bool)
| 40 | // Note that ImagePull does try ValidateImage first, so if the image is already in the cache, it will not |
| 41 | // do any network activity at all. |
| 42 | func (p *Provider) ImagePull(ref *reference.Spec, platforms []imagespec.Platform, alwaysPull bool) error { |
| 43 | imageName := util.ReferenceExpand(ref.String()) |
| 44 | canonicalRef, err := reference.Parse(imageName) |
| 45 | if err != nil { |
| 46 | return fmt.Errorf("invalid image name %s: %v", imageName, err) |
| 47 | } |
| 48 | ref = &canonicalRef |
| 49 | image := ref.String() |
| 50 | pullImageName := image |
| 51 | platformMessage := platformMessageGenerator(platforms) |
| 52 | remoteOptions := []remote.Option{remote.WithAuthFromKeychain(authn.DefaultKeychain)} |
| 53 | log.Debugf("ImagePull to cache %s trusted reference %s", image, pullImageName) |
| 54 | |
| 55 | // unless alwaysPull is set to true, check locally first |
| 56 | if alwaysPull { |
| 57 | log.Debugf("Instructed always to pull, so pulling image %s %s", image, platformMessage) |
| 58 | } else { |
| 59 | imgSrc, err := p.ValidateImage(ref, platforms) |
| 60 | switch { |
| 61 | case err == nil && imgSrc != nil: |
| 62 | log.Debugf("Image %s %s found in local cache, not pulling", image, platformMessage) |
| 63 | return nil |
| 64 | case err != nil && errors.Is(err, &noReferenceError{}): |
| 65 | log.Debugf("Image %s %s not found in local cache, pulling", image, platformMessage) |
| 66 | default: |
| 67 | log.Debugf("Image %s %s incomplete or invalid in local cache, error %v, pulling", image, platformMessage, err) |
| 68 | } |
| 69 | } |
| 70 | remoteRef, err := name.ParseReference(pullImageName) |
| 71 | if err != nil { |
| 72 | return fmt.Errorf("invalid image name %s: %v", pullImageName, err) |
| 73 | } |
| 74 | |
| 75 | desc, err := registry.GetRemote().Get(remoteRef, remoteOptions...) |
| 76 | if err != nil { |
| 77 | return fmt.Errorf("error getting manifest for image %s: %v", pullImageName, err) |
| 78 | } |
| 79 | |
| 80 | // get our lock |
| 81 | if err := p.Lock(); err != nil { |
| 82 | return fmt.Errorf("unable to lock cache for removing descriptors: %v", err) |
| 83 | } |
| 84 | defer p.Unlock() |
| 85 | |
| 86 | // first attempt as an index |
| 87 | ii, err := desc.ImageIndex() |
| 88 | if err == nil { |
| 89 | log.Debugf("ImageWrite retrieved %s is index, saving, first checking if it contains target %s", pullImageName, platformMessage) |
| 90 | im, err := ii.IndexManifest() |
| 91 | if err != nil { |
| 92 | return fmt.Errorf("unable to get IndexManifest: %v", err) |
| 93 | } |
| 94 | // only useful if it contains our architecture |
| 95 | var foundPlatforms []*v1.Platform |
| 96 | for _, m := range im.Manifests { |
| 97 | if m.MediaType.IsImage() && m.Platform != nil { |
| 98 | foundPlatforms = append(foundPlatforms, m.Platform) |
| 99 | } |
nothing calls this directly
no test coverage detected