fake_client.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package fake
  14. import (
  15. "context"
  16. "errors"
  17. "strings"
  18. "google.golang.org/grpc"
  19. csipb "github.com/container-storage-interface/spec/lib/go/csi"
  20. )
  21. // IdentityClient is a CSI identity client used for testing
  22. type IdentityClient struct {
  23. nextErr error
  24. }
  25. // NewIdentityClient returns a new IdentityClient
  26. func NewIdentityClient() *IdentityClient {
  27. return &IdentityClient{}
  28. }
  29. // SetNextError injects expected error
  30. func (f *IdentityClient) SetNextError(err error) {
  31. f.nextErr = err
  32. }
  33. // GetPluginInfo returns plugin info
  34. func (f *IdentityClient) GetPluginInfo(ctx context.Context, in *csipb.GetPluginInfoRequest, opts ...grpc.CallOption) (*csipb.GetPluginInfoResponse, error) {
  35. return nil, nil
  36. }
  37. // GetPluginCapabilities implements csi method
  38. func (f *IdentityClient) GetPluginCapabilities(ctx context.Context, in *csipb.GetPluginCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.GetPluginCapabilitiesResponse, error) {
  39. return nil, nil
  40. }
  41. // Probe implements csi method
  42. func (f *IdentityClient) Probe(ctx context.Context, in *csipb.ProbeRequest, opts ...grpc.CallOption) (*csipb.ProbeResponse, error) {
  43. return nil, nil
  44. }
  45. type CSIVolume struct {
  46. VolumeHandle string
  47. VolumeContext map[string]string
  48. Path string
  49. DeviceMountPath string
  50. FSType string
  51. MountFlags []string
  52. }
  53. // NodeClient returns CSI node client
  54. type NodeClient struct {
  55. nodePublishedVolumes map[string]CSIVolume
  56. nodeStagedVolumes map[string]CSIVolume
  57. stageUnstageSet bool
  58. expansionSet bool
  59. volumeStatsSet bool
  60. nodeGetInfoResp *csipb.NodeGetInfoResponse
  61. nodeVolumeStatsResp *csipb.NodeGetVolumeStatsResponse
  62. nextErr error
  63. }
  64. // NewNodeClient returns fake node client
  65. func NewNodeClient(stageUnstageSet bool) *NodeClient {
  66. return &NodeClient{
  67. nodePublishedVolumes: make(map[string]CSIVolume),
  68. nodeStagedVolumes: make(map[string]CSIVolume),
  69. stageUnstageSet: stageUnstageSet,
  70. volumeStatsSet: true,
  71. }
  72. }
  73. func NewNodeClientWithExpansion(stageUnstageSet bool, expansionSet bool) *NodeClient {
  74. return &NodeClient{
  75. nodePublishedVolumes: make(map[string]CSIVolume),
  76. nodeStagedVolumes: make(map[string]CSIVolume),
  77. stageUnstageSet: stageUnstageSet,
  78. expansionSet: expansionSet,
  79. }
  80. }
  81. func NewNodeClientWithVolumeStats(volumeStatsSet bool) *NodeClient {
  82. return &NodeClient{
  83. volumeStatsSet: volumeStatsSet,
  84. }
  85. }
  86. // SetNextError injects next expected error
  87. func (f *NodeClient) SetNextError(err error) {
  88. f.nextErr = err
  89. }
  90. func (f *NodeClient) SetNodeGetInfoResp(resp *csipb.NodeGetInfoResponse) {
  91. f.nodeGetInfoResp = resp
  92. }
  93. func (f *NodeClient) SetNodeVolumeStatsResp(resp *csipb.NodeGetVolumeStatsResponse) {
  94. f.nodeVolumeStatsResp = resp
  95. }
  96. // GetNodePublishedVolumes returns node published volumes
  97. func (f *NodeClient) GetNodePublishedVolumes() map[string]CSIVolume {
  98. return f.nodePublishedVolumes
  99. }
  100. // GetNodeStagedVolumes returns node staged volumes
  101. func (f *NodeClient) GetNodeStagedVolumes() map[string]CSIVolume {
  102. return f.nodeStagedVolumes
  103. }
  104. func (f *NodeClient) AddNodeStagedVolume(volID, deviceMountPath string, volumeContext map[string]string) {
  105. f.nodeStagedVolumes[volID] = CSIVolume{
  106. Path: deviceMountPath,
  107. VolumeContext: volumeContext,
  108. }
  109. }
  110. // NodePublishVolume implements CSI NodePublishVolume
  111. func (f *NodeClient) NodePublishVolume(ctx context.Context, req *csipb.NodePublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodePublishVolumeResponse, error) {
  112. if f.nextErr != nil {
  113. return nil, f.nextErr
  114. }
  115. if req.GetVolumeId() == "" {
  116. return nil, errors.New("missing volume id")
  117. }
  118. if req.GetTargetPath() == "" {
  119. return nil, errors.New("missing target path")
  120. }
  121. fsTypes := "block|ext4|xfs|zfs"
  122. fsType := req.GetVolumeCapability().GetMount().GetFsType()
  123. if !strings.Contains(fsTypes, fsType) {
  124. return nil, errors.New("invalid fstype")
  125. }
  126. f.nodePublishedVolumes[req.GetVolumeId()] = CSIVolume{
  127. VolumeHandle: req.GetVolumeId(),
  128. Path: req.GetTargetPath(),
  129. DeviceMountPath: req.GetStagingTargetPath(),
  130. VolumeContext: req.GetVolumeContext(),
  131. FSType: req.GetVolumeCapability().GetMount().GetFsType(),
  132. MountFlags: req.GetVolumeCapability().GetMount().MountFlags,
  133. }
  134. return &csipb.NodePublishVolumeResponse{}, nil
  135. }
  136. // NodeUnpublishVolume implements csi method
  137. func (f *NodeClient) NodeUnpublishVolume(ctx context.Context, req *csipb.NodeUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeUnpublishVolumeResponse, error) {
  138. if f.nextErr != nil {
  139. return nil, f.nextErr
  140. }
  141. if req.GetVolumeId() == "" {
  142. return nil, errors.New("missing volume id")
  143. }
  144. if req.GetTargetPath() == "" {
  145. return nil, errors.New("missing target path")
  146. }
  147. delete(f.nodePublishedVolumes, req.GetVolumeId())
  148. return &csipb.NodeUnpublishVolumeResponse{}, nil
  149. }
  150. // NodeStagevolume implements csi method
  151. func (f *NodeClient) NodeStageVolume(ctx context.Context, req *csipb.NodeStageVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeStageVolumeResponse, error) {
  152. if f.nextErr != nil {
  153. return nil, f.nextErr
  154. }
  155. if req.GetVolumeId() == "" {
  156. return nil, errors.New("missing volume id")
  157. }
  158. if req.GetStagingTargetPath() == "" {
  159. return nil, errors.New("missing staging target path")
  160. }
  161. csiVol := CSIVolume{
  162. Path: req.GetStagingTargetPath(),
  163. VolumeContext: req.GetVolumeContext(),
  164. }
  165. fsType := ""
  166. fsTypes := "block|ext4|xfs|zfs"
  167. mounted := req.GetVolumeCapability().GetMount()
  168. if mounted != nil {
  169. fsType = mounted.GetFsType()
  170. csiVol.MountFlags = mounted.GetMountFlags()
  171. }
  172. if !strings.Contains(fsTypes, fsType) {
  173. return nil, errors.New("invalid fstype")
  174. }
  175. f.nodeStagedVolumes[req.GetVolumeId()] = csiVol
  176. return &csipb.NodeStageVolumeResponse{}, nil
  177. }
  178. // NodeUnstageVolume implements csi method
  179. func (f *NodeClient) NodeUnstageVolume(ctx context.Context, req *csipb.NodeUnstageVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeUnstageVolumeResponse, error) {
  180. if f.nextErr != nil {
  181. return nil, f.nextErr
  182. }
  183. if req.GetVolumeId() == "" {
  184. return nil, errors.New("missing volume id")
  185. }
  186. if req.GetStagingTargetPath() == "" {
  187. return nil, errors.New("missing staging target path")
  188. }
  189. delete(f.nodeStagedVolumes, req.GetVolumeId())
  190. return &csipb.NodeUnstageVolumeResponse{}, nil
  191. }
  192. // NodeExpandVolume implements csi method
  193. func (f *NodeClient) NodeExpandVolume(ctx context.Context, req *csipb.NodeExpandVolumeRequest, opts ...grpc.CallOption) (*csipb.NodeExpandVolumeResponse, error) {
  194. if f.nextErr != nil {
  195. return nil, f.nextErr
  196. }
  197. if req.GetVolumeId() == "" {
  198. return nil, errors.New("missing volume id")
  199. }
  200. if req.GetVolumePath() == "" {
  201. return nil, errors.New("missing volume path")
  202. }
  203. if req.GetCapacityRange().RequiredBytes <= 0 {
  204. return nil, errors.New("required bytes should be greater than 0")
  205. }
  206. resp := &csipb.NodeExpandVolumeResponse{
  207. CapacityBytes: req.GetCapacityRange().RequiredBytes,
  208. }
  209. return resp, nil
  210. }
  211. // NodeGetId implements csi method
  212. func (f *NodeClient) NodeGetInfo(ctx context.Context, in *csipb.NodeGetInfoRequest, opts ...grpc.CallOption) (*csipb.NodeGetInfoResponse, error) {
  213. if f.nextErr != nil {
  214. return nil, f.nextErr
  215. }
  216. return f.nodeGetInfoResp, nil
  217. }
  218. // NodeGetCapabilities implements csi method
  219. func (f *NodeClient) NodeGetCapabilities(ctx context.Context, in *csipb.NodeGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.NodeGetCapabilitiesResponse, error) {
  220. resp := &csipb.NodeGetCapabilitiesResponse{
  221. Capabilities: []*csipb.NodeServiceCapability{},
  222. }
  223. if f.stageUnstageSet {
  224. resp.Capabilities = append(resp.Capabilities, &csipb.NodeServiceCapability{
  225. Type: &csipb.NodeServiceCapability_Rpc{
  226. Rpc: &csipb.NodeServiceCapability_RPC{
  227. Type: csipb.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
  228. },
  229. },
  230. })
  231. }
  232. if f.expansionSet {
  233. resp.Capabilities = append(resp.Capabilities, &csipb.NodeServiceCapability{
  234. Type: &csipb.NodeServiceCapability_Rpc{
  235. Rpc: &csipb.NodeServiceCapability_RPC{
  236. Type: csipb.NodeServiceCapability_RPC_EXPAND_VOLUME,
  237. },
  238. },
  239. })
  240. }
  241. if f.volumeStatsSet {
  242. resp.Capabilities = append(resp.Capabilities, &csipb.NodeServiceCapability{
  243. Type: &csipb.NodeServiceCapability_Rpc{
  244. Rpc: &csipb.NodeServiceCapability_RPC{
  245. Type: csipb.NodeServiceCapability_RPC_GET_VOLUME_STATS,
  246. },
  247. },
  248. })
  249. }
  250. return resp, nil
  251. }
  252. /*
  253. // NodeGetVolumeStats implements csi method
  254. func (f *NodeClient) NodeGetVolumeStats(ctx context.Context, in *csipb.NodeGetVolumeStatsRequest, opts ...grpc.CallOption) (*csipb.NodeGetVolumeStatsResponse, error) {
  255. return nil, nil
  256. }
  257. */
  258. // NodeGetVolumeStats implements csi method
  259. func (f *NodeClient) NodeGetVolumeStats(ctx context.Context, req *csipb.NodeGetVolumeStatsRequest, opts ...grpc.CallOption) (*csipb.NodeGetVolumeStatsResponse, error) {
  260. if f.nextErr != nil {
  261. return nil, f.nextErr
  262. }
  263. if req.GetVolumeId() == "" {
  264. return nil, errors.New("missing volume id")
  265. }
  266. if req.GetVolumePath() == "" {
  267. return nil, errors.New("missing Volume path")
  268. }
  269. if f.nodeVolumeStatsResp != nil {
  270. return f.nodeVolumeStatsResp, nil
  271. }
  272. return &csipb.NodeGetVolumeStatsResponse{}, nil
  273. }
  274. // ControllerClient represents a CSI Controller client
  275. type ControllerClient struct {
  276. nextCapabilities []*csipb.ControllerServiceCapability
  277. nextErr error
  278. }
  279. // NewControllerClient returns a ControllerClient
  280. func NewControllerClient() *ControllerClient {
  281. return &ControllerClient{}
  282. }
  283. // SetNextError injects next expected error
  284. func (f *ControllerClient) SetNextError(err error) {
  285. f.nextErr = err
  286. }
  287. // SetNextCapabilities injects next expected capabilities
  288. func (f *ControllerClient) SetNextCapabilities(caps []*csipb.ControllerServiceCapability) {
  289. f.nextCapabilities = caps
  290. }
  291. // ControllerGetCapabilities implements csi method
  292. func (f *ControllerClient) ControllerGetCapabilities(ctx context.Context, in *csipb.ControllerGetCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ControllerGetCapabilitiesResponse, error) {
  293. if f.nextErr != nil {
  294. return nil, f.nextErr
  295. }
  296. if f.nextCapabilities == nil {
  297. f.nextCapabilities = []*csipb.ControllerServiceCapability{
  298. {
  299. Type: &csipb.ControllerServiceCapability_Rpc{
  300. Rpc: &csipb.ControllerServiceCapability_RPC{
  301. Type: csipb.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
  302. },
  303. },
  304. },
  305. }
  306. }
  307. return &csipb.ControllerGetCapabilitiesResponse{
  308. Capabilities: f.nextCapabilities,
  309. }, nil
  310. }
  311. // CreateVolume implements csi method
  312. func (f *ControllerClient) CreateVolume(ctx context.Context, in *csipb.CreateVolumeRequest, opts ...grpc.CallOption) (*csipb.CreateVolumeResponse, error) {
  313. return nil, nil
  314. }
  315. // DeleteVolume implements csi method
  316. func (f *ControllerClient) DeleteVolume(ctx context.Context, in *csipb.DeleteVolumeRequest, opts ...grpc.CallOption) (*csipb.DeleteVolumeResponse, error) {
  317. return nil, nil
  318. }
  319. // ControllerPublishVolume implements csi method
  320. func (f *ControllerClient) ControllerPublishVolume(ctx context.Context, in *csipb.ControllerPublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerPublishVolumeResponse, error) {
  321. return nil, nil
  322. }
  323. // ControllerUnpublishVolume implements csi method
  324. func (f *ControllerClient) ControllerUnpublishVolume(ctx context.Context, in *csipb.ControllerUnpublishVolumeRequest, opts ...grpc.CallOption) (*csipb.ControllerUnpublishVolumeResponse, error) {
  325. return nil, nil
  326. }
  327. // ValidateVolumeCapabilities implements csi method
  328. func (f *ControllerClient) ValidateVolumeCapabilities(ctx context.Context, in *csipb.ValidateVolumeCapabilitiesRequest, opts ...grpc.CallOption) (*csipb.ValidateVolumeCapabilitiesResponse, error) {
  329. return nil, nil
  330. }
  331. // ListVolumes implements csi method
  332. func (f *ControllerClient) ListVolumes(ctx context.Context, in *csipb.ListVolumesRequest, opts ...grpc.CallOption) (*csipb.ListVolumesResponse, error) {
  333. return nil, nil
  334. }
  335. // GetCapacity implements csi method
  336. func (f *ControllerClient) GetCapacity(ctx context.Context, in *csipb.GetCapacityRequest, opts ...grpc.CallOption) (*csipb.GetCapacityResponse, error) {
  337. return nil, nil
  338. }