Card container_security_113 - Delete image support

Add support to mark images for deletion from repository

Requires:
  * V2 API and schema
  * registry configured to allow deletes
  * run registry garbage collection to free up disk space

Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
Jhon Honce 2016-06-06 16:05:00 -07:00
parent 0ff261802b
commit f3efa063e3
7 changed files with 100 additions and 1 deletions

27
cmd/skopeo/delete.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
)
func deleteHandler(context *cli.Context) {
if len(context.Args()) != 1 {
logrus.Fatal("Usage: delete imageReference")
}
image, err := parseImageSource(context, context.Args()[0])
if err != nil {
logrus.Fatal(err.Error())
}
if err := image.Delete(); err != nil {
logrus.Fatal(err)
}
}
var deleteCmd = cli.Command{
Name: "delete",
Usage: "Delete given image",
Action: deleteHandler,
}

View File

@ -63,6 +63,7 @@ func main() {
copyCmd,
inspectCmd,
layersCmd,
deleteCmd,
standaloneSignCmd,
standaloneVerifyCmd,
}

View File

@ -111,3 +111,7 @@ func (s *dirImageSource) GetSignatures() ([][]byte, error) {
}
return signatures, nil
}
func (s *dirImageSource) Delete() error {
return fmt.Errorf("directory#dirImageSource.Delete() not implmented")
}

View File

@ -7,6 +7,7 @@ import (
"net/http"
"github.com/Sirupsen/logrus"
"github.com/projectatomic/skopeo/docker/utils"
"github.com/projectatomic/skopeo/reference"
"github.com/projectatomic/skopeo/types"
)
@ -94,3 +95,51 @@ func (s *dockerImageSource) GetLayer(digest string) (io.ReadCloser, error) {
func (s *dockerImageSource) GetSignatures() ([][]byte, error) {
return [][]byte{}, nil
}
func (s *dockerImageSource) Delete() error {
var body []byte
// When retrieving the digest from a registry >= 2.3 use the following header:
// "Accept": "application/vnd.docker.distribution.manifest.v2+json"
headers := make(map[string][]string)
headers["Accept"] = []string{utils.DockerV2Schema2MIMEType}
getURL := fmt.Sprintf(manifestURL, s.ref.RemoteName(), s.tag)
get, err := s.c.makeRequest("GET", getURL, headers, nil)
if err != nil {
return err
}
defer get.Body.Close()
body, err = ioutil.ReadAll(get.Body)
if err != nil {
return err
}
switch get.StatusCode {
case http.StatusOK:
case http.StatusNotFound:
return fmt.Errorf("Unable to delete %v. Image may not exist or is not stored with a v2 Schema in a v2 registry.", s.ref)
default:
return fmt.Errorf("Failed to delete %v: %v (%v)", s.ref, body, get.Status)
}
digest := get.Header.Get("Docker-Content-Digest")
deleteURL := fmt.Sprintf(manifestURL, s.ref.RemoteName(), digest)
// When retrieving the digest from a registry >= 2.3 use the following header:
// "Accept": "application/vnd.docker.distribution.manifest.v2+json"
delete, err := s.c.makeRequest("DELETE", deleteURL, headers, nil)
if err != nil {
return err
}
defer delete.Body.Close()
body, err = ioutil.ReadAll(delete.Body)
if err != nil {
return err
}
if delete.StatusCode != http.StatusAccepted {
return fmt.Errorf("Failed to delete %v: %v (%v)", deleteURL, body, delete.Status)
}
return nil
}

View File

@ -10,6 +10,8 @@ skopeo \(em Inspect Docker images and repositories on registries
.SH SYNOPSIS
\fBskopeo copy\fR [\fB--sign-by=\fRkey-ID] source-location destination-location
.PP
\fBskopeo delete\fR source-location
.PP
\fBskopeo inspect\fR image-name [\fB--raw\fR]
.PP
\fBskopeo layers\fR image-name
@ -54,12 +56,22 @@ Copy an image (manifest, filesystem layers, signatures) from one location to ano
.B source-location
and
.B destination-location
can be \fBdocker://\fRdocker-reference, \fBdir:\fRlocal-path, or \fBatomic:\fRimagestream-name\fB:\fRtag .
can be \fB\%docker://\fRdocker-reference, \fBdir:\fRlocal-path, or \fBatomic:\fRimagestream-name\fB:\fRtag .
.sp
\fB\-\-sign\-by=\fRkey-id
Add a signature by the specified key ID for image name corresponding to \fBdestination-location\fR.
Existing signatures, if any, are preserved as well.
.TP
.B delete
Mark an image for deletion. You must then run docker registry garabage collection to recover the disk space. E.g.,
.sp
\fBdocker exec -it registry bin/registry \\
.br
garbage-collect /etc/docker/registry/config.yml\fR
.sp 2
Additionally, the registry must allow deletions by setting \fB\%REGISTRY_STORAGE_DELETE_ENABLED=true\fR
for the registry daemon.
.TP
.B inspect
Return low-level information on images in a registry
.sp

View File

@ -396,3 +396,7 @@ type status struct {
// Details *StatusDetails `json:"details,omitempty"`
Code int32 `json:"code,omitempty"`
}
func (s *openshiftImageSource) Delete() error {
return fmt.Errorf("openshift#openshiftImageSource.Delete() not implmented")
}

View File

@ -33,6 +33,8 @@ type ImageSource interface {
GetLayer(digest string) (io.ReadCloser, error)
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
GetSignatures() ([][]byte, error)
// Delete image from registry, if operation is supported
Delete() error
}
// ImageDestination is a service, possibly remote (= slow), to store components of a single image.