IndexWrite takes an image name and creates an index for the targets to which it points. does not pull down any images; entirely assumes that the subjects of the manifests are present. If a reference to the provided already exists and it is an index, updates the manifests in the existing index.
(ref *reference.Spec, descriptors ...v1.Descriptor)
| 234 | // If a reference to the provided already exists and it is an index, updates the manifests in the |
| 235 | // existing index. |
| 236 | func (p *Provider) IndexWrite(ref *reference.Spec, descriptors ...v1.Descriptor) error { |
| 237 | image := ref.String() |
| 238 | log.Debugf("writing an index for %s", image) |
| 239 | if len(descriptors) < 1 { |
| 240 | return errors.New("cannot create index without any manifests") |
| 241 | } |
| 242 | |
| 243 | ii, err := p.Index() |
| 244 | if err != nil { |
| 245 | return fmt.Errorf("unable to get root index: %v", err) |
| 246 | } |
| 247 | images, err := partial.FindImages(ii, match.Name(image)) |
| 248 | if err != nil { |
| 249 | return fmt.Errorf("error parsing index: %v", err) |
| 250 | } |
| 251 | if err == nil && len(images) > 0 { |
| 252 | return fmt.Errorf("image named %s already exists in cache and is not an index", image) |
| 253 | } |
| 254 | indexes, err := partial.FindIndexes(ii, match.Name(image)) |
| 255 | if err != nil { |
| 256 | return fmt.Errorf("error parsing index: %v", err) |
| 257 | } |
| 258 | var im v1.IndexManifest |
| 259 | // get our lock |
| 260 | if err := p.Lock(); err != nil { |
| 261 | return fmt.Errorf("unable to lock cache: %v", err) |
| 262 | } |
| 263 | defer p.Unlock() |
| 264 | // do we update an existing one? Or create a new one? |
| 265 | if len(indexes) > 0 { |
| 266 | // we already had one, so update just the referenced index and return |
| 267 | manifest, err := indexes[0].IndexManifest() |
| 268 | if err != nil { |
| 269 | return fmt.Errorf("unable to convert index for %s into its manifest: %v", image, err) |
| 270 | } |
| 271 | oldhash, err := indexes[0].Digest() |
| 272 | if err != nil { |
| 273 | return fmt.Errorf("unable to get hash of existing index: %v", err) |
| 274 | } |
| 275 | // we only care about avoiding duplicate arch/OS/Variant |
| 276 | var ( |
| 277 | descReplace = map[string]v1.Descriptor{} |
| 278 | descNonReplace []v1.Descriptor |
| 279 | ) |
| 280 | for _, desc := range descriptors { |
| 281 | // we do not replace "unknown" because those are attestations; we might remove attestations that point at things we remove |
| 282 | if desc.Platform == nil || (desc.Platform.Architecture == "unknown" && desc.Platform.OS == "unknown") { |
| 283 | descNonReplace = append(descNonReplace, desc) |
| 284 | continue |
| 285 | } |
| 286 | descReplace[fmt.Sprintf("%s/%s/%s", desc.Platform.OS, desc.Platform.Architecture, desc.Platform.OSVersion)] = desc |
| 287 | } |
| 288 | // now we can go through each one and see if it already exists, and, if so, replace it |
| 289 | // however, we do not replace attestations unless they point at something we are removing |
| 290 | var ( |
| 291 | manifests []v1.Descriptor |
| 292 | referencedDigests = map[string]bool{} |
| 293 | ) |
nothing calls this directly
no test coverage detected