test_oc_pvc.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. '''
  2. Unit tests for oc pvc
  3. '''
  4. import copy
  5. import os
  6. import six
  7. import sys
  8. import unittest
  9. import mock
  10. # Removing invalid variable names for tests so that I can
  11. # keep them brief
  12. # pylint: disable=invalid-name,no-name-in-module
  13. # Disable import-error b/c our libraries aren't loaded in jenkins
  14. # pylint: disable=import-error,wrong-import-position
  15. # place class in our python path
  16. module_path = os.path.join('/'.join(os.path.realpath(__file__).split('/')[:-4]), 'library') # noqa: E501
  17. sys.path.insert(0, module_path)
  18. from oc_pvc import OCPVC, locate_oc_binary # noqa: E402
  19. class OCPVCTest(unittest.TestCase):
  20. '''
  21. Test class for OCPVC
  22. '''
  23. params = {'kubeconfig': '/etc/origin/master/admin.kubeconfig',
  24. 'state': 'present',
  25. 'debug': False,
  26. 'name': 'mypvc',
  27. 'namespace': 'test',
  28. 'volume_capacity': '1G',
  29. 'selector': {'foo': 'bar', 'abc': 'a123'},
  30. 'storage_class_name': 'mystorage',
  31. 'access_modes': 'ReadWriteMany'}
  32. @mock.patch('oc_pvc.Utils.create_tmpfile_copy')
  33. @mock.patch('oc_pvc.OCPVC._run')
  34. def test_create_pvc(self, mock_run, mock_tmpfile_copy):
  35. ''' Testing a pvc create '''
  36. params = copy.deepcopy(OCPVCTest.params)
  37. pvc = '''{"kind": "PersistentVolumeClaim",
  38. "apiVersion": "v1",
  39. "metadata": {
  40. "name": "mypvc",
  41. "namespace": "test",
  42. "selfLink": "/api/v1/namespaces/test/persistentvolumeclaims/mypvc",
  43. "uid": "77597898-d8d8-11e6-aea5-0e3c0c633889",
  44. "resourceVersion": "126510787",
  45. "creationTimestamp": "2017-01-12T15:04:50Z",
  46. "labels": {
  47. "mypvc": "database"
  48. },
  49. "annotations": {
  50. "pv.kubernetes.io/bind-completed": "yes",
  51. "pv.kubernetes.io/bound-by-controller": "yes",
  52. "v1.2-volume.experimental.kubernetes.io/provisioning-required": "volume.experimental.kubernetes.io/provisioning-completed"
  53. }
  54. },
  55. "spec": {
  56. "accessModes": [
  57. "ReadWriteOnce"
  58. ],
  59. "resources": {
  60. "requests": {
  61. "storage": "1Gi"
  62. }
  63. },
  64. "selector": {
  65. "matchLabels": {
  66. "foo": "bar",
  67. "abc": "a123"
  68. }
  69. },
  70. "storageClassName": "myStorage",
  71. "volumeName": "pv-aws-ow5vl"
  72. },
  73. "status": {
  74. "phase": "Bound",
  75. "accessModes": [
  76. "ReadWriteOnce"
  77. ],
  78. "capacity": {
  79. "storage": "1Gi"
  80. }
  81. }
  82. }'''
  83. mock_run.side_effect = [
  84. (1, '', 'Error from server: persistentvolumeclaims "mypvc" not found'),
  85. (1, '', 'Error from server: persistentvolumeclaims "mypvc" not found'),
  86. (0, '', ''),
  87. (0, pvc, ''),
  88. ]
  89. mock_tmpfile_copy.side_effect = [
  90. '/tmp/mocked_kubeconfig',
  91. ]
  92. results = OCPVC.run_ansible(params, False)
  93. self.assertTrue(results['changed'])
  94. self.assertEqual(results['results']['results'][0]['metadata']['name'], 'mypvc')
  95. self.assertEqual(results['results']['results'][0]['spec']['storageClassName'], 'myStorage')
  96. self.assertEqual(results['results']['results'][0]['spec']['selector']['matchLabels']['foo'], 'bar')
  97. @mock.patch('oc_pvc.Utils.create_tmpfile_copy')
  98. @mock.patch('oc_pvc.OCPVC._run')
  99. def test_update_pvc(self, mock_run, mock_tmpfile_copy):
  100. ''' Testing a pvc create '''
  101. params = copy.deepcopy(OCPVCTest.params)
  102. params['access_modes'] = 'ReadWriteMany'
  103. pvc = '''{"kind": "PersistentVolumeClaim",
  104. "apiVersion": "v1",
  105. "metadata": {
  106. "name": "mypvc",
  107. "namespace": "test",
  108. "selfLink": "/api/v1/namespaces/test/persistentvolumeclaims/mypvc",
  109. "uid": "77597898-d8d8-11e6-aea5-0e3c0c633889",
  110. "resourceVersion": "126510787",
  111. "creationTimestamp": "2017-01-12T15:04:50Z",
  112. "labels": {
  113. "mypvc": "database"
  114. },
  115. "annotations": {
  116. "pv.kubernetes.io/bind-completed": "yes",
  117. "pv.kubernetes.io/bound-by-controller": "yes",
  118. "v1.2-volume.experimental.kubernetes.io/provisioning-required": "volume.experimental.kubernetes.io/provisioning-completed"
  119. }
  120. },
  121. "spec": {
  122. "accessModes": [
  123. "ReadWriteOnce"
  124. ],
  125. "resources": {
  126. "requests": {
  127. "storage": "1Gi"
  128. }
  129. },
  130. "volumeName": "pv-aws-ow5vl"
  131. },
  132. "status": {
  133. "phase": "Bound",
  134. "accessModes": [
  135. "ReadWriteOnce"
  136. ],
  137. "capacity": {
  138. "storage": "1Gi"
  139. }
  140. }
  141. }'''
  142. mod_pvc = '''{"kind": "PersistentVolumeClaim",
  143. "apiVersion": "v1",
  144. "metadata": {
  145. "name": "mypvc",
  146. "namespace": "test",
  147. "selfLink": "/api/v1/namespaces/test/persistentvolumeclaims/mypvc",
  148. "uid": "77597898-d8d8-11e6-aea5-0e3c0c633889",
  149. "resourceVersion": "126510787",
  150. "creationTimestamp": "2017-01-12T15:04:50Z",
  151. "labels": {
  152. "mypvc": "database"
  153. },
  154. "annotations": {
  155. "pv.kubernetes.io/bind-completed": "yes",
  156. "pv.kubernetes.io/bound-by-controller": "yes",
  157. "v1.2-volume.experimental.kubernetes.io/provisioning-required": "volume.experimental.kubernetes.io/provisioning-completed"
  158. }
  159. },
  160. "spec": {
  161. "accessModes": [
  162. "ReadWriteMany"
  163. ],
  164. "resources": {
  165. "requests": {
  166. "storage": "1Gi"
  167. }
  168. },
  169. "volumeName": "pv-aws-ow5vl"
  170. },
  171. "status": {
  172. "phase": "Bound",
  173. "accessModes": [
  174. "ReadWriteOnce"
  175. ],
  176. "capacity": {
  177. "storage": "1Gi"
  178. }
  179. }
  180. }'''
  181. mock_run.side_effect = [
  182. (0, pvc, ''),
  183. (0, pvc, ''),
  184. (0, '', ''),
  185. (0, mod_pvc, ''),
  186. ]
  187. mock_tmpfile_copy.side_effect = [
  188. '/tmp/mocked_kubeconfig',
  189. ]
  190. results = OCPVC.run_ansible(params, False)
  191. self.assertFalse(results['changed'])
  192. self.assertEqual(results['results']['msg'], '##### - This volume is currently bound. Will not update - ####')
  193. @mock.patch('oc_pvc.Utils.create_tmpfile_copy')
  194. @mock.patch('oc_pvc.OCPVC._run')
  195. def test_delete_pvc(self, mock_run, mock_tmpfile_copy):
  196. ''' Testing a pvc create '''
  197. params = copy.deepcopy(OCPVCTest.params)
  198. params['state'] = 'absent'
  199. pvc = '''{"kind": "PersistentVolumeClaim",
  200. "apiVersion": "v1",
  201. "metadata": {
  202. "name": "mypvc",
  203. "namespace": "test",
  204. "selfLink": "/api/v1/namespaces/test/persistentvolumeclaims/mypvc",
  205. "uid": "77597898-d8d8-11e6-aea5-0e3c0c633889",
  206. "resourceVersion": "126510787",
  207. "creationTimestamp": "2017-01-12T15:04:50Z",
  208. "labels": {
  209. "mypvc": "database"
  210. },
  211. "annotations": {
  212. "pv.kubernetes.io/bind-completed": "yes",
  213. "pv.kubernetes.io/bound-by-controller": "yes",
  214. "v1.2-volume.experimental.kubernetes.io/provisioning-required": "volume.experimental.kubernetes.io/provisioning-completed"
  215. }
  216. },
  217. "spec": {
  218. "accessModes": [
  219. "ReadWriteOnce"
  220. ],
  221. "resources": {
  222. "requests": {
  223. "storage": "1Gi"
  224. }
  225. },
  226. "volumeName": "pv-aws-ow5vl"
  227. },
  228. "status": {
  229. "phase": "Bound",
  230. "accessModes": [
  231. "ReadWriteOnce"
  232. ],
  233. "capacity": {
  234. "storage": "1Gi"
  235. }
  236. }
  237. }'''
  238. mock_run.side_effect = [
  239. (0, pvc, ''),
  240. (0, '', ''),
  241. ]
  242. mock_tmpfile_copy.side_effect = [
  243. '/tmp/mocked_kubeconfig',
  244. ]
  245. results = OCPVC.run_ansible(params, False)
  246. self.assertTrue(results['changed'])
  247. @unittest.skipIf(six.PY3, 'py2 test only')
  248. @mock.patch('os.path.exists')
  249. @mock.patch('os.environ.get')
  250. def test_binary_lookup_fallback(self, mock_env_get, mock_path_exists):
  251. ''' Testing binary lookup fallback '''
  252. mock_env_get.side_effect = lambda _v, _d: ''
  253. mock_path_exists.side_effect = lambda _: False
  254. self.assertEqual(locate_oc_binary(), 'oc')
  255. @unittest.skipIf(six.PY3, 'py2 test only')
  256. @mock.patch('os.path.exists')
  257. @mock.patch('os.environ.get')
  258. def test_binary_lookup_in_path(self, mock_env_get, mock_path_exists):
  259. ''' Testing binary lookup in path '''
  260. oc_bin = '/usr/bin/oc'
  261. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  262. mock_path_exists.side_effect = lambda f: f == oc_bin
  263. self.assertEqual(locate_oc_binary(), oc_bin)
  264. @unittest.skipIf(six.PY3, 'py2 test only')
  265. @mock.patch('os.path.exists')
  266. @mock.patch('os.environ.get')
  267. def test_binary_lookup_in_usr_local(self, mock_env_get, mock_path_exists):
  268. ''' Testing binary lookup in /usr/local/bin '''
  269. oc_bin = '/usr/local/bin/oc'
  270. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  271. mock_path_exists.side_effect = lambda f: f == oc_bin
  272. self.assertEqual(locate_oc_binary(), oc_bin)
  273. @unittest.skipIf(six.PY3, 'py2 test only')
  274. @mock.patch('os.path.exists')
  275. @mock.patch('os.environ.get')
  276. def test_binary_lookup_in_home(self, mock_env_get, mock_path_exists):
  277. ''' Testing binary lookup in ~/bin '''
  278. oc_bin = os.path.expanduser('~/bin/oc')
  279. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  280. mock_path_exists.side_effect = lambda f: f == oc_bin
  281. self.assertEqual(locate_oc_binary(), oc_bin)
  282. @unittest.skipIf(six.PY2, 'py3 test only')
  283. @mock.patch('shutil.which')
  284. @mock.patch('os.environ.get')
  285. def test_binary_lookup_fallback_py3(self, mock_env_get, mock_shutil_which):
  286. ''' Testing binary lookup fallback '''
  287. mock_env_get.side_effect = lambda _v, _d: ''
  288. mock_shutil_which.side_effect = lambda _f, path=None: None
  289. self.assertEqual(locate_oc_binary(), 'oc')
  290. @unittest.skipIf(six.PY2, 'py3 test only')
  291. @mock.patch('shutil.which')
  292. @mock.patch('os.environ.get')
  293. def test_binary_lookup_in_path_py3(self, mock_env_get, mock_shutil_which):
  294. ''' Testing binary lookup in path '''
  295. oc_bin = '/usr/bin/oc'
  296. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  297. mock_shutil_which.side_effect = lambda _f, path=None: oc_bin
  298. self.assertEqual(locate_oc_binary(), oc_bin)
  299. @unittest.skipIf(six.PY2, 'py3 test only')
  300. @mock.patch('shutil.which')
  301. @mock.patch('os.environ.get')
  302. def test_binary_lookup_in_usr_local_py3(self, mock_env_get, mock_shutil_which):
  303. ''' Testing binary lookup in /usr/local/bin '''
  304. oc_bin = '/usr/local/bin/oc'
  305. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  306. mock_shutil_which.side_effect = lambda _f, path=None: oc_bin
  307. self.assertEqual(locate_oc_binary(), oc_bin)
  308. @unittest.skipIf(six.PY2, 'py3 test only')
  309. @mock.patch('shutil.which')
  310. @mock.patch('os.environ.get')
  311. def test_binary_lookup_in_home_py3(self, mock_env_get, mock_shutil_which):
  312. ''' Testing binary lookup in ~/bin '''
  313. oc_bin = os.path.expanduser('~/bin/oc')
  314. mock_env_get.side_effect = lambda _v, _d: '/bin:/usr/bin'
  315. mock_shutil_which.side_effect = lambda _f, path=None: oc_bin
  316. self.assertEqual(locate_oc_binary(), oc_bin)