Inspect prints detailed information of each image in `images`.
(ctx context.Context, client *containerd.Client, identifiers []string, options types.ImageInspectOptions)
| 87 | |
| 88 | // Inspect prints detailed information of each image in `images`. |
| 89 | func Inspect(ctx context.Context, client *containerd.Client, identifiers []string, options types.ImageInspectOptions) ([]any, error) { |
| 90 | // Set a timeout |
| 91 | ctx, cancel := context.WithTimeout(ctx, 5*time.Second) |
| 92 | defer cancel() |
| 93 | |
| 94 | // Will hold the final answers |
| 95 | var errs []error |
| 96 | var entries []interface{} |
| 97 | |
| 98 | snapshotter := containerdutil.SnapshotService(client, options.GOptions.Snapshotter) |
| 99 | // We have to query per provided identifier, as we need to post-process results for the case name + digest |
| 100 | for _, identifier := range identifiers { |
| 101 | candidateImageList, requestedName, requestedTag, err := inspectIdentifier(ctx, client, identifier) |
| 102 | if err != nil { |
| 103 | errs = append(errs, fmt.Errorf("%w: %s", err, identifier)) |
| 104 | continue |
| 105 | } |
| 106 | |
| 107 | var validatedImage *dockercompat.Image |
| 108 | var repoTags []string |
| 109 | var repoDigests []string |
| 110 | |
| 111 | // Go through the candidates |
| 112 | for _, candidateImage := range candidateImageList { |
| 113 | // Inspect the image |
| 114 | candidateNativeImage, err := imageinspector.Inspect(ctx, client, candidateImage, snapshotter) |
| 115 | if err != nil { |
| 116 | log.G(ctx).WithError(err).WithField("name", candidateImage.Name).Error("failure inspecting image") |
| 117 | continue |
| 118 | } |
| 119 | |
| 120 | // If native, we just add everything in there and that's it |
| 121 | if options.Mode == "native" { |
| 122 | entries = append(entries, candidateNativeImage) |
| 123 | continue |
| 124 | } |
| 125 | |
| 126 | // If dockercompat: does the candidate have a name? Get it if so |
| 127 | parsedReference, err := referenceutil.Parse(candidateNativeImage.Image.Name) |
| 128 | if err != nil { |
| 129 | log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("the found image has an unparsable name") |
| 130 | continue |
| 131 | } |
| 132 | |
| 133 | // If we were ALSO asked for a specific name on top of the digest, we need to make sure we keep only the image with that name |
| 134 | if requestedName != "" { |
| 135 | // If the candidate did not have a name, then we should ignore this one and continue |
| 136 | if parsedReference.Name() == "" { |
| 137 | continue |
| 138 | } |
| 139 | |
| 140 | // Otherwise, the candidate has a name. If it is the one we want, store it and continue, otherwise, fall through |
| 141 | candidateTag := parsedReference.Tag |
| 142 | // If the name had a digest, an empty tag is not normalized to latest, so, account for that here |
| 143 | if requestedTag == "" { |
| 144 | requestedTag = "latest" |
| 145 | } |
| 146 | if parsedReference.Name() == requestedName && candidateTag == requestedTag { |
no test coverage detected
searching dependent graphs…