PageRenderTime 202ms CodeModel.GetById 40ms RepoModel.GetById 1ms app.codeStats 0ms

/pkg/volume/host_path/host_path_test.go

https://gitlab.com/github-cloud-corporation/kubernetes
Go | 275 lines | 226 code | 31 blank | 18 comment | 70 complexity | 4e677ef59abee2d533bddeb74eb5673b MD5 | raw file
  1. // +build linux
  2. /*
  3. Copyright 2014 The Kubernetes Authors.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package host_path
  15. import (
  16. "fmt"
  17. "os"
  18. "testing"
  19. "k8s.io/kubernetes/pkg/api"
  20. "k8s.io/kubernetes/pkg/api/resource"
  21. "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
  22. "k8s.io/kubernetes/pkg/types"
  23. "k8s.io/kubernetes/pkg/util"
  24. "k8s.io/kubernetes/pkg/util/uuid"
  25. "k8s.io/kubernetes/pkg/volume"
  26. volumetest "k8s.io/kubernetes/pkg/volume/testing"
  27. )
  28. func TestCanSupport(t *testing.T) {
  29. plugMgr := volume.VolumePluginMgr{}
  30. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("fake", nil, nil, "" /* rootContext */))
  31. plug, err := plugMgr.FindPluginByName("kubernetes.io/host-path")
  32. if err != nil {
  33. t.Errorf("Can't find the plugin by name")
  34. }
  35. if plug.GetPluginName() != "kubernetes.io/host-path" {
  36. t.Errorf("Wrong name: %s", plug.GetPluginName())
  37. }
  38. if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{}}}}) {
  39. t.Errorf("Expected true")
  40. }
  41. if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{}}}}}) {
  42. t.Errorf("Expected true")
  43. }
  44. if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
  45. t.Errorf("Expected false")
  46. }
  47. }
  48. func TestGetAccessModes(t *testing.T) {
  49. plugMgr := volume.VolumePluginMgr{}
  50. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil, "" /* rootContext */))
  51. plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/host-path")
  52. if err != nil {
  53. t.Errorf("Can't find the plugin by name")
  54. }
  55. if len(plug.GetAccessModes()) != 1 || plug.GetAccessModes()[0] != api.ReadWriteOnce {
  56. t.Errorf("Expected %s PersistentVolumeAccessMode", api.ReadWriteOnce)
  57. }
  58. }
  59. func TestRecycler(t *testing.T) {
  60. plugMgr := volume.VolumePluginMgr{}
  61. pluginHost := volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil, "" /* rootContext */)
  62. plugMgr.InitPlugins([]volume.VolumePlugin{&hostPathPlugin{nil, volumetest.NewFakeRecycler, nil, nil, volume.VolumeConfig{}}}, pluginHost)
  63. spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/foo"}}}}}
  64. plug, err := plugMgr.FindRecyclablePluginBySpec(spec)
  65. if err != nil {
  66. t.Errorf("Can't find the plugin by name")
  67. }
  68. recycler, err := plug.NewRecycler("pv-name", spec)
  69. if err != nil {
  70. t.Errorf("Failed to make a new Recyler: %v", err)
  71. }
  72. if recycler.GetPath() != spec.PersistentVolume.Spec.HostPath.Path {
  73. t.Errorf("Expected %s but got %s", spec.PersistentVolume.Spec.HostPath.Path, recycler.GetPath())
  74. }
  75. if err := recycler.Recycle(); err != nil {
  76. t.Errorf("Mock Recycler expected to return nil but got %s", err)
  77. }
  78. }
  79. func TestDeleter(t *testing.T) {
  80. // Deleter has a hard-coded regex for "/tmp".
  81. tempPath := fmt.Sprintf("/tmp/hostpath/%s", uuid.NewUUID())
  82. defer os.RemoveAll(tempPath)
  83. err := os.MkdirAll(tempPath, 0750)
  84. if err != nil {
  85. t.Fatalf("Failed to create tmp directory for deleter: %v", err)
  86. }
  87. plugMgr := volume.VolumePluginMgr{}
  88. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil, "" /* rootContext */))
  89. spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: tempPath}}}}}
  90. plug, err := plugMgr.FindDeletablePluginBySpec(spec)
  91. if err != nil {
  92. t.Errorf("Can't find the plugin by name")
  93. }
  94. deleter, err := plug.NewDeleter(spec)
  95. if err != nil {
  96. t.Errorf("Failed to make a new Deleter: %v", err)
  97. }
  98. if deleter.GetPath() != tempPath {
  99. t.Errorf("Expected %s but got %s", tempPath, deleter.GetPath())
  100. }
  101. if err := deleter.Delete(); err != nil {
  102. t.Errorf("Mock Recycler expected to return nil but got %s", err)
  103. }
  104. if exists, _ := util.FileExists("foo"); exists {
  105. t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath)
  106. }
  107. }
  108. func TestDeleterTempDir(t *testing.T) {
  109. tests := map[string]struct {
  110. expectedFailure bool
  111. path string
  112. }{
  113. "just-tmp": {true, "/tmp"},
  114. "not-tmp": {true, "/nottmp"},
  115. "good-tmp": {false, "/tmp/scratch"},
  116. }
  117. for name, test := range tests {
  118. plugMgr := volume.VolumePluginMgr{}
  119. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil, "" /* rootContext */))
  120. spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: test.path}}}}}
  121. plug, _ := plugMgr.FindDeletablePluginBySpec(spec)
  122. deleter, _ := plug.NewDeleter(spec)
  123. err := deleter.Delete()
  124. if err == nil && test.expectedFailure {
  125. t.Errorf("Expected failure for test '%s' but got nil err", name)
  126. }
  127. if err != nil && !test.expectedFailure {
  128. t.Errorf("Unexpected failure for test '%s': %v", name, err)
  129. }
  130. }
  131. }
  132. func TestProvisioner(t *testing.T) {
  133. tempPath := fmt.Sprintf("/tmp/hostpath/%s", uuid.NewUUID())
  134. defer os.RemoveAll(tempPath)
  135. err := os.MkdirAll(tempPath, 0750)
  136. plugMgr := volume.VolumePluginMgr{}
  137. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{ProvisioningEnabled: true}),
  138. volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil, "" /* rootContext */))
  139. spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: tempPath}}}}}
  140. plug, err := plugMgr.FindCreatablePluginBySpec(spec)
  141. if err != nil {
  142. t.Errorf("Can't find the plugin by name")
  143. }
  144. creater, err := plug.NewProvisioner(volume.VolumeOptions{Capacity: resource.MustParse("1Gi"), PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimDelete})
  145. if err != nil {
  146. t.Errorf("Failed to make a new Provisioner: %v", err)
  147. }
  148. pv, err := creater.Provision()
  149. if err != nil {
  150. t.Errorf("Unexpected error creating volume: %v", err)
  151. }
  152. if pv.Spec.HostPath.Path == "" {
  153. t.Errorf("Expected pv.Spec.HostPath.Path to not be empty: %#v", pv)
  154. }
  155. expectedCapacity := resource.NewQuantity(1*1024*1024*1024, resource.BinarySI)
  156. actualCapacity := pv.Spec.Capacity[api.ResourceStorage]
  157. expectedAmt := expectedCapacity.Value()
  158. actualAmt := actualCapacity.Value()
  159. if expectedAmt != actualAmt {
  160. t.Errorf("Expected capacity %+v but got %+v", expectedAmt, actualAmt)
  161. }
  162. if pv.Spec.PersistentVolumeReclaimPolicy != api.PersistentVolumeReclaimDelete {
  163. t.Errorf("Expected reclaim policy %+v but got %+v", api.PersistentVolumeReclaimDelete, pv.Spec.PersistentVolumeReclaimPolicy)
  164. }
  165. os.RemoveAll(pv.Spec.HostPath.Path)
  166. }
  167. func TestPlugin(t *testing.T) {
  168. plugMgr := volume.VolumePluginMgr{}
  169. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("fake", nil, nil, "" /* rootContext */))
  170. plug, err := plugMgr.FindPluginByName("kubernetes.io/host-path")
  171. if err != nil {
  172. t.Errorf("Can't find the plugin by name")
  173. }
  174. spec := &api.Volume{
  175. Name: "vol1",
  176. VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/vol1"}},
  177. }
  178. pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
  179. mounter, err := plug.NewMounter(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{})
  180. if err != nil {
  181. t.Errorf("Failed to make a new Mounter: %v", err)
  182. }
  183. if mounter == nil {
  184. t.Errorf("Got a nil Mounter")
  185. }
  186. path := mounter.GetPath()
  187. if path != "/vol1" {
  188. t.Errorf("Got unexpected path: %s", path)
  189. }
  190. if err := mounter.SetUp(nil); err != nil {
  191. t.Errorf("Expected success, got: %v", err)
  192. }
  193. unmounter, err := plug.NewUnmounter("vol1", types.UID("poduid"))
  194. if err != nil {
  195. t.Errorf("Failed to make a new Unmounter: %v", err)
  196. }
  197. if unmounter == nil {
  198. t.Errorf("Got a nil Unmounter")
  199. }
  200. if err := unmounter.TearDown(); err != nil {
  201. t.Errorf("Expected success, got: %v", err)
  202. }
  203. }
  204. func TestPersistentClaimReadOnlyFlag(t *testing.T) {
  205. pv := &api.PersistentVolume{
  206. ObjectMeta: api.ObjectMeta{
  207. Name: "pvA",
  208. },
  209. Spec: api.PersistentVolumeSpec{
  210. PersistentVolumeSource: api.PersistentVolumeSource{
  211. HostPath: &api.HostPathVolumeSource{Path: "foo"},
  212. },
  213. ClaimRef: &api.ObjectReference{
  214. Name: "claimA",
  215. },
  216. },
  217. }
  218. claim := &api.PersistentVolumeClaim{
  219. ObjectMeta: api.ObjectMeta{
  220. Name: "claimA",
  221. Namespace: "nsA",
  222. },
  223. Spec: api.PersistentVolumeClaimSpec{
  224. VolumeName: "pvA",
  225. },
  226. Status: api.PersistentVolumeClaimStatus{
  227. Phase: api.ClaimBound,
  228. },
  229. }
  230. client := fake.NewSimpleClientset(pv, claim)
  231. plugMgr := volume.VolumePluginMgr{}
  232. plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", client, nil, "" /* rootContext */))
  233. plug, _ := plugMgr.FindPluginByName(hostPathPluginName)
  234. // readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
  235. spec := volume.NewSpecFromPersistentVolume(pv, true)
  236. pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
  237. mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
  238. if !mounter.GetAttributes().ReadOnly {
  239. t.Errorf("Expected true for mounter.IsReadOnly")
  240. }
  241. }