deleteImage deletes the named image from the registry, if supported.
(ctx context.Context, sys *types.SystemContext, ref dockerReference)
| 658 | |
| 659 | // deleteImage deletes the named image from the registry, if supported. |
| 660 | func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerReference) error { |
| 661 | if ref.isUnknownDigest { |
| 662 | return fmt.Errorf("Docker reference without a tag or digest cannot be deleted") |
| 663 | } |
| 664 | |
| 665 | registryConfig, err := loadRegistryConfiguration(sys) |
| 666 | if err != nil { |
| 667 | return err |
| 668 | } |
| 669 | // docker/distribution does not document what action should be used for deleting images. |
| 670 | // |
| 671 | // Current docker/distribution requires "pull" for reading the manifest and "delete" for deleting it. |
| 672 | // quay.io requires "push" (an explicit "pull" is unnecessary), does not grant any token (fails parsing the request) if "delete" is included. |
| 673 | // OpenShift ignores the action string (both the password and the token is an OpenShift API token identifying a user). |
| 674 | // |
| 675 | // We have to hard-code a single string, luckily both docker/distribution and quay.io support "*" to mean "everything". |
| 676 | c, err := newDockerClientFromRef(sys, ref, registryConfig, true, "*") |
| 677 | if err != nil { |
| 678 | return err |
| 679 | } |
| 680 | defer c.Close() |
| 681 | |
| 682 | headers := map[string][]string{ |
| 683 | "Accept": manifest.DefaultRequestedManifestMIMETypes, |
| 684 | } |
| 685 | refTail, err := ref.tagOrDigest() |
| 686 | if err != nil { |
| 687 | return err |
| 688 | } |
| 689 | getPath := fmt.Sprintf(manifestPath, reference.Path(ref.ref), refTail) |
| 690 | get, err := c.makeRequest(ctx, http.MethodGet, getPath, headers, nil, v2Auth, nil) |
| 691 | if err != nil { |
| 692 | return err |
| 693 | } |
| 694 | defer get.Body.Close() |
| 695 | switch get.StatusCode { |
| 696 | case http.StatusOK: |
| 697 | case http.StatusNotFound: |
| 698 | return fmt.Errorf("Unable to delete %v. Image may not exist or is not stored with a v2 Schema in a v2 registry", ref.ref) |
| 699 | default: |
| 700 | return fmt.Errorf("deleting %v: %w", ref.ref, registryHTTPResponseToError(get)) |
| 701 | } |
| 702 | manifestBody, err := iolimits.ReadAtMost(get.Body, iolimits.MaxManifestBodySize) |
| 703 | if err != nil { |
| 704 | return err |
| 705 | } |
| 706 | |
| 707 | manifestDigest, err := manifest.Digest(manifestBody) |
| 708 | if err != nil { |
| 709 | return fmt.Errorf("computing manifest digest: %w", err) |
| 710 | } |
| 711 | deletePath := fmt.Sprintf(manifestPath, reference.Path(ref.ref), manifestDigest) |
| 712 | |
| 713 | // When retrieving the digest from a registry >= 2.3 use the following header: |
| 714 | // "Accept": "application/vnd.docker.distribution.manifest.v2+json" |
| 715 | delete, err := c.makeRequest(ctx, http.MethodDelete, deletePath, headers, nil, v2Auth, nil) |
| 716 | if err != nil { |
| 717 | return err |
no test coverage detected
searching dependent graphs…