probe_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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 flexvolume
  14. import (
  15. "fmt"
  16. "path/filepath"
  17. "testing"
  18. "github.com/fsnotify/fsnotify"
  19. "github.com/stretchr/testify/assert"
  20. utilfs "k8s.io/kubernetes/pkg/util/filesystem"
  21. "k8s.io/kubernetes/pkg/volume"
  22. "k8s.io/utils/exec"
  23. )
  24. const (
  25. pluginDir = "/flexvolume"
  26. driverName = "fake-driver"
  27. )
  28. // Probes a driver installed before prober initialization.
  29. func TestProberExistingDriverBeforeInit(t *testing.T) {
  30. // Arrange
  31. driverPath, _, watcher, prober := initTestEnvironment(t)
  32. // Act
  33. events, err := prober.Probe()
  34. // Assert
  35. // Probe occurs, 1 plugin should be returned, and 2 watches (pluginDir and all its
  36. // current subdirectories) registered.
  37. assert.Equal(t, 1, len(events))
  38. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
  39. assert.Equal(t, pluginDir, watcher.watches[0])
  40. assert.Equal(t, driverPath, watcher.watches[1])
  41. assert.NoError(t, err)
  42. // Should no longer probe.
  43. // Act
  44. events, err = prober.Probe()
  45. // Assert
  46. assert.Equal(t, 0, len(events))
  47. assert.NoError(t, err)
  48. }
  49. // Probes newly added drivers after prober is running.
  50. func TestProberAddRemoveDriver(t *testing.T) {
  51. // Arrange
  52. _, fs, watcher, prober := initTestEnvironment(t)
  53. prober.Probe()
  54. events, err := prober.Probe()
  55. assert.Equal(t, 0, len(events))
  56. // Call probe after a file is added. Should return 1 event.
  57. // add driver
  58. const driverName2 = "fake-driver2"
  59. driverPath := filepath.Join(pluginDir, driverName2)
  60. executablePath := filepath.Join(driverPath, driverName2)
  61. installDriver(driverName2, fs)
  62. watcher.TriggerEvent(fsnotify.Create, driverPath)
  63. watcher.TriggerEvent(fsnotify.Create, executablePath)
  64. // Act
  65. events, err = prober.Probe()
  66. // Assert
  67. assert.Equal(t, 1, len(events))
  68. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op) // 1 newly added
  69. assert.Equal(t, driverPath, watcher.watches[len(watcher.watches)-1]) // Checks most recent watch
  70. assert.NoError(t, err)
  71. // Call probe again, should return 0 event.
  72. // Act
  73. events, err = prober.Probe()
  74. // Assert
  75. assert.Equal(t, 0, len(events))
  76. assert.NoError(t, err)
  77. // Call probe after a non-driver file is added in a subdirectory. should return 1 event.
  78. fp := filepath.Join(driverPath, "dummyfile")
  79. fs.Create(fp)
  80. watcher.TriggerEvent(fsnotify.Create, fp)
  81. // Act
  82. events, err = prober.Probe()
  83. // Assert
  84. assert.Equal(t, 1, len(events))
  85. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
  86. assert.NoError(t, err)
  87. // Call probe again, should return 0 event.
  88. // Act
  89. events, err = prober.Probe()
  90. // Assert
  91. assert.Equal(t, 0, len(events))
  92. assert.NoError(t, err)
  93. // Call probe after a subdirectory is added in a driver directory. should return 1 event.
  94. subdirPath := filepath.Join(driverPath, "subdir")
  95. fs.Create(subdirPath)
  96. watcher.TriggerEvent(fsnotify.Create, subdirPath)
  97. // Act
  98. events, err = prober.Probe()
  99. // Assert
  100. assert.Equal(t, 1, len(events))
  101. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
  102. assert.NoError(t, err)
  103. // Call probe again, should return 0 event.
  104. // Act
  105. events, err = prober.Probe()
  106. // Assert
  107. assert.Equal(t, 0, len(events))
  108. assert.NoError(t, err)
  109. // Call probe after a subdirectory is removed in a driver directory. should return 1 event.
  110. fs.Remove(subdirPath)
  111. watcher.TriggerEvent(fsnotify.Remove, subdirPath)
  112. // Act
  113. events, err = prober.Probe()
  114. // Assert
  115. assert.Equal(t, 1, len(events))
  116. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
  117. assert.NoError(t, err)
  118. // Call probe again, should return 0 event.
  119. // Act
  120. events, err = prober.Probe()
  121. // Assert
  122. assert.Equal(t, 0, len(events))
  123. assert.NoError(t, err)
  124. // Call probe after a driver executable and driver directory is remove. should return 1 event.
  125. fs.Remove(executablePath)
  126. fs.Remove(driverPath)
  127. watcher.TriggerEvent(fsnotify.Remove, executablePath)
  128. watcher.TriggerEvent(fsnotify.Remove, driverPath)
  129. // Act and Assert: 1 ProbeRemove event
  130. events, err = prober.Probe()
  131. assert.Equal(t, 1, len(events))
  132. assert.Equal(t, volume.ProbeRemove, events[0].Op)
  133. assert.NoError(t, err)
  134. // Act and Assert: 0 event
  135. events, err = prober.Probe()
  136. assert.Equal(t, 0, len(events))
  137. assert.NoError(t, err)
  138. }
  139. // Tests the behavior when no drivers exist in the plugin directory.
  140. func TestEmptyPluginDir(t *testing.T) {
  141. // Arrange
  142. fs := utilfs.NewFakeFs()
  143. watcher := newFakeWatcher()
  144. prober := &flexVolumeProber{
  145. pluginDir: pluginDir,
  146. watcher: watcher,
  147. fs: fs,
  148. factory: fakePluginFactory{error: false},
  149. }
  150. prober.Init()
  151. // Act
  152. events, err := prober.Probe()
  153. // Assert
  154. assert.Equal(t, 0, len(events))
  155. assert.NoError(t, err)
  156. }
  157. // Issue an event to remove plugindir. New directory should still be watched.
  158. func TestRemovePluginDir(t *testing.T) {
  159. // Arrange
  160. driverPath, fs, watcher, _ := initTestEnvironment(t)
  161. fs.RemoveAll(pluginDir)
  162. watcher.TriggerEvent(fsnotify.Remove, filepath.Join(driverPath, driverName))
  163. watcher.TriggerEvent(fsnotify.Remove, driverPath)
  164. watcher.TriggerEvent(fsnotify.Remove, pluginDir)
  165. // Act: The handler triggered by the above events should have already handled the event appropriately.
  166. // Assert
  167. assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
  168. assert.Equal(t, pluginDir, watcher.watches[len(watcher.watches)-1])
  169. }
  170. // Issue an event to remove plugindir. New directory should still be watched.
  171. func TestNestedDriverDir(t *testing.T) {
  172. // Arrange
  173. _, fs, watcher, _ := initTestEnvironment(t)
  174. // Assert
  175. assert.Equal(t, 2, len(watcher.watches)) // 2 from initial setup
  176. // test add testDriverName
  177. testDriverName := "testDriverName"
  178. testDriverPath := filepath.Join(pluginDir, testDriverName)
  179. fs.MkdirAll(testDriverPath, 0666)
  180. watcher.TriggerEvent(fsnotify.Create, testDriverPath)
  181. // Assert
  182. assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
  183. assert.Equal(t, testDriverPath, watcher.watches[len(watcher.watches)-1])
  184. // test add nested subdir inside testDriverName
  185. basePath := testDriverPath
  186. for i := 0; i < 10; i++ {
  187. subdirName := "subdirName"
  188. subdirPath := filepath.Join(basePath, subdirName)
  189. fs.MkdirAll(subdirPath, 0666)
  190. watcher.TriggerEvent(fsnotify.Create, subdirPath)
  191. // Assert
  192. assert.Equal(t, 4+i, len(watcher.watches)) // 3 + newly added
  193. assert.Equal(t, subdirPath, watcher.watches[len(watcher.watches)-1])
  194. basePath = subdirPath
  195. }
  196. }
  197. // Issue multiple events and probe multiple times.
  198. func TestProberMultipleEvents(t *testing.T) {
  199. const iterations = 5
  200. // Arrange
  201. _, fs, watcher, prober := initTestEnvironment(t)
  202. for i := 0; i < iterations; i++ {
  203. newDriver := fmt.Sprintf("multi-event-driver%d", 1)
  204. installDriver(newDriver, fs)
  205. driverPath := filepath.Join(pluginDir, newDriver)
  206. watcher.TriggerEvent(fsnotify.Create, driverPath)
  207. watcher.TriggerEvent(fsnotify.Create, filepath.Join(driverPath, newDriver))
  208. }
  209. // Act
  210. events, err := prober.Probe()
  211. // Assert
  212. assert.Equal(t, 2, len(events))
  213. assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
  214. assert.Equal(t, volume.ProbeAddOrUpdate, events[1].Op)
  215. assert.NoError(t, err)
  216. for i := 0; i < iterations-1; i++ {
  217. events, err = prober.Probe()
  218. assert.Equal(t, 0, len(events))
  219. assert.NoError(t, err)
  220. }
  221. }
  222. func TestProberError(t *testing.T) {
  223. fs := utilfs.NewFakeFs()
  224. watcher := newFakeWatcher()
  225. prober := &flexVolumeProber{
  226. pluginDir: pluginDir,
  227. watcher: watcher,
  228. fs: fs,
  229. factory: fakePluginFactory{error: true},
  230. }
  231. installDriver(driverName, fs)
  232. prober.Init()
  233. _, err := prober.Probe()
  234. assert.Error(t, err)
  235. }
  236. // Installs a mock driver (an empty file) in the mock fs.
  237. func installDriver(driverName string, fs utilfs.Filesystem) {
  238. driverPath := filepath.Join(pluginDir, driverName)
  239. fs.MkdirAll(driverPath, 0666)
  240. fs.Create(filepath.Join(driverPath, driverName))
  241. }
  242. // Initializes mocks, installs a single driver in the mock fs, then initializes prober.
  243. func initTestEnvironment(t *testing.T) (
  244. driverPath string,
  245. fs utilfs.Filesystem,
  246. watcher *fakeWatcher,
  247. prober volume.DynamicPluginProber) {
  248. fs = utilfs.NewFakeFs()
  249. watcher = newFakeWatcher()
  250. prober = &flexVolumeProber{
  251. pluginDir: pluginDir,
  252. watcher: watcher,
  253. fs: fs,
  254. factory: fakePluginFactory{error: false},
  255. }
  256. driverPath = filepath.Join(pluginDir, driverName)
  257. installDriver(driverName, fs)
  258. prober.Init()
  259. assert.NotNilf(t, watcher.eventHandler,
  260. "Expect watch event handler to be registered after prober init, but is not.")
  261. return
  262. }
  263. // Fake Flexvolume plugin
  264. type fakePluginFactory struct {
  265. error bool // Indicates whether an error should be returned.
  266. }
  267. var _ PluginFactory = fakePluginFactory{}
  268. func (m fakePluginFactory) NewFlexVolumePlugin(_, driverName string, _ exec.Interface) (volume.VolumePlugin, error) {
  269. if m.error {
  270. return nil, fmt.Errorf("Flexvolume plugin error")
  271. }
  272. // Dummy Flexvolume plugin. Prober never interacts with the plugin.
  273. return &flexVolumePlugin{driverName: driverName}, nil
  274. }