// WriteImage writes an image to an image store func (h *StorageHandlersImpl) WriteImage(params storage.WriteImageParams) middleware.Responder { u, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewWriteImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } parent := &spl.Image{ Store: u, ID: params.ParentID, } var meta map[string][]byte if params.Metadatakey != nil && params.Metadataval != nil { meta = map[string][]byte{*params.Metadatakey: []byte(*params.Metadataval)} } op := trace.NewOperation(context.Background(), fmt.Sprintf("WriteImage(%s)", params.ImageID)) image, err := h.imageCache.WriteImage(op, parent, params.ImageID, meta, params.Sum, params.ImageFile) if err != nil { return storage.NewWriteImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } i := convertImage(image) return storage.NewWriteImageCreated().WithPayload(i) }
// ListImages returns a list of images in a store func (handler *StorageHandlersImpl) ListImages(params storage.ListImagesParams) middleware.Responder { u, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewListImagesDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } images, err := storageImageLayer.ListImages(context.TODO(), u, params.Ids) if err != nil { return storage.NewListImagesNotFound().WithPayload( &models.Error{ Code: swag.Int64(http.StatusNotFound), Message: err.Error(), }) } result := make([]*models.Image, 0, len(images)) for _, image := range images { result = append(result, convertImage(image)) } return storage.NewListImagesOK().WithPayload(result) }
// WriteImage writes an image to an image store func (handler *StorageHandlersImpl) WriteImage(params storage.WriteImageParams) middleware.Responder { u, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewWriteImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } parent := &spl.Image{ Store: u, ID: params.ParentID, } var meta map[string][]byte if params.Metadatakey != nil && params.Metadataval != nil { meta = map[string][]byte{*params.Metadatakey: []byte(*params.Metadataval)} } image, err := storageImageLayer.WriteImage(context.TODO(), parent, params.ImageID, meta, params.Sum, params.ImageFile) if err != nil { return storage.NewWriteImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } i := convertImage(image) return storage.NewWriteImageCreated().WithPayload(i) }
// ListImages returns a list of images in a store func (h *StorageHandlersImpl) ListImages(params storage.ListImagesParams) middleware.Responder { u, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewListImagesDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } op := trace.NewOperation(context.Background(), fmt.Sprintf("ListImages(%s, %q)", u.String(), params.Ids)) images, err := h.imageCache.ListImages(op, u, params.Ids) if err != nil { return storage.NewListImagesNotFound().WithPayload( &models.Error{ Code: swag.Int64(http.StatusNotFound), Message: err.Error(), }) } result := make([]*models.Image, 0, len(images)) for _, image := range images { result = append(result, convertImage(image)) } return storage.NewListImagesOK().WithPayload(result) }
//VolumesList : Lists available volumes for use func (handler *StorageHandlersImpl) VolumesList(params storage.ListVolumesParams) middleware.Responder { defer trace.End(trace.Begin("")) var result []*models.VolumeResponse portlayerVolumes, err := storageVolumeLayer.VolumesList(context.TODO()) if err != nil { log.Error(err) return storage.NewListVolumesInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } log.Debugf("volumes fetched from list call : %#v", portlayerVolumes) for i := range portlayerVolumes { model, err := fillVolumeModel(portlayerVolumes[i]) if err != nil { log.Error(err) return storage.NewListVolumesInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } result = append(result, &model) } log.Debugf("volumes returned from list call : %#v", result) return storage.NewListVolumesOK().WithPayload(result) }
//VolumeJoin : modifies the config spec of a container to mount the specified container func (handler *StorageHandlersImpl) VolumeJoin(params storage.VolumeJoinParams) middleware.Responder { defer trace.End(trace.Begin("storage_handlers.RemoveVolume")) actualHandle := epl.GetHandle(params.JoinArgs.Handle) //Note: Name should already be populated by now. volume, err := storageVolumeLayer.VolumeGet(context.Background(), params.Name) if err != nil { log.Errorf("Volumes: StorageHandler : %#v", err) return storage.NewVolumeJoinInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } log.Infof("found volume %s for volume join", volume.ID) actualHandle, err = vsphereSpl.VolumeJoin(context.Background(), actualHandle, volume, params.JoinArgs.MountPath, params.JoinArgs.Flags) if err != nil { log.Errorf("Volumes: StorageHandler : %#v", err) return storage.NewVolumeJoinInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } log.Infof("volume %s has been joined to a container", volume.ID) return storage.NewVolumeJoinOK().WithPayload(actualHandle.String()) }
//CreateVolume : Create a Volume func (h *StorageHandlersImpl) CreateVolume(params storage.CreateVolumeParams) middleware.Responder { defer trace.End(trace.Begin("storage_handlers.CreateVolume")) //TODO: FIXME: add more errorcodes as we identify error scenarios. storeURL, err := util.VolumeStoreNameToURL(params.VolumeRequest.Store) if err != nil { log.Errorf("storagehandler: VolumeStoreName error: %s", err) return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } byteMap := make(map[string][]byte) for key, value := range params.VolumeRequest.Metadata { byteMap[key] = []byte(value) } capacity := uint64(0) if params.VolumeRequest.Capacity < 0 { capacity = uint64(1024) //FIXME: this should look for a default cap and set or fail here. } else { capacity = uint64(params.VolumeRequest.Capacity) } op := trace.NewOperation(context.Background(), fmt.Sprintf("VolumeCreate(%s)", params.VolumeRequest.Name)) volume, err := h.volumeCache.VolumeCreate(op, params.VolumeRequest.Name, storeURL, capacity*1024, byteMap) if err != nil { log.Errorf("storagehandler: VolumeCreate error: %#v", err) if os.IsExist(err) { return storage.NewCreateVolumeConflict().WithPayload(&models.Error{ Code: swag.Int64(http.StatusConflict), Message: err.Error(), }) } if _, ok := err.(spl.VolumeStoreNotFoundError); ok { return storage.NewCreateVolumeNotFound().WithPayload(&models.Error{ Code: swag.Int64(http.StatusNotFound), Message: err.Error(), }) } return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } response := volumeToCreateResponse(volume, params.VolumeRequest) return storage.NewCreateVolumeCreated().WithPayload(&response) }
func TestCreateImageStore(t *testing.T) { storageImageLayer = spl.NewLookupCache(&MockDataStore{}) s := &StorageHandlersImpl{} store := &models.ImageStore{ Name: "testStore", } params := &storage.CreateImageStoreParams{ Body: store, } result := s.CreateImageStore(*params) if !assert.NotNil(t, result) { return } // try to recreate the same image store result = s.CreateImageStore(*params) if !assert.NotNil(t, result) { return } // expect 409 since it already exists conflict := &storage.CreateImageStoreConflict{ Payload: &models.Error{ Code: swag.Int64(http.StatusConflict), Message: "An image store with that name already exists", }, } if !assert.Equal(t, conflict, result) { return } }
func configureAPI(api *operations.TodoListAPI) http.Handler { // configure the api here api.ServeError = errors.ServeError api.JSONConsumer = httpkit.JSONConsumer() api.JSONProducer = httpkit.JSONProducer() api.TodosAddOneHandler = todos.AddOneHandlerFunc(func(params todos.AddOneParams) middleware.Responder { if err := addItem(params.Body); err != nil { return todos.NewAddOneDefault(500).WithPayload(&models.Error{Code: swag.Int64(500), Message: err.Error()}) } return todos.NewAddOneCreated().WithPayload(params.Body) }) api.TodosDestroyOneHandler = todos.DestroyOneHandlerFunc(func(params todos.DestroyOneParams) middleware.Responder { if err := deleteItem(params.ID); err != nil { return todos.NewDestroyOneDefault(500).WithPayload(&models.Error{Code: swag.Int64(500), Message: err.Error()}) } return todos.NewDestroyOneNoContent() }) api.TodosFindTodosHandler = todos.FindTodosHandlerFunc(func(params todos.FindTodosParams) middleware.Responder { mergedParams := todos.NewFindTodosParams() mergedParams.Since = swag.Int64(0) if params.Since != nil { mergedParams.Since = params.Since } if params.Limit != nil { mergedParams.Limit = params.Limit } return todos.NewFindTodosOK().WithPayload(allItems(*mergedParams.Since, *mergedParams.Limit)) }) api.TodosUpdateOneHandler = todos.UpdateOneHandlerFunc(func(params todos.UpdateOneParams) middleware.Responder { if err := updateItem(params.ID, params.Body); err != nil { return todos.NewUpdateOneDefault(500).WithPayload(&models.Error{Code: swag.Int64(500), Message: err.Error()}) } return todos.NewUpdateOneOK().WithPayload(params.Body) }) api.ServerShutdown = func() {} return setupGlobalMiddleware(api.Serve(setupMiddlewares)) }
// CreateImageStore creates a new image store func (handler *StorageHandlersImpl) CreateImageStore(params storage.CreateImageStoreParams) middleware.Responder { url, err := storageImageLayer.CreateImageStore(context.TODO(), params.Body.Name) if err != nil { if os.IsExist(err) { return storage.NewCreateImageStoreConflict().WithPayload( &models.Error{ Code: swag.Int64(http.StatusConflict), Message: "An image store with that name already exists", }) } return storage.NewCreateImageStoreDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } s := &models.StoreURL{Code: swag.Int64(http.StatusCreated), URL: url.String()} return storage.NewCreateImageStoreCreated().WithPayload(s) }
// GetImage retrieves an image from a store func (handler *StorageHandlersImpl) GetImage(params storage.GetImageParams) middleware.Responder { id := params.ID url, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewGetImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } image, err := storageImageLayer.GetImage(context.TODO(), url, id) if err != nil { e := &models.Error{Code: swag.Int64(http.StatusNotFound), Message: err.Error()} return storage.NewGetImageNotFound().WithPayload(e) } result := convertImage(image) return storage.NewGetImageOK().WithPayload(result) }
// CreateImageStore creates a new image store func (h *StorageHandlersImpl) CreateImageStore(params storage.CreateImageStoreParams) middleware.Responder { op := trace.NewOperation(context.Background(), fmt.Sprintf("CreateImageStore(%s)", params.Body.Name)) url, err := h.imageCache.CreateImageStore(op, params.Body.Name) if err != nil { if os.IsExist(err) { return storage.NewCreateImageStoreConflict().WithPayload( &models.Error{ Code: swag.Int64(http.StatusConflict), Message: "An image store with that name already exists", }) } return storage.NewCreateImageStoreDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } s := &models.StoreURL{Code: swag.Int64(http.StatusCreated), URL: url.String()} return storage.NewCreateImageStoreCreated().WithPayload(s) }
func (handler *KvHandlersImpl) PutValueHandler(params kv.PutValueParams) middleware.Responder { defer trace.End(trace.Begin(*params.KeyValue.Key)) err := handler.defaultStore.Put(context.Background(), *params.KeyValue.Key, []byte(*params.KeyValue.Value)) if err != nil { log.Errorf("Error Setting Key/Value: %s", err.Error()) return kv.NewGetValueInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } return kv.NewPutValueOK() }
// GetImage retrieves an image from a store func (h *StorageHandlersImpl) GetImage(params storage.GetImageParams) middleware.Responder { id := params.ID url, err := util.ImageStoreNameToURL(params.StoreName) if err != nil { return storage.NewGetImageDefault(http.StatusInternalServerError).WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } op := trace.NewOperation(context.Background(), fmt.Sprintf("GetImage(%s)", id)) image, err := h.imageCache.GetImage(op, url, id) if err != nil { e := &models.Error{Code: swag.Int64(http.StatusNotFound), Message: err.Error()} return storage.NewGetImageNotFound().WithPayload(e) } result := convertImage(image) return storage.NewGetImageOK().WithPayload(result) }
//CreateVolume : Create a Volume func (handler *StorageHandlersImpl) CreateVolume(params storage.CreateVolumeParams) middleware.Responder { defer trace.End(trace.Begin("storage_handlers.CreateVolume")) //TODO: FIXME: add more errorcodes as we identify error scenarios. storeURL, err := util.VolumeStoreNameToURL(params.VolumeRequest.Store) if err != nil { log.Errorf("storagehandler: VolumeStoreName error: %s", err) return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } byteMap := make(map[string][]byte) for key, value := range params.VolumeRequest.Metadata { byteMap[key] = []byte(value) } capacity := uint64(0) if params.VolumeRequest.Capacity < 0 { capacity = uint64(1024) //FIXME: this should look for a default cap and set or fail here. } else { capacity = uint64(params.VolumeRequest.Capacity) } volume, err := storageVolumeLayer.VolumeCreate(context.TODO(), params.VolumeRequest.Name, storeURL, capacity*1024, byteMap) if err != nil { log.Errorf("storagehandler: VolumeCreate error: %s", err) return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } response := volumeToCreateResponse(volume, params.VolumeRequest) return storage.NewCreateVolumeCreated().WithPayload(&response) }
//GetVolume : Gets a handle to a volume func (h *StorageHandlersImpl) GetVolume(params storage.GetVolumeParams) middleware.Responder { defer trace.End(trace.Begin(params.Name)) op := trace.NewOperation(context.Background(), fmt.Sprintf("VolumeGet(%s)", params.Name)) data, err := h.volumeCache.VolumeGet(op, params.Name) if err == os.ErrNotExist { return storage.NewGetVolumeNotFound().WithPayload(&models.Error{ Code: swag.Int64(http.StatusNotFound), Message: err.Error(), }) } response, err := fillVolumeModel(data) if err != nil { return storage.NewListVolumesInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } log.Debugf("VolumeGet returned : %#v", response) return storage.NewGetVolumeOK().WithPayload(&response) }
func (handler *KvHandlersImpl) DeleteValueHandler(params kv.DeleteValueParams) middleware.Responder { defer trace.End(trace.Begin(params.Key)) err := handler.defaultStore.Delete(trace.NewOperation(context.Background(), "DeleteValue"), params.Key) if err != nil { switch err { case kvstore.ErrKeyNotFound: return kv.NewDeleteValueNotFound() default: log.Errorf("Error deleting Key/Value: %s", err.Error()) return kv.NewGetValueInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } } return kv.NewDeleteValueOK() }
func (handler *KvHandlersImpl) GetValueHandler(params kv.GetValueParams) middleware.Responder { defer trace.End(trace.Begin(params.Key)) val, err := handler.defaultStore.Get(params.Key) if err != nil { switch err { case kvstore.ErrKeyNotFound: return kv.NewGetValueNotFound() default: log.Errorf("Error Getting Key/Value: %s", err.Error()) return kv.NewGetValueInternalServerError().WithPayload(&models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } } s := string(val) return kv.NewGetValueOK().WithPayload(&models.KeyValue{Key: ¶ms.Key, Value: &s}) }
// VolumeStoresList lists the configured volume stores and their datastore path URIs. func (handler *StorageHandlersImpl) VolumeStoresList() middleware.Responder { defer trace.End(trace.Begin("storage_handlers.VolumeStoresList")) stores, err := storageVolumeLayer.VolumeStoresList(context.TODO()) if err != nil { return storage.NewVolumeStoresListInternalServerError().WithPayload( &models.Error{ Code: swag.Int64(http.StatusInternalServerError), Message: err.Error(), }) } resp := &models.VolumeStoresListResponse{ Stores: make(map[string]string), } for name, ds := range stores { resp.Stores[name] = ds.String() } return storage.NewVolumeStoresListOK().WithPayload(resp) }
// 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() }
func TestGetImage(t *testing.T) { storageImageLayer = spl.NewLookupCache(&MockDataStore{}) s := &StorageHandlersImpl{} params := &storage.GetImageParams{ ID: testImageID, StoreName: testStoreName, } // expect 404 since no image store exists by that name storeNotFound := &storage.GetImageNotFound{ Payload: &models.Error{ Code: swag.Int64(http.StatusNotFound), Message: fmt.Sprintf("store (%s) doesn't exist", testStoreURL.String()), }, } result := s.GetImage(*params) if !assert.NotNil(t, result) { return } if !assert.Equal(t, storeNotFound, result) { return } // create the image store url, err := storageImageLayer.CreateImageStore(context.TODO(), testStoreName) // TODO(jzt): these are testing NameLookupCache, do we need them here? if !assert.Nil(t, err, "Error while creating image store") { return } if !assert.Equal(t, testStoreURL.String(), url.String()) { return } // expect 404 since no image exists by that name in that store imageNotFound := &storage.GetImageNotFound{ Payload: &models.Error{ Code: swag.Int64(http.StatusNotFound), Message: fmt.Sprintf("store (%s) doesn't have image %s", testStoreURL.String(), testImageID), }, } // try GetImage again result = s.GetImage(*params) if !assert.NotNil(t, result) { return } if !assert.Equal(t, imageNotFound, result) { return } // add image to store parent := spl.Image{ ID: "scratch", SelfLink: nil, Parent: nil, Store: &testStoreURL, } expectedMeta := make(map[string][]byte) expectedMeta["foo"] = []byte("bar") // add the image to the store image, err := storageImageLayer.WriteImage(context.TODO(), &parent, testImageID, expectedMeta, testImageSum, nil) if !assert.NoError(t, err) || !assert.NotNil(t, image) { return } eMeta := make(map[string]string) eMeta["foo"] = "bar" // expect our image back now that we've created it expected := &storage.GetImageOK{ Payload: &models.Image{ ID: image.ID, SelfLink: nil, Parent: nil, Store: testStoreURL.String(), Metadata: eMeta, }, } result = s.GetImage(*params) if !assert.NotNil(t, result) { return } if !assert.Equal(t, expected, result) { return } }
func TestListImages(t *testing.T) { storageImageLayer = spl.NewLookupCache(&MockDataStore{}) s := &StorageHandlersImpl{} params := &storage.ListImagesParams{ StoreName: testStoreName, } // expect 404 if image store doesn't exist notFound := &storage.ListImagesNotFound{ Payload: &models.Error{ Code: swag.Int64(http.StatusNotFound), Message: fmt.Sprintf("store (%s) doesn't exist", testStoreURL.String()), }, } outImages := s.ListImages(*params) if !assert.NotNil(t, outImages) { return } if !assert.Equal(t, notFound, outImages) { return } // create the image store url, err := storageImageLayer.CreateImageStore(context.TODO(), testStoreName) if !assert.NoError(t, err) { return } if !assert.NotNil(t, url) { return } // create a set of images images := make(map[string]*spl.Image) parent := spl.Scratch parent.Store = &testStoreURL for i := 1; i < 50; i++ { id := fmt.Sprintf("id-%d", i) img, err := storageImageLayer.WriteImage(context.TODO(), &parent, id, nil, testImageSum, nil) if !assert.NoError(t, err) { return } if !assert.NotNil(t, img) { return } images[id] = img } // List all images outImages = s.ListImages(*params) assert.IsType(t, &storage.ListImagesOK{}, outImages) assert.Equal(t, len(outImages.(*storage.ListImagesOK).Payload), len(images)) for _, img := range outImages.(*storage.ListImagesOK).Payload { _, ok := images[img.ID] if !assert.True(t, ok) { return } } // List specific images var ids []string // query for odd-numbered image ids for i := 1; i < 50; i += 2 { ids = append(ids, fmt.Sprintf("id-%d", i)) } params.Ids = ids outImages = s.ListImages(*params) assert.IsType(t, &storage.ListImagesOK{}, outImages) assert.Equal(t, len(outImages.(*storage.ListImagesOK).Payload), len(ids)) outmap := make(map[string]*models.Image) for _, image := range outImages.(*storage.ListImagesOK).Payload { outmap[image.ID] = image } // ensure no even-numbered image ids in our result for i := 2; i < 50; i += 2 { id := fmt.Sprintf("id-%d", i) _, ok := outmap[id] if !assert.False(t, ok) { return } } }