Exemple #1
0
// DeleteImage deletes an image from a store
func (h *StorageHandlersImpl) DeleteImage(params storage.DeleteImageParams) middleware.Responder {

	ferr := func(err error, code int) middleware.Responder {
		log.Errorf("DeleteImage: error %s", err.Error())
		return storage.NewDeleteImageDefault(code).WithPayload(
			&models.Error{
				Code:    swag.Int64(int64(code)),
				Message: err.Error(),
			})
	}

	imageURL, err := util.ImageURL(params.StoreName, params.ID)
	if err != nil {
		return ferr(err, http.StatusInternalServerError)
	}

	image, err := spl.Parse(imageURL)
	if err != nil {
		return ferr(err, http.StatusInternalServerError)
	}

	op := trace.NewOperation(context.Background(), fmt.Sprintf("DeleteImage(%s)", image.ID))
	if err = h.imageCache.DeleteImage(op, image); err != nil {
		switch {
		case spl.IsErrImageInUse(err):
			return ferr(err, http.StatusLocked)

		case os.IsNotExist(err):
			return ferr(err, http.StatusNotFound)

		default:
			return ferr(err, http.StatusInternalServerError)
		}
	}

	return storage.NewDeleteImageOK()
}
Exemple #2
0
// Creates a tar archive in memory for each layer and uses this to test image creation of layers
func TestCreateImageLayers(t *testing.T) {
	numLayers := 4

	cacheStore, client, parentPath, err := setup(t)
	if !assert.NoError(t, err) {
		return
	}

	vsStore := cacheStore.DataStore.(*ImageStore)
	defer cleanup(t, client, vsStore, parentPath)

	op := trace.NewOperation(context.Background(), "test")

	storeURL, err := cacheStore.CreateImageStore(op, "testStore")
	if !assert.NoError(t, err) {
		return
	}

	// Get an image that doesn't exist and check for error
	grbg, err := cacheStore.GetImage(op, storeURL, "garbage")
	if !assert.Error(t, err) || !assert.Nil(t, grbg) {
		return
	}

	// base this image off scratch
	parent, err := cacheStore.GetImage(op, storeURL, portlayer.Scratch.ID)
	if !assert.NoError(t, err) {
		return
	}

	// Keep a list of all files we're extracting via layers so we can verify
	// they exist in the leaf layer.  Ext adds lost+found, so add it here.
	expectedFilesOnDisk := []string{"lost+found"}

	// Keep a list of images we created
	expectedImages := make(map[string]*portlayer.Image)
	expectedImages[parent.ID] = parent

	for layer := 0; layer < numLayers; layer++ {

		dirName := fmt.Sprintf("dir%d", layer)
		// Add some files to the archive.
		var files = []tarFile{
			{dirName, tar.TypeDir, ""},
			{dirName + "/readme.txt", tar.TypeReg, "This archive contains some text files."},
			{dirName + "/gopher.txt", tar.TypeReg, "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
			{dirName + "/todo.txt", tar.TypeReg, "Get animal handling license."},
		}

		for _, i := range files {
			expectedFilesOnDisk = append(expectedFilesOnDisk, i.Name)
		}

		// meta for the image
		meta := make(map[string][]byte)
		meta[dirName+"_meta"] = []byte("Some Meta")
		meta[dirName+"_moreMeta"] = []byte("Some More Meta")
		meta[dirName+"_scorpions"] = []byte("Here I am, rock you like a hurricane")

		// Tar the files
		buf, terr := tarFiles(files)
		if !assert.NoError(t, terr) {
			return
		}

		// Calculate the checksum
		h := sha256.New()
		h.Write(buf.Bytes())
		sum := fmt.Sprintf("sha256:%x", h.Sum(nil))

		// Write the image via the cache (which writes to the vsphere impl)
		writtenImage, terr := cacheStore.WriteImage(op, parent, dirName, meta, sum, buf)
		if !assert.NoError(t, terr) || !assert.NotNil(t, writtenImage) {
			return
		}

		expectedImages[dirName] = writtenImage

		// Get the image directly via the vsphere image store impl.
		vsImage, terr := vsStore.GetImage(op, parent.Store, dirName)
		if !assert.NoError(t, terr) || !assert.NotNil(t, vsImage) {
			return
		}

		assert.Equal(t, writtenImage, vsImage)

		// make the next image a child of the one we just created
		parent = writtenImage
	}

	// Test list images on the datastore
	listedImages, err := vsStore.ListImages(op, parent.Store, nil)
	if !assert.NoError(t, err) || !assert.NotNil(t, listedImages) {
		return
	}
	for _, img := range listedImages {
		if !assert.Equal(t, expectedImages[img.ID], img) {
			return
		}
	}

	// verify the disk's data by attaching the last layer rdonly
	roDisk, err := mountLayerRO(vsStore, parent)
	if !assert.NoError(t, err) {
		return
	}

	p, err := roDisk.MountPath()
	if !assert.NoError(t, err) {
		return
	}

	rodiskcleanupfunc := func() {
		if roDisk != nil {
			if roDisk.Mounted() {
				roDisk.Unmount()
			}
			if roDisk.Attached() {
				vsStore.dm.Detach(op, roDisk)
			}
		}
		os.RemoveAll(p)
	}

	filesFoundOnDisk := []string{}
	// Diff the contents of the RO file of the last child (with all of the contents)
	err = filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		f := path[len(p):]
		if f != "" {
			// strip the slash
			filesFoundOnDisk = append(filesFoundOnDisk, f[1:])
		}
		return nil
	})
	if !assert.NoError(t, err) {
		return
	}

	rodiskcleanupfunc()
	sort.Strings(filesFoundOnDisk)
	sort.Strings(expectedFilesOnDisk)

	if !assert.Equal(t, expectedFilesOnDisk, filesFoundOnDisk) {
		return
	}

	// Try to delete an intermediate image (should fail)
	exec.NewContainerCache()
	err = cacheStore.DeleteImage(op, expectedImages["dir1"])
	if !assert.Error(t, err) || !assert.True(t, portlayer.IsErrImageInUse(err)) {
		return
	}

	// Try to delete a leaf (should pass)
	leaf := expectedImages["dir"+strconv.Itoa(numLayers-1)]
	err = cacheStore.DeleteImage(op, leaf)
	if !assert.NoError(t, err) {
		return
	}

	// Get the delete image directly via the vsphere image store impl.
	deletedImage, err := vsStore.GetImage(op, parent.Store, leaf.ID)
	if !assert.Error(t, err) || !assert.Nil(t, deletedImage) || !assert.True(t, os.IsNotExist(err)) {
		return
	}
}