2017-10-25 02:44:48 +00:00
|
|
|
/*
|
|
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package fake
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
|
2018-02-24 21:30:17 +00:00
|
|
|
csipb "github.com/container-storage-interface/spec/lib/go/csi/v0"
|
2017-10-25 02:44:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// IdentityClient is a CSI identity client used for testing
|
|
|
|
type IdentityClient struct {
|
|
|
|
nextErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewIdentityClient returns a new IdentityClient
|
|
|
|
func NewIdentityClient() *IdentityClient {
|
|
|
|
return &IdentityClient{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetNextError injects expected error
|
|
|
|
func (f *IdentityClient) SetNextError(err error) {
|
|
|
|
f.nextErr = err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPluginInfo returns plugin info
|
|
|
|
func (f *IdentityClient) GetPluginInfo(ctx context.Context, in *csipb.GetPluginInfoRequest, opts ...grpc.CallOption) (*csipb.GetPluginInfoResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-02-23 21:50:43 +00:00
|
|
|
// GetPluginCapabilities implements csi method
|
|
|
|
func (f *IdentityClient) GetPluginCapabilities(ctx context.Context, in *csipb.GetPluginCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.GetPluginCapabilitiesResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Probe implements csi method
|
|
|
|
func (f *IdentityClient) Probe(ctx context.Context, in *csipb.ProbeRequest, opts ...grpc.CallOption) (*csipb.ProbeResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-08-28 12:00:55 +00:00
|
|
|
type CSIVolume struct {
|
|
|
|
Attributes map[string]string
|
|
|
|
Path string
|
|
|
|
}
|
|
|
|
|
2017-10-25 02:44:48 +00:00
|
|
|
// NodeClient returns CSI node client
|
|
|
|
type NodeClient struct {
|
2018-08-28 12:00:55 +00:00
|
|
|
nodePublishedVolumes map[string]CSIVolume
|
|
|
|
nodeStagedVolumes map[string]CSIVolume
|
2018-02-21 01:48:32 +00:00
|
|
|
stageUnstageSet bool
|
2018-08-07 19:28:19 +00:00
|
|
|
nodeGetInfoResp *csipb.NodeGetInfoResponse
|
2017-10-25 02:44:48 +00:00
|
|
|
nextErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewNodeClient returns fake node client
|
2018-02-21 01:48:32 +00:00
|
|
|
func NewNodeClient(stageUnstageSet bool) *NodeClient {
|
|
|
|
return &NodeClient{
|
2018-08-28 12:00:55 +00:00
|
|
|
nodePublishedVolumes: make(map[string]CSIVolume),
|
|
|
|
nodeStagedVolumes: make(map[string]CSIVolume),
|
2018-02-21 01:48:32 +00:00
|
|
|
stageUnstageSet: stageUnstageSet,
|
|
|
|
}
|
2017-10-25 02:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetNextError injects next expected error
|
|
|
|
func (f *NodeClient) SetNextError(err error) {
|
|
|
|
f.nextErr = err
|
|
|
|
}
|
|
|
|
|
2018-08-07 19:28:19 +00:00
|
|
|
func (f *NodeClient) SetNodeGetInfoResp(resp *csipb.NodeGetInfoResponse) {
|
|
|
|
f.nodeGetInfoResp = resp
|
|
|
|
}
|
|
|
|
|
2017-10-25 02:44:48 +00:00
|
|
|
// GetNodePublishedVolumes returns node published volumes
|
2018-08-28 12:00:55 +00:00
|
|
|
func (f *NodeClient) GetNodePublishedVolumes() map[string]CSIVolume {
|
2017-10-25 02:44:48 +00:00
|
|
|
return f.nodePublishedVolumes
|
|
|
|
}
|
|
|
|
|
2018-02-21 01:48:32 +00:00
|
|
|
// GetNodeStagedVolumes returns node staged volumes
|
2018-08-28 12:00:55 +00:00
|
|
|
func (f *NodeClient) GetNodeStagedVolumes() map[string]CSIVolume {
|
2018-02-21 01:48:32 +00:00
|
|
|
return f.nodeStagedVolumes
|
|
|
|
}
|
|
|
|
|
2018-08-28 12:00:55 +00:00
|
|
|
func (f *NodeClient) AddNodeStagedVolume(volID, deviceMountPath string, attributes map[string]string) {
|
|
|
|
f.nodeStagedVolumes[volID] = CSIVolume{
|
|
|
|
Path: deviceMountPath,
|
|
|
|
Attributes: attributes,
|
|
|
|
}
|
2018-02-21 01:48:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-25 02:44:48 +00:00
|
|
|
// NodePublishVolume implements CSI NodePublishVolume
|
2018-02-28 04:20:22 +00:00
|
|
|
func (f *NodeClient) NodePublishVolume(ctx context.Context, req *csipb.NodePublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodePublishVolumeResponse, error) {
|
2017-10-25 02:44:48 +00:00
|
|
|
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.GetVolumeId() == "" {
|
|
|
|
return nil, errors.New("missing volume id")
|
|
|
|
}
|
|
|
|
if req.GetTargetPath() == "" {
|
|
|
|
return nil, errors.New("missing target path")
|
|
|
|
}
|
2018-05-09 18:28:53 +00:00
|
|
|
fsTypes := "block|ext4|xfs|zfs"
|
2017-10-25 02:44:48 +00:00
|
|
|
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
|
|
|
if !strings.Contains(fsTypes, fsType) {
|
2018-02-09 06:53:53 +00:00
|
|
|
return nil, errors.New("invalid fstype")
|
2017-10-25 02:44:48 +00:00
|
|
|
}
|
2018-08-28 12:00:55 +00:00
|
|
|
f.nodePublishedVolumes[req.GetVolumeId()] = CSIVolume{
|
|
|
|
Path: req.GetTargetPath(),
|
|
|
|
Attributes: req.GetVolumeAttributes(),
|
|
|
|
}
|
2017-10-25 02:44:48 +00:00
|
|
|
return &csipb.NodePublishVolumeResponse{}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeUnpublishVolume implements csi method
|
|
|
|
func (f *NodeClient) NodeUnpublishVolume(ctx context.Context, req *csipb.NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeUnpublishVolumeResponse, error) {
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.GetVolumeId() == "" {
|
|
|
|
return nil, errors.New("missing volume id")
|
|
|
|
}
|
|
|
|
if req.GetTargetPath() == "" {
|
|
|
|
return nil, errors.New("missing target path")
|
|
|
|
}
|
|
|
|
delete(f.nodePublishedVolumes, req.GetVolumeId())
|
|
|
|
return &csipb.NodeUnpublishVolumeResponse{}, nil
|
|
|
|
}
|
|
|
|
|
2018-02-21 01:48:32 +00:00
|
|
|
// NodeStagevolume implements csi method
|
|
|
|
func (f *NodeClient) NodeStageVolume(ctx context.Context, req *csipb.NodeStageVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeStageVolumeResponse, error) {
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.GetVolumeId() == "" {
|
|
|
|
return nil, errors.New("missing volume id")
|
|
|
|
}
|
|
|
|
if req.GetStagingTargetPath() == "" {
|
|
|
|
return nil, errors.New("missing staging target path")
|
|
|
|
}
|
|
|
|
|
|
|
|
fsType := ""
|
2018-05-09 18:28:53 +00:00
|
|
|
fsTypes := "block|ext4|xfs|zfs"
|
2018-02-21 01:48:32 +00:00
|
|
|
mounted := req.GetVolumeCapability().GetMount()
|
|
|
|
if mounted != nil {
|
|
|
|
fsType = mounted.GetFsType()
|
|
|
|
}
|
|
|
|
if !strings.Contains(fsTypes, fsType) {
|
|
|
|
return nil, errors.New("invalid fstype")
|
|
|
|
}
|
|
|
|
|
2018-08-28 12:00:55 +00:00
|
|
|
f.nodeStagedVolumes[req.GetVolumeId()] = CSIVolume{
|
|
|
|
Path: req.GetStagingTargetPath(),
|
|
|
|
Attributes: req.GetVolumeAttributes(),
|
|
|
|
}
|
2018-02-21 01:48:32 +00:00
|
|
|
return &csipb.NodeStageVolumeResponse{}, nil
|
2017-10-25 02:44:48 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 01:48:32 +00:00
|
|
|
// NodeUnstageVolume implements csi method
|
|
|
|
func (f *NodeClient) NodeUnstageVolume(ctx context.Context, req *csipb.NodeUnstageVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeUnstageVolumeResponse, error) {
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.GetVolumeId() == "" {
|
|
|
|
return nil, errors.New("missing volume id")
|
|
|
|
}
|
|
|
|
if req.GetStagingTargetPath() == "" {
|
|
|
|
return nil, errors.New("missing staging target path")
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(f.nodeStagedVolumes, req.GetVolumeId())
|
|
|
|
return &csipb.NodeUnstageVolumeResponse{}, nil
|
2017-10-25 02:44:48 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 01:48:32 +00:00
|
|
|
// NodeGetId implements method
|
|
|
|
func (f *NodeClient) NodeGetId(ctx context.Context, in *csipb.NodeGetIdRequest, opts ...grpc.CallOption) (*csipb.NodeGetIdResponse, error) {
|
2018-02-23 21:50:43 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-08-07 19:28:19 +00:00
|
|
|
// NodeGetId implements csi method
|
|
|
|
func (f *NodeClient) NodeGetInfo(ctx context.Context, in *csipb.NodeGetInfoRequest, opts ...grpc.CallOption) (*csipb.NodeGetInfoResponse, error) {
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
return f.nodeGetInfoResp, nil
|
|
|
|
}
|
|
|
|
|
2018-02-21 01:48:32 +00:00
|
|
|
// NodeGetCapabilities implements csi method
|
|
|
|
func (f *NodeClient) NodeGetCapabilities(ctx context.Context, in *csipb.NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.NodeGetCapabilitiesResponse, error) {
|
|
|
|
resp := &csipb.NodeGetCapabilitiesResponse{
|
|
|
|
Capabilities: []*csipb.NodeServiceCapability{
|
|
|
|
{
|
|
|
|
Type: &csipb.NodeServiceCapability_Rpc{
|
|
|
|
Rpc: &csipb.NodeServiceCapability_RPC{
|
|
|
|
Type: csipb.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if f.stageUnstageSet {
|
|
|
|
return resp, nil
|
|
|
|
}
|
2018-02-23 21:50:43 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-10-25 02:44:48 +00:00
|
|
|
// ControllerClient represents a CSI Controller client
|
|
|
|
type ControllerClient struct {
|
|
|
|
nextCapabilities []*csipb.ControllerServiceCapability
|
|
|
|
nextErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewControllerClient returns a ControllerClient
|
|
|
|
func NewControllerClient() *ControllerClient {
|
|
|
|
return &ControllerClient{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetNextError injects next expected error
|
|
|
|
func (f *ControllerClient) SetNextError(err error) {
|
|
|
|
f.nextErr = err
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetNextCapabilities injects next expected capabilities
|
|
|
|
func (f *ControllerClient) SetNextCapabilities(caps []*csipb.ControllerServiceCapability) {
|
|
|
|
f.nextCapabilities = caps
|
|
|
|
}
|
|
|
|
|
|
|
|
// ControllerGetCapabilities implements csi method
|
|
|
|
func (f *ControllerClient) ControllerGetCapabilities(ctx context.Context, in *csipb.ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ControllerGetCapabilitiesResponse, error) {
|
|
|
|
if f.nextErr != nil {
|
|
|
|
return nil, f.nextErr
|
|
|
|
}
|
|
|
|
|
|
|
|
if f.nextCapabilities == nil {
|
|
|
|
f.nextCapabilities = []*csipb.ControllerServiceCapability{
|
|
|
|
{
|
|
|
|
Type: &csipb.ControllerServiceCapability_Rpc{
|
|
|
|
Rpc: &csipb.ControllerServiceCapability_RPC{
|
|
|
|
Type: csipb.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &csipb.ControllerGetCapabilitiesResponse{
|
|
|
|
Capabilities: f.nextCapabilities,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateVolume implements csi method
|
|
|
|
func (f *ControllerClient) CreateVolume(ctx context.Context, in *csipb.CreateVolumeRequest, opts ...grpc.CallOption) (*csipb.CreateVolumeResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteVolume implements csi method
|
|
|
|
func (f *ControllerClient) DeleteVolume(ctx context.Context, in *csipb.DeleteVolumeRequest, opts ...grpc.CallOption) (*csipb.DeleteVolumeResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ControllerPublishVolume implements csi method
|
|
|
|
func (f *ControllerClient) ControllerPublishVolume(ctx context.Context, in *csipb.ControllerPublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerPublishVolumeResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ControllerUnpublishVolume implements csi method
|
|
|
|
func (f *ControllerClient) ControllerUnpublishVolume(ctx context.Context, in *csipb.ControllerUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerUnpublishVolumeResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateVolumeCapabilities implements csi method
|
|
|
|
func (f *ControllerClient) ValidateVolumeCapabilities(ctx context.Context, in *csipb.ValidateVolumeCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ValidateVolumeCapabilitiesResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListVolumes implements csi method
|
|
|
|
func (f *ControllerClient) ListVolumes(ctx context.Context, in *csipb.ListVolumesRequest, opts ...grpc.CallOption) (*csipb.ListVolumesResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCapacity implements csi method
|
|
|
|
func (f *ControllerClient) GetCapacity(ctx context.Context, in *csipb.GetCapacityRequest, opts ...grpc.CallOption) (*csipb.GetCapacityResponse, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|