-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add test for volume snapshot #83
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good.
Could you also implement snapshots in the mock driver so that we could test the changes and fix any bugs that are not obvious?
pkg/sanity/controller.go
Outdated
|
||
It("should fail when no name is provided", func() { | ||
|
||
req := &csi.CreateSnapshotRequest{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to add the other attributes here and just exclude name.
pkg/sanity/controller.go
Outdated
BeforeEach(func() { | ||
c = csi.NewControllerClient(conn) | ||
|
||
if !isControllerCapabilitySupported(c, csi.ControllerServiceCapability_RPC_LIST_VOLUMES) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be ControllerServiceCapability_RPC_LIST_SNAPSHOTS
. Looks like this is causing the test to fail.
@darkowlzz Thanks for your review, will update it. |
ff727c2
to
a709649
Compare
/cc @jingxu97 @xing-yang |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the mock driver implementation.
I've suggested some improvements.
mock/service/controller.go
Outdated
return nil, status.Error(codes.InvalidArgument, "Not Implemented") | ||
// Check arguments | ||
if len(req.GetName()) == 0 { | ||
return nil, status.Error(codes.InvalidArgument, "Name missing in request") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Snapshot Name cannot be empty"
? Maybe it's better to be consistent with CreateVolume
error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
mock/service/controller.go
Outdated
return nil, status.Error(codes.InvalidArgument, "Name missing in request") | ||
} | ||
if len(req.GetSourceVolumeId()) == 0 { | ||
return nil, status.Error(codes.InvalidArgument, "SourceVolumeId missing in request") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Snapshot SourceVolumeId cannot be empty"
? Maybe it's better to be consistent with CreateVolume
error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
mock/service/controller.go
Outdated
// Requested snapshot name already exists | ||
if v.GetSourceVolumeId() == req.SourceVolumeId { | ||
return nil, status.Error(codes.AlreadyExists, | ||
fmt.Sprintf("Snapshot with name %s already exists", req.GetName())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the snapshot exists with the same source volume ID, I think it should return OK.
And there should be a check for parameters as well.
If the source volume ID and parameters are equal, return OK, else return ALREADY_EXISTS error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. If source_volume_id, create_snapshot_secrets, and parameters are the same for the same snapshot name, it should return OK for idempotency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated for check parameters also, I do not think we should check create_snapshot_secrets that may change every request.
mock/service/service.go
Outdated
ctx context.Context, name string) (int, csi.Snapshot) { | ||
|
||
return s.findSnapshot("name", name) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a newline at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -48,6 +48,11 @@ func verifyVolumeInfo(v *csi.Volume) { | |||
Expect(v.GetId()).NotTo(BeEmpty()) | |||
} | |||
|
|||
func verifySnapshotInfo(snapshot *csi.Snapshot) { | |||
Expect(snapshot).NotTo(BeNil()) | |||
Expect(snapshot.GetId()).NotTo(BeEmpty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can add some more verification here.
SourceVolumeID
is REQUIRED.
Snapshot definition talks about SizeBytes
.
The size of the volume MUST NOT be less than the size of the source snapshot.
Let's add those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated for check attributes that is REQUIRED. As for SizeBytes
,
The purpose of this field is to give CO guidance on how much space is needed to
// create a volume from this snapshot. The size of the volume MUST NOT
// be less than the size of the source snapshot.
I think it is used to CO when restore volume from a snapshot to verify there is enough space. So we do not need verify here.
mock/service/controller.go
Outdated
} | ||
|
||
// case 2: SourceVolumeId is not empty, return snapshots that match the source volume id. | ||
if len(req.SourceVolumeId) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would recommend using req.GetSourceVolumeId()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
mock/service/controller.go
Outdated
}, | ||
}, | ||
}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to consider both req.GetSnapshotId()
and req.GetSourceVolumeID
when they aren't empty. If the volume received from ID has a different source volume ID, do not include them in the snapshot list.
mock/service/controller.go
Outdated
|
||
// case 2: SourceVolumeId is not empty, return snapshots that match the source volume id. | ||
if len(req.SourceVolumeId) != 0 { | ||
i, snapshot := s.findSnapshotNoLock("id", req.SourceVolumeId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"id"
-> "sourceVolumeId"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done
.idea/workspace.xml
Outdated
</provider> | ||
</entry> | ||
</component> | ||
</project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this file :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, please remove this file.
mock/service/controller.go
Outdated
@@ -271,7 +271,7 @@ func (s *service) ListVolumes( | |||
i int | |||
j = startingToken | |||
entries = make( | |||
[]*csi.ListVolumesResponse_Entry, | |||
[]*csi.ListVolumesResponse_Entry, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked better before :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Seems that there are two CI errors: Go fmt errors and some failed csi-sanity errors |
0888172
to
8ab5016
Compare
@lpabon @darkowlzz updated all comments, PTAL |
mock/service/controller.go
Outdated
// themselves have fields that are. | ||
copy(s.snapshots[i:], s.snapshots[i+1:]) | ||
s.snapshots[len(s.snapshots)-1] = Snapshot{} | ||
s.snapshots = s.snapshots[:len(s.snapshots)-1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line 440 removes the last element which was just initialized in line 439. It looks to me that line 439 is not needed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just imitate the code about volume deletion, make sense, will delete it.
mock/service/controller.go
Outdated
// locking the service's snapshot slice for the duration of the | ||
// ListSnapshots RPC. | ||
var snapshots []csi.Snapshot | ||
func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've never seen an anonymous function without a go
statement or assigned to a variable. Just curious, but why use this style?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, when I review, I'm not only looking for bugs, but I am looking at maintenance. If it is hard to maintain, even if it works, it should be redone.
mock/service/controller.go
Outdated
// ListSnapshots RPC. | ||
var snapshots []csi.Snapshot | ||
func() { | ||
s.snapshotsRWL.RLock() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have to be very careful creating a deadlock situation sometime in the future. I would instead place these locks as close to the object as possible. I would suggest creating a new data structure object that handles the the work with the list. It supports Insert, Delete, List, Find, etc. and it is the one managing the lock
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just imitate the code about volume deletion, make sense, I will update the code and commit a separate pr to change the volume part.
} | ||
|
||
func (s *service) ListSnapshots(ctx context.Context, | ||
req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) { | ||
return nil, status.Error(codes.InvalidArgument, "Not Implemented") | ||
|
||
// case 1: SnapshotId is not empty, return snapshots that match the snapshot id. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is too large, do you mind breaking it up by the cases you have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sense, will update.
0a5929c
to
626cfbb
Compare
add test for volume snapshot
/assign @lpabon