Pull pulls an artifact from a registry and stores it in the content store. The digest check, manifest read, and layer downloads all reuse a single authenticated registry session (a remote.Puller) so the token exchange and underlying connection are established only once, rather than re-doing authent
(ctx context.Context, registryRef string, force bool, opts ...crane.Option)
| 65 | // underlying connection are established only once, rather than re-doing |
| 66 | // authentication for each step. |
| 67 | func Pull(ctx context.Context, registryRef string, force bool, opts ...crane.Option) (string, error) { |
| 68 | opts = append(opts, crane.WithContext(ctx), crane.WithTransport(NewTransport(ctx))) |
| 69 | o := crane.GetOptions(opts...) |
| 70 | |
| 71 | ref, err := name.ParseReference(registryRef, o.Name...) |
| 72 | if err != nil { |
| 73 | return "", fmt.Errorf("parsing registry reference %s: %w", registryRef, err) |
| 74 | } |
| 75 | |
| 76 | s, err := newSession(o) |
| 77 | if err != nil { |
| 78 | return "", fmt.Errorf("creating registry session: %w", err) |
| 79 | } |
| 80 | |
| 81 | remoteDigest, err := s.digest(ctx, ref) |
| 82 | if err != nil { |
| 83 | return "", fmt.Errorf("resolving remote digest for %s: %w", registryRef, err) |
| 84 | } |
| 85 | |
| 86 | store, err := content.NewStore() |
| 87 | if err != nil { |
| 88 | return "", fmt.Errorf("creating content store: %w", err) |
| 89 | } |
| 90 | |
| 91 | localRef := ref.Context().RepositoryStr() + separator(ref) + ref.Identifier() |
| 92 | if !force { |
| 93 | if meta, metaErr := store.GetArtifactMetadata(localRef); metaErr == nil { |
| 94 | if meta.Digest == remoteDigest { |
| 95 | if !hasCagentAnnotation(meta.Annotations) { |
| 96 | return "", fmt.Errorf("artifact %s found in store wasn't created by `docker agent share push`\nTry to push again with `docker agent share push`", localRef) |
| 97 | } |
| 98 | return meta.Digest, nil |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | img, err := s.image(ctx, ref) |
| 104 | if err != nil { |
| 105 | return "", fmt.Errorf("pulling image from registry %s: %w", registryRef, err) |
| 106 | } |
| 107 | |
| 108 | manifest, err := img.Manifest() |
| 109 | if err != nil { |
| 110 | return "", fmt.Errorf("getting manifest from pulled image: %w", err) |
| 111 | } |
| 112 | if !hasCagentAnnotation(manifest.Annotations) { |
| 113 | return "", fmt.Errorf("artifact %s wasn't created by `docker agent share push`\nTry to push again with `docker agent share push`", localRef) |
| 114 | } |
| 115 | |
| 116 | digest, err := storeArtifact(ctx, store, s, ref, localRef, img) |
| 117 | if err != nil { |
| 118 | return "", fmt.Errorf("storing artifact in content store: %w", err) |
| 119 | } |
| 120 | |
| 121 | return digest, nil |
| 122 | } |
| 123 | |
| 124 | func storeArtifact(ctx context.Context, store *content.Store, s *session, ref name.Reference, localRef string, img v1.Image) (string, error) { |