From f907fc4b3e530ea6b3722bcf7736107882be4f6e Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 15 Jun 2018 13:44:36 +0530 Subject: [PATCH] sanity: Add more ControllerPublishVolume tests Adds tests for: * should fail when the volume does not exist * should fail when the node does not exist * should fail when the volume is already published but is incompatible --- mock/service/controller.go | 33 +++++- pkg/sanity/controller.go | 206 +++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 2 deletions(-) diff --git a/mock/service/controller.go b/mock/service/controller.go index d4a44f84..53cee9ee 100644 --- a/mock/service/controller.go +++ b/mock/service/controller.go @@ -16,6 +16,7 @@ import ( const ( MaxStorageCapacity = tib + ReadOnlyKey = "readonly" ) func (s *service) CreateVolume( @@ -135,21 +136,48 @@ func (s *service) ControllerPublishVolume( // Check to see if the volume is already published. if device := v.Attributes[devPathKey]; device != "" { + var volRo bool + var roVal string + if ro, ok := v.Attributes[ReadOnlyKey]; ok { + roVal = ro + } + + if roVal == "true" { + volRo = true + } else { + volRo = false + } + + // Check if readonly flag is compatible with the publish request. + if req.GetReadonly() != volRo { + return nil, status.Error(codes.AlreadyExists, "Volume published but has incompatible readonly flag") + } + return &csi.ControllerPublishVolumeResponse{ PublishInfo: map[string]string{ - "device": device, + "device": device, + "readonly": roVal, }, }, nil } + var roVal string + if req.GetReadonly() { + roVal = "true" + } else { + roVal = "false" + } + // Publish the volume. device := "/dev/mock" v.Attributes[devPathKey] = device + v.Attributes[ReadOnlyKey] = roVal s.vols[i] = v return &csi.ControllerPublishVolumeResponse{ PublishInfo: map[string]string{ - "device": device, + "device": device, + "readonly": roVal, }, }, nil } @@ -192,6 +220,7 @@ func (s *service) ControllerUnpublishVolume( // Unpublish the volume. delete(v.Attributes, devPathKey) + delete(v.Attributes, ReadOnlyKey) s.vols[i] = v return &csi.ControllerUnpublishVolumeResponse{}, nil diff --git a/pkg/sanity/controller.go b/pkg/sanity/controller.go index 0fb22392..d40e8795 100644 --- a/pkg/sanity/controller.go +++ b/pkg/sanity/controller.go @@ -806,6 +806,212 @@ var _ = Describe("ControllerPublishVolume [Controller Server]", func() { _, err = c.DeleteVolume(context.Background(), delReq) Expect(err).NotTo(HaveOccurred()) }) + + It("should fail when the volume does not exist", func() { + + By("calling controller publish on a non-existent volume") + + pubReq := &csi.ControllerPublishVolumeRequest{ + VolumeId: "some-vol-id", + NodeId: "some-node-id", + VolumeCapability: &csi.VolumeCapability{ + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + Readonly: false, + } + + if secrets != nil { + pubReq.ControllerPublishSecrets = secrets.ControllerPublishVolumeSecret + } + + conpubvol, err := c.ControllerPublishVolume(context.Background(), pubReq) + Expect(err).To(HaveOccurred()) + Expect(conpubvol).To(BeNil()) + + serverError, ok := status.FromError(err) + Expect(ok).To(BeTrue()) + Expect(serverError.Code()).To(Equal(codes.NotFound)) + }) + + It("should fail when the node does not exist", func() { + + // Create Volume First + By("creating a single node writer volume") + name := "sanity" + req := &csi.CreateVolumeRequest{ + Name: name, + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + }, + } + + if secrets != nil { + req.ControllerCreateSecrets = secrets.CreateVolumeSecret + } + + vol, err := c.CreateVolume(context.Background(), req) + Expect(err).NotTo(HaveOccurred()) + Expect(vol).NotTo(BeNil()) + Expect(vol.GetVolume()).NotTo(BeNil()) + Expect(vol.GetVolume().GetId()).NotTo(BeEmpty()) + + // ControllerPublishVolume + By("calling controllerpublish on that volume") + + pubReq := &csi.ControllerPublishVolumeRequest{ + VolumeId: vol.GetVolume().GetId(), + NodeId: "some-fake-node-id", + VolumeCapability: &csi.VolumeCapability{ + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + Readonly: false, + } + + if secrets != nil { + pubReq.ControllerPublishSecrets = secrets.ControllerPublishVolumeSecret + } + + conpubvol, err := c.ControllerPublishVolume(context.Background(), pubReq) + Expect(err).To(HaveOccurred()) + Expect(conpubvol).To(BeNil()) + + serverError, ok := status.FromError(err) + Expect(ok).To(BeTrue()) + Expect(serverError.Code()).To(Equal(codes.NotFound)) + + By("cleaning up deleting the volume") + + delReq := &csi.DeleteVolumeRequest{ + VolumeId: vol.GetVolume().GetId(), + } + + if secrets != nil { + delReq.ControllerDeleteSecrets = secrets.DeleteVolumeSecret + } + + _, err = c.DeleteVolume(context.Background(), delReq) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should fail when the volume is already published but is incompatible", func() { + + // Create Volume First + By("creating a single node writer volume") + name := "sanity" + req := &csi.CreateVolumeRequest{ + Name: name, + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + }, + } + + if secrets != nil { + req.ControllerCreateSecrets = secrets.CreateVolumeSecret + } + + vol, err := c.CreateVolume(context.Background(), req) + Expect(err).NotTo(HaveOccurred()) + Expect(vol).NotTo(BeNil()) + Expect(vol.GetVolume()).NotTo(BeNil()) + Expect(vol.GetVolume().GetId()).NotTo(BeEmpty()) + + By("getting a node id") + nid, err := n.NodeGetId( + context.Background(), + &csi.NodeGetIdRequest{}) + Expect(err).NotTo(HaveOccurred()) + Expect(nid).NotTo(BeNil()) + Expect(nid.GetNodeId()).NotTo(BeEmpty()) + + // ControllerPublishVolume + By("calling controllerpublish on that volume") + + pubReq := &csi.ControllerPublishVolumeRequest{ + VolumeId: vol.GetVolume().GetId(), + NodeId: nid.GetNodeId(), + VolumeCapability: &csi.VolumeCapability{ + AccessType: &csi.VolumeCapability_Mount{ + Mount: &csi.VolumeCapability_MountVolume{}, + }, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + Readonly: false, + } + + if secrets != nil { + pubReq.ControllerPublishSecrets = secrets.ControllerPublishVolumeSecret + } + + conpubvol, err := c.ControllerPublishVolume(context.Background(), pubReq) + Expect(err).NotTo(HaveOccurred()) + Expect(conpubvol).NotTo(BeNil()) + + // Publish again with different attributes. + pubReq.Readonly = true + + conpubvol, err = c.ControllerPublishVolume(context.Background(), pubReq) + Expect(err).To(HaveOccurred()) + Expect(conpubvol).To(BeNil()) + + serverError, ok := status.FromError(err) + Expect(ok).To(BeTrue()) + Expect(serverError.Code()).To(Equal(codes.AlreadyExists)) + + By("cleaning up unpublishing the volume") + + unpubReq := &csi.ControllerUnpublishVolumeRequest{ + VolumeId: vol.GetVolume().GetId(), + // NodeID is optional in ControllerUnpublishVolume + NodeId: nid.GetNodeId(), + } + + if secrets != nil { + unpubReq.ControllerUnpublishSecrets = secrets.ControllerUnpublishVolumeSecret + } + + conunpubvol, err := c.ControllerUnpublishVolume(context.Background(), unpubReq) + Expect(err).NotTo(HaveOccurred()) + Expect(conunpubvol).NotTo(BeNil()) + + By("cleaning up deleting the volume") + + delReq := &csi.DeleteVolumeRequest{ + VolumeId: vol.GetVolume().GetId(), + } + + if secrets != nil { + delReq.ControllerDeleteSecrets = secrets.DeleteVolumeSecret + } + + _, err = c.DeleteVolume(context.Background(), delReq) + Expect(err).NotTo(HaveOccurred()) + }) }) var _ = Describe("ControllerUnpublishVolume [Controller Server]", func() {