From 675b8d83071446d7d1f2df7f6e2005a88d0107a5 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Tue, 3 Apr 2018 09:32:36 +0200 Subject: [PATCH] Add support for ControllerPublishSecrets --- pkg/connection/connection.go | 12 +-- pkg/connection/connection_test.go | 43 ++++++++- pkg/controller/csi_handler.go | 33 ++++++- pkg/controller/csi_handler_test.go | 141 +++++++++++++++++++++++++---- pkg/controller/framework_test.go | 21 ++++- 5 files changed, 219 insertions(+), 31 deletions(-) diff --git a/pkg/connection/connection.go b/pkg/connection/connection.go index 91c4555ca..788e695e6 100644 --- a/pkg/connection/connection.go +++ b/pkg/connection/connection.go @@ -51,13 +51,13 @@ type CSIConnection interface { // detached from the node. "false" means that the volume may be either // detached, attaching or attached and caller should retry to get the final // status. - Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes map[string]string) (metadata map[string]string, detached bool, err error) + Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes, secrets map[string]string) (metadata map[string]string, detached bool, err error) // Detach given volume from given node. Note that "detached" is returned on // error and means that the volume is for sure detached from the node. // "false" means that the volume may or may not be detached and caller // should retry. - Detach(ctx context.Context, volumeID string, nodeID string) (detached bool, err error) + Detach(ctx context.Context, volumeID string, nodeID string, secrets map[string]string) (detached bool, err error) // Probe checks that the CSI driver is ready to process requests Probe(ctx context.Context) error @@ -192,7 +192,7 @@ func (c *csiConnection) SupportsPluginControllerService(ctx context.Context) (bo return false, nil } -func (c *csiConnection) Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes map[string]string) (metadata map[string]string, detached bool, err error) { +func (c *csiConnection) Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes, secrets map[string]string) (metadata map[string]string, detached bool, err error) { client := csi.NewControllerClient(c.conn) req := csi.ControllerPublishVolumeRequest{ @@ -201,7 +201,7 @@ func (c *csiConnection) Attach(ctx context.Context, volumeID string, readOnly bo VolumeCapability: caps, Readonly: readOnly, VolumeAttributes: attributes, - ControllerPublishSecrets: nil, + ControllerPublishSecrets: secrets, } rsp, err := client.ControllerPublishVolume(ctx, &req) @@ -211,13 +211,13 @@ func (c *csiConnection) Attach(ctx context.Context, volumeID string, readOnly bo return rsp.PublishInfo, false, nil } -func (c *csiConnection) Detach(ctx context.Context, volumeID string, nodeID string) (detached bool, err error) { +func (c *csiConnection) Detach(ctx context.Context, volumeID string, nodeID string, secrets map[string]string) (detached bool, err error) { client := csi.NewControllerClient(c.conn) req := csi.ControllerUnpublishVolumeRequest{ VolumeId: volumeID, NodeId: nodeID, - ControllerUnpublishSecrets: nil, + ControllerUnpublishSecrets: secrets, } _, err = client.ControllerUnpublishVolume(ctx, &req) diff --git a/pkg/connection/connection_test.go b/pkg/connection/connection_test.go index 15247f413..97d81cc5d 100644 --- a/pkg/connection/connection_test.go +++ b/pkg/connection/connection_test.go @@ -358,6 +358,13 @@ func TestAttach(t *testing.T) { VolumeAttributes: map[string]string{"foo": "bar"}, Readonly: false, } + secretsRequest := &csi.ControllerPublishVolumeRequest{ + VolumeId: defaultVolumeID, + NodeId: defaultNodeID, + VolumeCapability: defaultCaps, + ControllerPublishSecrets: map[string]string{"foo": "bar"}, + Readonly: false, + } tests := []struct { name string @@ -366,6 +373,7 @@ func TestAttach(t *testing.T) { caps *csi.VolumeCapability readonly bool attributes map[string]string + secrets map[string]string input *csi.ControllerPublishVolumeRequest output *csi.ControllerPublishVolumeResponse injectError codes.Code @@ -447,6 +455,20 @@ func TestAttach(t *testing.T) { expectedInfo: publishVolumeInfo, expectDetached: false, }, + { + name: "secrets", + volumeID: defaultVolumeID, + nodeID: defaultNodeID, + caps: defaultCaps, + secrets: map[string]string{"foo": "bar"}, + input: secretsRequest, + output: &csi.ControllerPublishVolumeResponse{ + PublishInfo: publishVolumeInfo, + }, + expectError: false, + expectedInfo: publishVolumeInfo, + expectDetached: false, + }, } mockController, driver, _, controllerServer, csiConn, err := createMockServer(t) @@ -470,7 +492,7 @@ func TestAttach(t *testing.T) { controllerServer.EXPECT().ControllerPublishVolume(gomock.Any(), in).Return(out, injectedErr).Times(1) } - publishInfo, detached, err := csiConn.Attach(context.Background(), test.volumeID, test.readonly, test.nodeID, test.caps, test.attributes) + publishInfo, detached, err := csiConn.Attach(context.Background(), test.volumeID, test.readonly, test.nodeID, test.caps, test.attributes, test.secrets) if test.expectError && err == nil { t.Errorf("test %q: Expected error, got none", test.name) } @@ -496,10 +518,17 @@ func TestDetachAttach(t *testing.T) { NodeId: defaultNodeID, } + secretsRequest := &csi.ControllerUnpublishVolumeRequest{ + VolumeId: defaultVolumeID, + NodeId: defaultNodeID, + ControllerUnpublishSecrets: map[string]string{"foo": "bar"}, + } + tests := []struct { name string volumeID string nodeID string + secrets map[string]string input *csi.ControllerUnpublishVolumeRequest output *csi.ControllerUnpublishVolumeResponse injectError codes.Code @@ -515,6 +544,16 @@ func TestDetachAttach(t *testing.T) { expectError: false, expectDetached: true, }, + { + name: "secrets", + volumeID: defaultVolumeID, + nodeID: defaultNodeID, + secrets: map[string]string{"foo": "bar"}, + input: secretsRequest, + output: &csi.ControllerUnpublishVolumeResponse{}, + expectError: false, + expectDetached: true, + }, { name: "gRPC final error", volumeID: defaultVolumeID, @@ -558,7 +597,7 @@ func TestDetachAttach(t *testing.T) { controllerServer.EXPECT().ControllerUnpublishVolume(gomock.Any(), in).Return(out, injectedErr).Times(1) } - detached, err := csiConn.Detach(context.Background(), test.volumeID, test.nodeID) + detached, err := csiConn.Detach(context.Background(), test.volumeID, test.nodeID, test.secrets) if test.expectError && err == nil { t.Errorf("test %q: Expected error, got none", test.name) } diff --git a/pkg/controller/csi_handler.go b/pkg/controller/csi_handler.go index cada5e7ea..351b7da7e 100644 --- a/pkg/controller/csi_handler.go +++ b/pkg/controller/csi_handler.go @@ -239,6 +239,10 @@ func (h *csiHandler) csiAttach(va *storage.VolumeAttachment) (*storage.VolumeAtt if err != nil { return va, nil, err } + secrets, err := h.getCredentialsFromPV(pv) + if err != nil { + return va, nil, err + } node, err := h.nodeLister.Get(va.Spec.NodeName) if err != nil { @@ -257,7 +261,7 @@ func (h *csiHandler) csiAttach(va *storage.VolumeAttachment) (*storage.VolumeAtt ctx := context.TODO() // We're not interested in `detached` return value, the controller will // issue Detach to be sure the volume is really detached. - publishInfo, _, err := h.csiConnection.Attach(ctx, volumeHandle, readOnly, nodeID, volumeCapabilities, attributes) + publishInfo, _, err := h.csiConnection.Attach(ctx, volumeHandle, readOnly, nodeID, volumeCapabilities, attributes, secrets) if err != nil { return va, nil, err } @@ -278,6 +282,10 @@ func (h *csiHandler) csiDetach(va *storage.VolumeAttachment) (*storage.VolumeAtt if err != nil { return va, err } + secrets, err := h.getCredentialsFromPV(pv) + if err != nil { + return va, err + } node, err := h.nodeLister.Get(va.Spec.NodeName) if err != nil { @@ -289,7 +297,7 @@ func (h *csiHandler) csiDetach(va *storage.VolumeAttachment) (*storage.VolumeAtt } ctx := context.TODO() - detached, err := h.csiConnection.Detach(ctx, volumeHandle, nodeID) + detached, err := h.csiConnection.Detach(ctx, volumeHandle, nodeID, secrets) if err != nil && !detached { // The volume may not be fully detached. Save the error and try again // after backoff. @@ -407,3 +415,24 @@ func (h *csiHandler) SyncNewOrUpdatedPersistentVolume(pv *v1.PersistentVolume) { return } + +func (h *csiHandler) getCredentialsFromPV(pv *v1.PersistentVolume) (map[string]string, error) { + if pv.Spec.PersistentVolumeSource.CSI == nil { + return nil, fmt.Errorf("persistent volume does not contain CSI volume source") + } + secretRef := pv.Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef + if secretRef == nil { + return nil, nil + } + + secret, err := h.client.CoreV1().Secrets(secretRef.Namespace).Get(secretRef.Name, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to load secret \"%s/%s\": %s", secretRef.Namespace, secretRef.Name, err) + } + credentials := map[string]string{} + for key, value := range secret.Data { + credentials[key] = string(value) + } + + return credentials, nil +} diff --git a/pkg/controller/csi_handler_test.go b/pkg/controller/csi_handler_test.go index 39365bc52..455cf2f00 100644 --- a/pkg/controller/csi_handler_test.go +++ b/pkg/controller/csi_handler_test.go @@ -90,6 +90,14 @@ func pvWithAttributes(pv *v1.PersistentVolume, attributes map[string]string) *v1 return pv } +func pvWithSecret(pv *v1.PersistentVolume, secretName string) *v1.PersistentVolume { + pv.Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef = &v1.SecretReference{ + Name: secretName, + Namespace: "default", + } + return pv +} + func node() *v1.Node { return &v1.Node{ ObjectMeta: metav1.ObjectMeta{ @@ -101,6 +109,27 @@ func node() *v1.Node { } } +func emptySecret() *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "emptySecret", + Namespace: "default", + }, + } +} + +func secret() *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "foo": []byte("bar"), + }, + } +} + func TestCSIHandler(t *testing.T) { vaGroupResourceVersion := schema.GroupVersionResource{ Group: storage.GroupName, @@ -112,9 +141,15 @@ func TestCSIHandler(t *testing.T) { Version: "v1", Resource: "persistentvolumes", } + secretGroupResourceVersion := schema.GroupVersionResource{ + Group: v1.GroupName, + Version: "v1", + Resource: "secrets", + } var noMetadata map[string]string = nil var noAttrs map[string]string = nil + var noSecrets map[string]string = nil var notDetached = false var detached = true var success error = nil @@ -133,7 +168,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -146,7 +181,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -159,9 +194,47 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, map[string]string{"foo": "bar"}, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, map[string]string{"foo": "bar"}, noSecrets, success, notDetached, noMetadata}, + }, + }, + { + name: "VolumeAttachment with secrets -> successful attachment", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "secret"), node(), secret()}, + updatedVA: va(false, ""), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "secret"), + // Finalizer is saved first + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(false /*attached*/, fin)), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), + }, + expectedCSICalls: []csiCall{ + {"attach", testVolumeHandle, testNodeID, noAttrs, map[string]string{"foo": "bar"}, success, notDetached, noMetadata}, + }, + }, + { + name: "VolumeAttachment with empty secrets -> successful attachment", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "emptySecret"), node(), emptySecret()}, + updatedVA: va(false, ""), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "emptySecret"), + // Finalizer is saved first + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(false /*attached*/, fin)), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), + }, + expectedCSICalls: []csiCall{ + {"attach", testVolumeHandle, testNodeID, noAttrs, map[string]string{}, success, notDetached, noMetadata}, }, }, + { + name: "VolumeAttachment with missing secrets -> error", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "unknownSecret"), node()}, + updatedVA: va(false, ""), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "unknownSecret"), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, vaWithAttachError(va(false, ""), "failed to load secret \"default/unknownSecret\": secrets \"unknownSecret\" not found")), + }, + expectedCSICalls: []csiCall{}, + }, { name: "VolumeAttachment updated -> PV finalizer is added", initialObjects: []runtime.Object{pv(), node()}, @@ -174,7 +247,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -212,7 +285,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -241,7 +314,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, vaWithMetadata(va(true, fin), map[string]string{"foo": "bar"})), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, map[string]string{"foo": "bar"}}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, map[string]string{"foo": "bar"}}, }, }, { @@ -334,7 +407,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -365,8 +438,8 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, { @@ -380,8 +453,8 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, va(true /*attached*/, fin)), }, expectedCSICalls: []csiCall{ - {"attach", testVolumeHandle, testNodeID, noAttrs, fmt.Errorf("mock error"), notDetached, noMetadata}, - {"attach", testVolumeHandle, testNodeID, noAttrs, success, notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, fmt.Errorf("mock error"), notDetached, noMetadata}, + {"attach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, notDetached, noMetadata}, }, }, // @@ -395,8 +468,42 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), }, expectedCSICalls: []csiCall{ - {"detach", testVolumeHandle, testNodeID, noAttrs, success, detached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, detached, noMetadata}, + }, + }, + { + name: "volume with secrets -> successful detach", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "secret"), node(), secret()}, + addedVA: deleted(va(true, fin)), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "secret"), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), }, + expectedCSICalls: []csiCall{ + {"detach", testVolumeHandle, testNodeID, noAttrs, map[string]string{"foo": "bar"}, success, detached, noMetadata}, + }, + }, + { + name: "volume with empty secrets -> successful detach", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "emptySecret"), node(), emptySecret()}, + addedVA: deleted(va(true, fin)), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "emptySecret"), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), + }, + expectedCSICalls: []csiCall{ + {"detach", testVolumeHandle, testNodeID, noAttrs, map[string]string{}, success, detached, noMetadata}, + }, + }, + { + name: "volume with missing secrets -> error", + initialObjects: []runtime.Object{pvWithSecret(pvWithFinalizer(), "unknownSecret"), node()}, + addedVA: deleted(va(true, fin)), + expectedActions: []core.Action{ + core.NewGetAction(secretGroupResourceVersion, "default", "unknownSecret"), + core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(vaWithDetachError(va(true, fin), "failed to load secret \"default/unknownSecret\": secrets \"unknownSecret\" not found"))), + }, + expectedCSICalls: []csiCall{}, }, { name: "CSI detach fails with transient error -> controller retries", @@ -407,8 +514,8 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), }, expectedCSICalls: []csiCall{ - {"detach", testVolumeHandle, testNodeID, noAttrs, fmt.Errorf("mock error"), notDetached, noMetadata}, - {"detach", testVolumeHandle, testNodeID, noAttrs, success, detached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, fmt.Errorf("mock error"), notDetached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, detached, noMetadata}, }, }, { @@ -419,7 +526,7 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false /*attached*/, ""))), }, expectedCSICalls: []csiCall{ - {"detach", testVolumeHandle, testNodeID, noAttrs, fmt.Errorf("mock error"), detached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, fmt.Errorf("mock error"), detached, noMetadata}, }, }, { @@ -510,8 +617,8 @@ func TestCSIHandler(t *testing.T) { core.NewUpdateAction(vaGroupResourceVersion, metav1.NamespaceNone, deleted(va(false, ""))), }, expectedCSICalls: []csiCall{ - {"detach", testVolumeHandle, testNodeID, noAttrs, success, detached, noMetadata}, - {"detach", testVolumeHandle, testNodeID, noAttrs, success, detached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, detached, noMetadata}, + {"detach", testVolumeHandle, testNodeID, noAttrs, noSecrets, success, detached, noMetadata}, }, }, diff --git a/pkg/controller/framework_test.go b/pkg/controller/framework_test.go index fd79ba543..fa78b9309 100644 --- a/pkg/controller/framework_test.go +++ b/pkg/controller/framework_test.go @@ -84,6 +84,8 @@ type csiCall struct { nodeID string // Expected volume attributes volumeAttributes map[string]string + // Expected secrets + secrets map[string]string // error to return err error // "detached" bool to return. Used only when err != nil @@ -123,6 +125,8 @@ func runTests(t *testing.T, handlerFactory handlerFactory, tests []testCase) { nodeInformer.Informer().GetStore().Add(obj) case *storage.VolumeAttachment: vaInformer.Informer().GetStore().Add(obj) + case *v1.Secret: + // Secrets are not cached in any informer default: t.Fatalf("Unknown initalObject type: %+v", obj) } @@ -332,7 +336,7 @@ func (f *fakeCSIConnection) SupportsControllerPublish(ctx context.Context) (bool return false, fmt.Errorf("Not implemented") } -func (f *fakeCSIConnection) Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes map[string]string) (map[string]string, bool, error) { +func (f *fakeCSIConnection) Attach(ctx context.Context, volumeID string, readOnly bool, nodeID string, caps *csi.VolumeCapability, attributes, secrets map[string]string) (map[string]string, bool, error) { if f.index >= len(f.calls) { f.t.Errorf("Unexpected CSI Attach call: volume=%s, node=%s, index: %d, calls: %+v", volumeID, nodeID, f.index, f.calls) return nil, true, fmt.Errorf("unexpected call") @@ -360,13 +364,17 @@ func (f *fakeCSIConnection) Attach(ctx context.Context, volumeID string, readOnl f.t.Errorf("Wrong CSI Attach call: volume=%s, node=%s, expected attributes %+v, got %+v", volumeID, nodeID, call.volumeAttributes, attributes) } + if !reflect.DeepEqual(call.secrets, secrets) { + f.t.Errorf("Wrong CSI Attach call: volume=%s, node=%s, expected secrets %+v, got %+v", volumeID, nodeID, call.secrets, secrets) + } + if err != nil { return nil, true, err } return call.metadata, call.detached, call.err } -func (f *fakeCSIConnection) Detach(ctx context.Context, volumeID string, nodeID string) (bool, error) { +func (f *fakeCSIConnection) Detach(ctx context.Context, volumeID string, nodeID string, secrets map[string]string) (bool, error) { if f.index >= len(f.calls) { f.t.Errorf("Unexpected CSI Detach call: volume=%s, node=%s, index: %d, calls: %+v", volumeID, nodeID, f.index, f.calls) return true, fmt.Errorf("unexpected call") @@ -381,14 +389,19 @@ func (f *fakeCSIConnection) Detach(ctx context.Context, volumeID string, nodeID } if call.volumeHandle != volumeID { - f.t.Errorf("Wrong CSI Attach call: volume=%s, node=%s, expected PV: %s", volumeID, nodeID, call.volumeHandle) + f.t.Errorf("Wrong CSI Detach call: volume=%s, node=%s, expected PV: %s", volumeID, nodeID, call.volumeHandle) err = fmt.Errorf("unexpected detach call") } if call.nodeID != nodeID { - f.t.Errorf("Wrong CSI Attach call: volume=%s, node=%s, expected Node: %s", volumeID, nodeID, call.nodeID) + f.t.Errorf("Wrong CSI Detach call: volume=%s, node=%s, expected Node: %s", volumeID, nodeID, call.nodeID) err = fmt.Errorf("unexpected detach call") } + + if !reflect.DeepEqual(call.secrets, secrets) { + f.t.Errorf("Wrong CSI Detach call: volume=%s, node=%s, expected secrets %+v, got %+v", volumeID, nodeID, call.secrets, secrets) + } + if err != nil { return true, err }