Skip to content

Commit

Permalink
Merge pull request #38 from jsafrane/add-secrets
Browse files Browse the repository at this point in the history
Add support for ControllerPublishSecrets
  • Loading branch information
jsafrane authored Apr 3, 2018
2 parents f759283 + 675b8d8 commit 27299be
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 31 deletions.
12 changes: 6 additions & 6 deletions pkg/connection/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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{
Expand All @@ -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)
Expand All @@ -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)
Expand Down
43 changes: 41 additions & 2 deletions pkg/connection/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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)
}
Expand Down
33 changes: 31 additions & 2 deletions pkg/controller/csi_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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 {
Expand All @@ -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.
Expand Down Expand Up @@ -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
}
Loading

0 comments on commit 27299be

Please sign in to comment.