cli_installer_tests.py 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. # TODO: Temporarily disabled due to importing old code into openshift-ansible
  2. # repo. We will work on these over time.
  3. # pylint: disable=bad-continuation,missing-docstring,no-self-use,invalid-name,too-many-lines
  4. import copy
  5. import os
  6. import ConfigParser
  7. import ooinstall.cli_installer as cli
  8. from test.fixture import OOCliFixture, SAMPLE_CONFIG, build_input, read_yaml
  9. from mock import patch
  10. MOCK_FACTS = {
  11. '10.0.0.1': {
  12. 'common': {
  13. 'ip': '10.0.0.1',
  14. 'public_ip': '10.0.0.1',
  15. 'hostname': 'master-private.example.com',
  16. 'public_hostname': 'master.example.com'
  17. }
  18. },
  19. '10.0.0.2': {
  20. 'common': {
  21. 'ip': '10.0.0.2',
  22. 'public_ip': '10.0.0.2',
  23. 'hostname': 'node1-private.example.com',
  24. 'public_hostname': 'node1.example.com'
  25. }
  26. },
  27. '10.0.0.3': {
  28. 'common': {
  29. 'ip': '10.0.0.3',
  30. 'public_ip': '10.0.0.3',
  31. 'hostname': 'node2-private.example.com',
  32. 'public_hostname': 'node2.example.com'
  33. }
  34. },
  35. }
  36. MOCK_FACTS_QUICKHA = {
  37. '10.0.0.1': {
  38. 'common': {
  39. 'ip': '10.0.0.1',
  40. 'public_ip': '10.0.0.1',
  41. 'hostname': 'master-private.example.com',
  42. 'public_hostname': 'master.example.com'
  43. }
  44. },
  45. '10.0.0.2': {
  46. 'common': {
  47. 'ip': '10.0.0.2',
  48. 'public_ip': '10.0.0.2',
  49. 'hostname': 'node1-private.example.com',
  50. 'public_hostname': 'node1.example.com'
  51. }
  52. },
  53. '10.0.0.3': {
  54. 'common': {
  55. 'ip': '10.0.0.3',
  56. 'public_ip': '10.0.0.3',
  57. 'hostname': 'node2-private.example.com',
  58. 'public_hostname': 'node2.example.com'
  59. }
  60. },
  61. '10.0.0.4': {
  62. 'common': {
  63. 'ip': '10.0.0.4',
  64. 'public_ip': '10.0.0.4',
  65. 'hostname': 'proxy-private.example.com',
  66. 'public_hostname': 'proxy.example.com'
  67. }
  68. },
  69. '10.1.0.1': {
  70. 'common': {
  71. 'ip': '10.1.0.1',
  72. 'public_ip': '10.1.0.1',
  73. 'hostname': 'storage-private.example.com',
  74. 'public_hostname': 'storage.example.com'
  75. }
  76. },
  77. }
  78. # Missing connect_to on some hosts:
  79. BAD_CONFIG = """
  80. variant: %s
  81. ansible_ssh_user: root
  82. hosts:
  83. - connect_to: 10.0.0.1
  84. ip: 10.0.0.1
  85. hostname: master-private.example.com
  86. public_ip: 24.222.0.1
  87. public_hostname: master.example.com
  88. master: true
  89. node: true
  90. - ip: 10.0.0.2
  91. hostname: node1-private.example.com
  92. public_ip: 24.222.0.2
  93. public_hostname: node1.example.com
  94. node: true
  95. - connect_to: 10.0.0.3
  96. ip: 10.0.0.3
  97. hostname: node2-private.example.com
  98. public_ip: 24.222.0.3
  99. public_hostname: node2.example.com
  100. node: true
  101. """
  102. QUICKHA_CONFIG = """
  103. variant: %s
  104. ansible_ssh_user: root
  105. master_routingconfig_subdomain: example.com
  106. hosts:
  107. - connect_to: 10.0.0.1
  108. ip: 10.0.0.1
  109. hostname: master-private.example.com
  110. public_ip: 24.222.0.1
  111. public_hostname: master.example.com
  112. master: true
  113. node: true
  114. - connect_to: 10.0.0.2
  115. ip: 10.0.0.2
  116. hostname: node1-private.example.com
  117. public_ip: 24.222.0.2
  118. public_hostname: node1.example.com
  119. master: true
  120. node: true
  121. - connect_to: 10.0.0.3
  122. ip: 10.0.0.3
  123. hostname: node2-private.example.com
  124. public_ip: 24.222.0.3
  125. public_hostname: node2.example.com
  126. node: true
  127. master: true
  128. - connect_to: 10.0.0.4
  129. ip: 10.0.0.4
  130. hostname: node3-private.example.com
  131. public_ip: 24.222.0.4
  132. public_hostname: node3.example.com
  133. node: true
  134. - connect_to: 10.0.0.5
  135. ip: 10.0.0.5
  136. hostname: proxy-private.example.com
  137. public_ip: 24.222.0.5
  138. public_hostname: proxy.example.com
  139. master_lb: true
  140. - connect_to: 10.1.0.1
  141. ip: 10.1.0.1
  142. hostname: storage-private.example.com
  143. public_ip: 24.222.0.6
  144. public_hostname: storage.example.com
  145. storage: true
  146. """
  147. QUICKHA_2_MASTER_CONFIG = """
  148. variant: %s
  149. ansible_ssh_user: root
  150. hosts:
  151. - connect_to: 10.0.0.1
  152. ip: 10.0.0.1
  153. hostname: master-private.example.com
  154. public_ip: 24.222.0.1
  155. public_hostname: master.example.com
  156. master: true
  157. node: true
  158. - connect_to: 10.0.0.2
  159. ip: 10.0.0.2
  160. hostname: node1-private.example.com
  161. public_ip: 24.222.0.2
  162. public_hostname: node1.example.com
  163. master: true
  164. node: true
  165. - connect_to: 10.0.0.4
  166. ip: 10.0.0.4
  167. hostname: node3-private.example.com
  168. public_ip: 24.222.0.4
  169. public_hostname: node3.example.com
  170. node: true
  171. - connect_to: 10.0.0.5
  172. ip: 10.0.0.5
  173. hostname: proxy-private.example.com
  174. public_ip: 24.222.0.5
  175. public_hostname: proxy.example.com
  176. master_lb: true
  177. - connect_to: 10.1.0.1
  178. ip: 10.1.0.1
  179. hostname: storage-private.example.com
  180. public_ip: 24.222.0.6
  181. public_hostname: storage.example.com
  182. storage: true
  183. """
  184. QUICKHA_CONFIG_REUSED_LB = """
  185. variant: %s
  186. ansible_ssh_user: root
  187. hosts:
  188. - connect_to: 10.0.0.1
  189. ip: 10.0.0.1
  190. hostname: master-private.example.com
  191. public_ip: 24.222.0.1
  192. public_hostname: master.example.com
  193. master: true
  194. node: true
  195. - connect_to: 10.0.0.2
  196. ip: 10.0.0.2
  197. hostname: node1-private.example.com
  198. public_ip: 24.222.0.2
  199. public_hostname: node1.example.com
  200. master: true
  201. node: true
  202. master_lb: true
  203. - connect_to: 10.0.0.3
  204. ip: 10.0.0.3
  205. hostname: node2-private.example.com
  206. public_ip: 24.222.0.3
  207. public_hostname: node2.example.com
  208. node: true
  209. master: true
  210. - connect_to: 10.1.0.1
  211. ip: 10.1.0.1
  212. hostname: storage-private.example.com
  213. public_ip: 24.222.0.6
  214. public_hostname: storage.example.com
  215. storage: true
  216. """
  217. QUICKHA_CONFIG_NO_LB = """
  218. variant: %s
  219. ansible_ssh_user: root
  220. hosts:
  221. - connect_to: 10.0.0.1
  222. ip: 10.0.0.1
  223. hostname: master-private.example.com
  224. public_ip: 24.222.0.1
  225. public_hostname: master.example.com
  226. master: true
  227. node: true
  228. - connect_to: 10.0.0.2
  229. ip: 10.0.0.2
  230. hostname: node1-private.example.com
  231. public_ip: 24.222.0.2
  232. public_hostname: node1.example.com
  233. master: true
  234. node: true
  235. - connect_to: 10.0.0.3
  236. ip: 10.0.0.3
  237. hostname: node2-private.example.com
  238. public_ip: 24.222.0.3
  239. public_hostname: node2.example.com
  240. node: true
  241. master: true
  242. """
  243. QUICKHA_CONFIG_PRECONFIGURED_LB = """
  244. variant: %s
  245. ansible_ssh_user: root
  246. master_routingconfig_subdomain: example.com
  247. hosts:
  248. - connect_to: 10.0.0.1
  249. ip: 10.0.0.1
  250. hostname: master-private.example.com
  251. public_ip: 24.222.0.1
  252. public_hostname: master.example.com
  253. master: true
  254. node: true
  255. - connect_to: 10.0.0.2
  256. ip: 10.0.0.2
  257. hostname: node1-private.example.com
  258. public_ip: 24.222.0.2
  259. public_hostname: node1.example.com
  260. master: true
  261. node: true
  262. - connect_to: 10.0.0.3
  263. ip: 10.0.0.3
  264. hostname: node2-private.example.com
  265. public_ip: 24.222.0.3
  266. public_hostname: node2.example.com
  267. node: true
  268. master: true
  269. - connect_to: 10.0.0.4
  270. ip: 10.0.0.4
  271. hostname: node3-private.example.com
  272. public_ip: 24.222.0.4
  273. public_hostname: node3.example.com
  274. node: true
  275. - connect_to: proxy-private.example.com
  276. hostname: proxy-private.example.com
  277. public_hostname: proxy.example.com
  278. master_lb: true
  279. preconfigured: true
  280. - connect_to: 10.1.0.1
  281. ip: 10.1.0.1
  282. hostname: storage-private.example.com
  283. public_ip: 24.222.0.6
  284. public_hostname: storage.example.com
  285. storage: true
  286. """
  287. class UnattendedCliTests(OOCliFixture):
  288. def setUp(self):
  289. OOCliFixture.setUp(self)
  290. self.cli_args.append("-u")
  291. # unattended with config file and all installed hosts (without --force)
  292. @patch('ooinstall.openshift_ansible.run_main_playbook')
  293. @patch('ooinstall.openshift_ansible.load_system_facts')
  294. def test_get_hosts_to_run_on1(self, load_facts_mock, run_playbook_mock):
  295. mock_facts = copy.deepcopy(MOCK_FACTS)
  296. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  297. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  298. mock_facts['10.0.0.3']['common']['version'] = "3.0.0"
  299. load_facts_mock.return_value = (mock_facts, 0)
  300. run_playbook_mock.return_value = 0
  301. config_file = self.write_config(os.path.join(self.work_dir,
  302. 'ooinstall.conf'), SAMPLE_CONFIG % 'openshift-enterprise')
  303. self.cli_args.extend(["-c", config_file, "install"])
  304. result = self.runner.invoke(cli.cli, self.cli_args)
  305. if result.exception is None or result.exit_code != 1:
  306. print "Exit code: %s" % result.exit_code
  307. self.fail("Unexpected CLI return")
  308. # unattended with config file and all installed hosts (with --force)
  309. @patch('ooinstall.openshift_ansible.run_main_playbook')
  310. @patch('ooinstall.openshift_ansible.load_system_facts')
  311. def test_get_hosts_to_run_on2(self, load_facts_mock, run_playbook_mock):
  312. mock_facts = copy.deepcopy(MOCK_FACTS)
  313. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  314. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  315. mock_facts['10.0.0.3']['common']['version'] = "3.0.0"
  316. self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock, run_playbook_mock,
  317. cli_input=None,
  318. exp_hosts_len=3,
  319. exp_hosts_to_run_on_len=3,
  320. force=True)
  321. # unattended with config file and no installed hosts (without --force)
  322. @patch('ooinstall.openshift_ansible.run_main_playbook')
  323. @patch('ooinstall.openshift_ansible.load_system_facts')
  324. def test_get_hosts_to_run_on3(self, load_facts_mock, run_playbook_mock):
  325. load_facts_mock.return_value = (MOCK_FACTS, 0)
  326. run_playbook_mock.return_value = 0
  327. self._verify_get_hosts_to_run_on(MOCK_FACTS, load_facts_mock, run_playbook_mock,
  328. cli_input=None,
  329. exp_hosts_len=3,
  330. exp_hosts_to_run_on_len=3,
  331. force=False)
  332. # unattended with config file and no installed hosts (with --force)
  333. @patch('ooinstall.openshift_ansible.run_main_playbook')
  334. @patch('ooinstall.openshift_ansible.load_system_facts')
  335. def test_get_hosts_to_run_on4(self, load_facts_mock, run_playbook_mock):
  336. load_facts_mock.return_value = (MOCK_FACTS, 0)
  337. run_playbook_mock.return_value = 0
  338. self._verify_get_hosts_to_run_on(MOCK_FACTS, load_facts_mock, run_playbook_mock,
  339. cli_input=None,
  340. exp_hosts_len=3,
  341. exp_hosts_to_run_on_len=3,
  342. force=True)
  343. # unattended with config file and some installed some uninstalled hosts (without --force)
  344. @patch('ooinstall.openshift_ansible.run_main_playbook')
  345. @patch('ooinstall.openshift_ansible.load_system_facts')
  346. def test_get_hosts_to_run_on5(self, load_facts_mock, run_playbook_mock):
  347. mock_facts = copy.deepcopy(MOCK_FACTS)
  348. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  349. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  350. self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock, run_playbook_mock,
  351. cli_input=None,
  352. exp_hosts_len=3,
  353. exp_hosts_to_run_on_len=2,
  354. force=False)
  355. # unattended with config file and some installed some uninstalled hosts (with --force)
  356. @patch('ooinstall.openshift_ansible.run_main_playbook')
  357. @patch('ooinstall.openshift_ansible.load_system_facts')
  358. def test_get_hosts_to_run_on6(self, load_facts_mock, run_playbook_mock):
  359. mock_facts = copy.deepcopy(MOCK_FACTS)
  360. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  361. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  362. self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock, run_playbook_mock,
  363. cli_input=None,
  364. exp_hosts_len=3,
  365. exp_hosts_to_run_on_len=3,
  366. force=True)
  367. @patch('ooinstall.openshift_ansible.run_main_playbook')
  368. @patch('ooinstall.openshift_ansible.load_system_facts')
  369. def test_cfg_full_run(self, load_facts_mock, run_playbook_mock):
  370. load_facts_mock.return_value = (MOCK_FACTS, 0)
  371. run_playbook_mock.return_value = 0
  372. config_file = self.write_config(os.path.join(self.work_dir,
  373. 'ooinstall.conf'), SAMPLE_CONFIG % 'openshift-enterprise')
  374. self.cli_args.extend(["-c", config_file, "install"])
  375. result = self.runner.invoke(cli.cli, self.cli_args)
  376. self.assert_result(result, 0)
  377. load_facts_args = load_facts_mock.call_args[0]
  378. self.assertEquals(os.path.join(self.work_dir, "hosts"),
  379. load_facts_args[0])
  380. self.assertEquals(os.path.join(self.work_dir,
  381. "playbooks/byo/openshift_facts.yml"), load_facts_args[1])
  382. env_vars = load_facts_args[2]
  383. self.assertEquals(os.path.join(self.work_dir,
  384. '.ansible/callback_facts.yaml'),
  385. env_vars['OO_INSTALL_CALLBACK_FACTS_YAML'])
  386. self.assertEqual('/tmp/ansible.log', env_vars['ANSIBLE_LOG_PATH'])
  387. # If user running test has rpm installed, this might be set to default:
  388. self.assertTrue('ANSIBLE_CONFIG' not in env_vars or
  389. env_vars['ANSIBLE_CONFIG'] == cli.DEFAULT_ANSIBLE_CONFIG)
  390. # Make sure we ran on the expected masters and nodes:
  391. hosts = run_playbook_mock.call_args[0][1]
  392. hosts_to_run_on = run_playbook_mock.call_args[0][2]
  393. self.assertEquals(3, len(hosts))
  394. self.assertEquals(3, len(hosts_to_run_on))
  395. @patch('ooinstall.openshift_ansible.run_main_playbook')
  396. @patch('ooinstall.openshift_ansible.load_system_facts')
  397. def test_inventory_write(self, load_facts_mock, run_playbook_mock):
  398. # Add an ssh user so we can verify it makes it to the inventory file:
  399. merged_config = "%s\n%s" % (SAMPLE_CONFIG % 'openshift-enterprise',
  400. "ansible_ssh_user: bob")
  401. load_facts_mock.return_value = (MOCK_FACTS, 0)
  402. run_playbook_mock.return_value = 0
  403. config_file = self.write_config(os.path.join(self.work_dir,
  404. 'ooinstall.conf'), merged_config)
  405. self.cli_args.extend(["-c", config_file, "install"])
  406. result = self.runner.invoke(cli.cli, self.cli_args)
  407. self.assert_result(result, 0)
  408. # Check the inventory file looks as we would expect:
  409. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  410. inventory.read(os.path.join(self.work_dir, 'hosts'))
  411. self.assertEquals('bob',
  412. inventory.get('OSEv3:vars', 'ansible_ssh_user'))
  413. self.assertEquals('openshift-enterprise',
  414. inventory.get('OSEv3:vars', 'deployment_type'))
  415. # Check the masters:
  416. self.assertEquals(1, len(inventory.items('masters')))
  417. self.assertEquals(3, len(inventory.items('nodes')))
  418. for item in inventory.items('masters'):
  419. # ansible host lines do NOT parse nicely:
  420. master_line = item[0]
  421. if item[1] is not None:
  422. master_line = "%s=%s" % (master_line, item[1])
  423. self.assertTrue('openshift_ip' in master_line)
  424. self.assertTrue('openshift_public_ip' in master_line)
  425. self.assertTrue('openshift_hostname' in master_line)
  426. self.assertTrue('openshift_public_hostname' in master_line)
  427. @patch('ooinstall.openshift_ansible.run_main_playbook')
  428. @patch('ooinstall.openshift_ansible.load_system_facts')
  429. def test_variant_version_latest_assumed(self, load_facts_mock,
  430. run_playbook_mock):
  431. load_facts_mock.return_value = (MOCK_FACTS, 0)
  432. run_playbook_mock.return_value = 0
  433. config_file = self.write_config(os.path.join(self.work_dir,
  434. 'ooinstall.conf'), SAMPLE_CONFIG % 'openshift-enterprise')
  435. self.cli_args.extend(["-c", config_file, "install"])
  436. result = self.runner.invoke(cli.cli, self.cli_args)
  437. self.assert_result(result, 0)
  438. written_config = read_yaml(config_file)
  439. self.assertEquals('openshift-enterprise', written_config['variant'])
  440. # We didn't specify a version so the latest should have been assumed,
  441. # and written to disk:
  442. self.assertEquals('3.1', written_config['variant_version'])
  443. # Make sure the correct value was passed to ansible:
  444. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  445. inventory.read(os.path.join(self.work_dir, 'hosts'))
  446. self.assertEquals('openshift-enterprise',
  447. inventory.get('OSEv3:vars', 'deployment_type'))
  448. @patch('ooinstall.openshift_ansible.run_main_playbook')
  449. @patch('ooinstall.openshift_ansible.load_system_facts')
  450. def test_variant_version_preserved(self, load_facts_mock,
  451. run_playbook_mock):
  452. load_facts_mock.return_value = (MOCK_FACTS, 0)
  453. run_playbook_mock.return_value = 0
  454. config = SAMPLE_CONFIG % 'openshift-enterprise'
  455. config = '%s\n%s' % (config, 'variant_version: 3.0')
  456. config_file = self.write_config(os.path.join(self.work_dir,
  457. 'ooinstall.conf'), config)
  458. self.cli_args.extend(["-c", config_file, "install"])
  459. result = self.runner.invoke(cli.cli, self.cli_args)
  460. self.assert_result(result, 0)
  461. written_config = read_yaml(config_file)
  462. self.assertEquals('openshift-enterprise', written_config['variant'])
  463. # Make sure our older version was preserved:
  464. # and written to disk:
  465. self.assertEquals('3.0', written_config['variant_version'])
  466. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  467. inventory.read(os.path.join(self.work_dir, 'hosts'))
  468. self.assertEquals('enterprise',
  469. inventory.get('OSEv3:vars', 'deployment_type'))
  470. @patch('ooinstall.openshift_ansible.run_ansible')
  471. @patch('ooinstall.openshift_ansible.load_system_facts')
  472. def test_no_ansible_config_specified(self, load_facts_mock, run_ansible_mock):
  473. load_facts_mock.return_value = (MOCK_FACTS, 0)
  474. run_ansible_mock.return_value = 0
  475. config = SAMPLE_CONFIG % 'openshift-enterprise'
  476. self._ansible_config_test(load_facts_mock, run_ansible_mock,
  477. config, None, None)
  478. @patch('ooinstall.openshift_ansible.run_ansible')
  479. @patch('ooinstall.openshift_ansible.load_system_facts')
  480. def test_ansible_config_specified_cli(self, load_facts_mock, run_ansible_mock):
  481. load_facts_mock.return_value = (MOCK_FACTS, 0)
  482. run_ansible_mock.return_value = 0
  483. config = SAMPLE_CONFIG % 'openshift-enterprise'
  484. ansible_config = os.path.join(self.work_dir, 'ansible.cfg')
  485. self._ansible_config_test(load_facts_mock, run_ansible_mock,
  486. config, ansible_config, ansible_config)
  487. @patch('ooinstall.openshift_ansible.run_ansible')
  488. @patch('ooinstall.openshift_ansible.load_system_facts')
  489. def test_ansible_config_specified_in_installer_config(self,
  490. load_facts_mock, run_ansible_mock):
  491. load_facts_mock.return_value = (MOCK_FACTS, 0)
  492. run_ansible_mock.return_value = 0
  493. ansible_config = os.path.join(self.work_dir, 'ansible.cfg')
  494. config = SAMPLE_CONFIG % 'openshift-enterprise'
  495. config = "%s\nansible_config: %s" % (config, ansible_config)
  496. self._ansible_config_test(load_facts_mock, run_ansible_mock,
  497. config, None, ansible_config)
  498. #pylint: disable=too-many-arguments
  499. # This method allows for drastically simpler tests to write, and the args
  500. # are all useful.
  501. def _ansible_config_test(self, load_facts_mock, run_ansible_mock,
  502. installer_config, ansible_config_cli=None, expected_result=None):
  503. """
  504. Utility method for testing the ways you can specify the ansible config.
  505. """
  506. load_facts_mock.return_value = (MOCK_FACTS, 0)
  507. run_ansible_mock.return_value = 0
  508. config_file = self.write_config(os.path.join(self.work_dir,
  509. 'ooinstall.conf'), installer_config)
  510. self.cli_args.extend(["-c", config_file])
  511. if ansible_config_cli:
  512. self.cli_args.extend(["--ansible-config", ansible_config_cli])
  513. self.cli_args.append("install")
  514. result = self.runner.invoke(cli.cli, self.cli_args)
  515. self.assert_result(result, 0)
  516. # Test the env vars for facts playbook:
  517. facts_env_vars = load_facts_mock.call_args[0][2]
  518. if expected_result:
  519. self.assertEquals(expected_result, facts_env_vars['ANSIBLE_CONFIG'])
  520. else:
  521. # If user running test has rpm installed, this might be set to default:
  522. self.assertTrue('ANSIBLE_CONFIG' not in facts_env_vars or
  523. facts_env_vars['ANSIBLE_CONFIG'] == cli.DEFAULT_ANSIBLE_CONFIG)
  524. # Test the env vars for main playbook:
  525. env_vars = run_ansible_mock.call_args[0][2]
  526. if expected_result:
  527. self.assertEquals(expected_result, env_vars['ANSIBLE_CONFIG'])
  528. else:
  529. # If user running test has rpm installed, this might be set to default:
  530. self.assertTrue('ANSIBLE_CONFIG' not in env_vars or
  531. env_vars['ANSIBLE_CONFIG'] == cli.DEFAULT_ANSIBLE_CONFIG)
  532. # unattended with bad config file and no installed hosts (without --force)
  533. @patch('ooinstall.openshift_ansible.run_main_playbook')
  534. @patch('ooinstall.openshift_ansible.load_system_facts')
  535. def test_bad_config(self, load_facts_mock, run_playbook_mock):
  536. load_facts_mock.return_value = (MOCK_FACTS, 0)
  537. run_playbook_mock.return_value = 0
  538. config_file = self.write_config(os.path.join(self.work_dir,
  539. 'ooinstall.conf'), BAD_CONFIG % 'openshift-enterprise')
  540. self.cli_args.extend(["-c", config_file, "install"])
  541. result = self.runner.invoke(cli.cli, self.cli_args)
  542. self.assertEquals(1, result.exit_code)
  543. self.assertTrue("You must specify either an ip or hostname"
  544. in result.output)
  545. #unattended with three masters, one node, and haproxy
  546. @patch('ooinstall.openshift_ansible.run_main_playbook')
  547. @patch('ooinstall.openshift_ansible.load_system_facts')
  548. def test_quick_ha_full_run(self, load_facts_mock, run_playbook_mock):
  549. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  550. run_playbook_mock.return_value = 0
  551. config_file = self.write_config(os.path.join(self.work_dir,
  552. 'ooinstall.conf'), QUICKHA_CONFIG % 'openshift-enterprise')
  553. self.cli_args.extend(["-c", config_file, "install"])
  554. result = self.runner.invoke(cli.cli, self.cli_args)
  555. self.assert_result(result, 0)
  556. # Make sure we ran on the expected masters and nodes:
  557. hosts = run_playbook_mock.call_args[0][1]
  558. hosts_to_run_on = run_playbook_mock.call_args[0][2]
  559. self.assertEquals(6, len(hosts))
  560. self.assertEquals(6, len(hosts_to_run_on))
  561. #unattended with two masters, one node, and haproxy
  562. @patch('ooinstall.openshift_ansible.run_main_playbook')
  563. @patch('ooinstall.openshift_ansible.load_system_facts')
  564. def test_quick_ha_only_2_masters(self, load_facts_mock, run_playbook_mock):
  565. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  566. run_playbook_mock.return_value = 0
  567. config_file = self.write_config(os.path.join(self.work_dir,
  568. 'ooinstall.conf'), QUICKHA_2_MASTER_CONFIG % 'openshift-enterprise')
  569. self.cli_args.extend(["-c", config_file, "install"])
  570. result = self.runner.invoke(cli.cli, self.cli_args)
  571. # This is an invalid config:
  572. self.assert_result(result, 1)
  573. self.assertTrue("A minimum of 3 Masters are required" in result.output)
  574. #unattended with three masters, one node, but no load balancer specified:
  575. @patch('ooinstall.openshift_ansible.run_main_playbook')
  576. @patch('ooinstall.openshift_ansible.load_system_facts')
  577. def test_quick_ha_no_lb(self, load_facts_mock, run_playbook_mock):
  578. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  579. run_playbook_mock.return_value = 0
  580. config_file = self.write_config(os.path.join(self.work_dir,
  581. 'ooinstall.conf'), QUICKHA_CONFIG_NO_LB % 'openshift-enterprise')
  582. self.cli_args.extend(["-c", config_file, "install"])
  583. result = self.runner.invoke(cli.cli, self.cli_args)
  584. # This is not a valid input:
  585. self.assert_result(result, 1)
  586. self.assertTrue('No master load balancer specified in config' in result.output)
  587. #unattended with three masters, one node, and one of the masters reused as load balancer:
  588. @patch('ooinstall.openshift_ansible.run_main_playbook')
  589. @patch('ooinstall.openshift_ansible.load_system_facts')
  590. def test_quick_ha_reused_lb(self, load_facts_mock, run_playbook_mock):
  591. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  592. run_playbook_mock.return_value = 0
  593. config_file = self.write_config(os.path.join(self.work_dir,
  594. 'ooinstall.conf'), QUICKHA_CONFIG_REUSED_LB % 'openshift-enterprise')
  595. self.cli_args.extend(["-c", config_file, "install"])
  596. result = self.runner.invoke(cli.cli, self.cli_args)
  597. # This is not a valid configuration:
  598. self.assert_result(result, 1)
  599. #unattended with preconfigured lb
  600. @patch('ooinstall.openshift_ansible.run_main_playbook')
  601. @patch('ooinstall.openshift_ansible.load_system_facts')
  602. def test_quick_ha_preconfigured_lb(self, load_facts_mock, run_playbook_mock):
  603. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  604. run_playbook_mock.return_value = 0
  605. config_file = self.write_config(os.path.join(self.work_dir,
  606. 'ooinstall.conf'), QUICKHA_CONFIG_PRECONFIGURED_LB % 'openshift-enterprise')
  607. self.cli_args.extend(["-c", config_file, "install"])
  608. result = self.runner.invoke(cli.cli, self.cli_args)
  609. self.assert_result(result, 0)
  610. # Make sure we ran on the expected masters and nodes:
  611. hosts = run_playbook_mock.call_args[0][1]
  612. hosts_to_run_on = run_playbook_mock.call_args[0][2]
  613. self.assertEquals(6, len(hosts))
  614. self.assertEquals(6, len(hosts_to_run_on))
  615. class AttendedCliTests(OOCliFixture):
  616. def setUp(self):
  617. OOCliFixture.setUp(self)
  618. # Doesn't exist but keeps us from reading the local users config:
  619. self.config_file = os.path.join(self.work_dir, 'config.yml')
  620. self.cli_args.extend(["-c", self.config_file])
  621. @patch('ooinstall.openshift_ansible.run_main_playbook')
  622. @patch('ooinstall.openshift_ansible.load_system_facts')
  623. def test_full_run(self, load_facts_mock, run_playbook_mock):
  624. load_facts_mock.return_value = (MOCK_FACTS, 0)
  625. run_playbook_mock.return_value = 0
  626. cli_input = build_input(hosts=[
  627. ('10.0.0.1', True, False),
  628. ('10.0.0.2', False, False),
  629. ('10.0.0.3', False, False)],
  630. ssh_user='root',
  631. variant_num=1,
  632. confirm_facts='y')
  633. self.cli_args.append("install")
  634. result = self.runner.invoke(cli.cli, self.cli_args,
  635. input=cli_input)
  636. self.assert_result(result, 0)
  637. self._verify_load_facts(load_facts_mock)
  638. self._verify_run_playbook(run_playbook_mock, 3, 3)
  639. written_config = read_yaml(self.config_file)
  640. self._verify_config_hosts(written_config, 3)
  641. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  642. inventory.read(os.path.join(self.work_dir, 'hosts'))
  643. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.1',
  644. 'openshift_schedulable=False')
  645. self.assert_inventory_host_var_unset(inventory, 'nodes', '10.0.0.2',
  646. 'openshift_schedulable')
  647. self.assert_inventory_host_var_unset(inventory, 'nodes', '10.0.0.3',
  648. 'openshift_schedulable')
  649. # interactive with config file and some installed some uninstalled hosts
  650. @patch('ooinstall.openshift_ansible.run_main_playbook')
  651. @patch('ooinstall.openshift_ansible.load_system_facts')
  652. def test_add_nodes(self, load_facts_mock, run_playbook_mock):
  653. # Modify the mock facts to return a version indicating OpenShift
  654. # is already installed on our master, and the first node.
  655. mock_facts = copy.deepcopy(MOCK_FACTS)
  656. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  657. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  658. load_facts_mock.return_value = (mock_facts, 0)
  659. run_playbook_mock.return_value = 0
  660. cli_input = build_input(hosts=[
  661. ('10.0.0.1', True, False),
  662. ('10.0.0.2', False, False),
  663. ],
  664. add_nodes=[('10.0.0.3', False, False)],
  665. ssh_user='root',
  666. variant_num=1,
  667. confirm_facts='y')
  668. self.cli_args.append("install")
  669. result = self.runner.invoke(cli.cli,
  670. self.cli_args,
  671. input=cli_input)
  672. self.assert_result(result, 0)
  673. self._verify_load_facts(load_facts_mock)
  674. self._verify_run_playbook(run_playbook_mock, 3, 2)
  675. written_config = read_yaml(self.config_file)
  676. self._verify_config_hosts(written_config, 3)
  677. @patch('ooinstall.openshift_ansible.run_main_playbook')
  678. @patch('ooinstall.openshift_ansible.load_system_facts')
  679. def test_fresh_install_with_config(self, load_facts_mock, run_playbook_mock):
  680. load_facts_mock.return_value = (MOCK_FACTS, 0)
  681. run_playbook_mock.return_value = 0
  682. config_file = self.write_config(os.path.join(self.work_dir,
  683. 'ooinstall.conf'),
  684. SAMPLE_CONFIG % 'openshift-enterprise')
  685. cli_input = build_input(confirm_facts='y')
  686. self.cli_args.extend(["-c", config_file])
  687. self.cli_args.append("install")
  688. result = self.runner.invoke(cli.cli,
  689. self.cli_args,
  690. input=cli_input)
  691. self.assert_result(result, 0)
  692. self._verify_load_facts(load_facts_mock)
  693. self._verify_run_playbook(run_playbook_mock, 3, 3)
  694. written_config = read_yaml(config_file)
  695. self._verify_config_hosts(written_config, 3)
  696. #interactive with config file and all installed hosts
  697. @patch('ooinstall.openshift_ansible.run_main_playbook')
  698. @patch('ooinstall.openshift_ansible.load_system_facts')
  699. def test_get_hosts_to_run_on(self, load_facts_mock, run_playbook_mock):
  700. mock_facts = copy.deepcopy(MOCK_FACTS)
  701. mock_facts['10.0.0.1']['common']['version'] = "3.0.0"
  702. mock_facts['10.0.0.2']['common']['version'] = "3.0.0"
  703. cli_input = build_input(hosts=[
  704. ('10.0.0.1', True, False),
  705. ],
  706. add_nodes=[('10.0.0.2', False, False)],
  707. ssh_user='root',
  708. variant_num=1,
  709. schedulable_masters_ok=True,
  710. confirm_facts='y')
  711. self._verify_get_hosts_to_run_on(mock_facts, load_facts_mock,
  712. run_playbook_mock,
  713. cli_input,
  714. exp_hosts_len=2,
  715. exp_hosts_to_run_on_len=2,
  716. force=False)
  717. #interactive multimaster: one more node than master
  718. @patch('ooinstall.openshift_ansible.run_main_playbook')
  719. @patch('ooinstall.openshift_ansible.load_system_facts')
  720. def test_ha_dedicated_node(self, load_facts_mock, run_playbook_mock):
  721. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  722. run_playbook_mock.return_value = 0
  723. cli_input = build_input(hosts=[
  724. ('10.0.0.1', True, False),
  725. ('10.0.0.2', True, False),
  726. ('10.0.0.3', True, False),
  727. ('10.0.0.4', False, False)],
  728. ssh_user='root',
  729. variant_num=1,
  730. confirm_facts='y',
  731. master_lb=('10.0.0.5', False),
  732. storage='10.1.0.1',)
  733. self.cli_args.append("install")
  734. result = self.runner.invoke(cli.cli, self.cli_args,
  735. input=cli_input)
  736. self.assert_result(result, 0)
  737. self._verify_load_facts(load_facts_mock)
  738. self._verify_run_playbook(run_playbook_mock, 6, 6)
  739. written_config = read_yaml(self.config_file)
  740. self._verify_config_hosts(written_config, 6)
  741. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  742. inventory.read(os.path.join(self.work_dir, 'hosts'))
  743. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.1',
  744. 'openshift_schedulable=False')
  745. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.2',
  746. 'openshift_schedulable=False')
  747. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.3',
  748. 'openshift_schedulable=False')
  749. self.assert_inventory_host_var_unset(inventory, 'nodes', '10.0.0.4',
  750. 'openshift_schedulable')
  751. self.assertTrue(inventory.has_section('etcd'))
  752. self.assertEquals(3, len(inventory.items('etcd')))
  753. #interactive multimaster: identical masters and nodes
  754. @patch('ooinstall.openshift_ansible.run_main_playbook')
  755. @patch('ooinstall.openshift_ansible.load_system_facts')
  756. def test_ha_no_dedicated_nodes(self, load_facts_mock, run_playbook_mock):
  757. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  758. run_playbook_mock.return_value = 0
  759. cli_input = build_input(hosts=[
  760. ('10.0.0.1', True, False),
  761. ('10.0.0.2', True, False),
  762. ('10.0.0.3', True, False)],
  763. ssh_user='root',
  764. variant_num=1,
  765. confirm_facts='y',
  766. master_lb=('10.0.0.5', False),
  767. storage='10.1.0.1',)
  768. self.cli_args.append("install")
  769. result = self.runner.invoke(cli.cli, self.cli_args,
  770. input=cli_input)
  771. self.assert_result(result, 0)
  772. self._verify_load_facts(load_facts_mock)
  773. self._verify_run_playbook(run_playbook_mock, 5, 5)
  774. written_config = read_yaml(self.config_file)
  775. self._verify_config_hosts(written_config, 5)
  776. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  777. inventory.read(os.path.join(self.work_dir, 'hosts'))
  778. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.1',
  779. 'openshift_schedulable=True')
  780. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.2',
  781. 'openshift_schedulable=True')
  782. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.3',
  783. 'openshift_schedulable=True')
  784. # Checks the inventory (as a ConfigParser) for the given host, host
  785. # variable, and expected value.
  786. def assert_inventory_host_var(self, inventory, section, host, variable):
  787. # Config parser splits on the first "=", so we end up with:
  788. # 'hostname key1' -> 'val1 key2=val2 key3=val3'
  789. #
  790. # Convert to something easier to test:
  791. for (a, b) in inventory.items(section):
  792. full_line = "%s=%s" % (a, b)
  793. tokens = full_line.split()
  794. if tokens[0] == host:
  795. found = False
  796. for token in tokens:
  797. if token == variable:
  798. found = True
  799. continue
  800. self.assertTrue("Unable to find %s in line: %s" %
  801. (variable, full_line), found)
  802. return
  803. self.fail("unable to find host %s in inventory" % host)
  804. def assert_inventory_host_var_unset(self, inventory, section, host, variable):
  805. # Config parser splits on the first "=", so we end up with:
  806. # 'hostname key1' -> 'val1 key2=val2 key3=val3'
  807. #
  808. # Convert to something easier to test:
  809. for (a, b) in inventory.items(section):
  810. full_line = "%s=%s" % (a, b)
  811. tokens = full_line.split()
  812. if tokens[0] == host:
  813. self.assertFalse(("%s=" % variable) in full_line,
  814. msg='%s host variable was set: %s' %
  815. (variable, full_line))
  816. return
  817. self.fail("unable to find host %s in inventory" % host)
  818. #interactive multimaster: attempting to use a master as the load balancer should fail:
  819. @patch('ooinstall.openshift_ansible.run_main_playbook')
  820. @patch('ooinstall.openshift_ansible.load_system_facts')
  821. def test_ha_reuse_master_as_lb(self, load_facts_mock, run_playbook_mock):
  822. load_facts_mock.return_value = (MOCK_FACTS_QUICKHA, 0)
  823. run_playbook_mock.return_value = 0
  824. cli_input = build_input(hosts=[
  825. ('10.0.0.1', True, False),
  826. ('10.0.0.2', True, False),
  827. ('10.0.0.3', False, False),
  828. ('10.0.0.4', True, False)],
  829. ssh_user='root',
  830. variant_num=1,
  831. confirm_facts='y',
  832. master_lb=(['10.0.0.2', '10.0.0.5'], False),
  833. storage='10.1.0.1')
  834. self.cli_args.append("install")
  835. result = self.runner.invoke(cli.cli, self.cli_args,
  836. input=cli_input)
  837. self.assert_result(result, 0)
  838. #interactive all-in-one
  839. @patch('ooinstall.openshift_ansible.run_main_playbook')
  840. @patch('ooinstall.openshift_ansible.load_system_facts')
  841. def test_all_in_one(self, load_facts_mock, run_playbook_mock):
  842. load_facts_mock.return_value = (MOCK_FACTS, 0)
  843. run_playbook_mock.return_value = 0
  844. cli_input = build_input(hosts=[
  845. ('10.0.0.1', True, False)],
  846. ssh_user='root',
  847. variant_num=1,
  848. confirm_facts='y')
  849. self.cli_args.append("install")
  850. result = self.runner.invoke(cli.cli, self.cli_args,
  851. input=cli_input)
  852. self.assert_result(result, 0)
  853. self._verify_load_facts(load_facts_mock)
  854. self._verify_run_playbook(run_playbook_mock, 1, 1)
  855. written_config = read_yaml(self.config_file)
  856. self._verify_config_hosts(written_config, 1)
  857. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  858. inventory.read(os.path.join(self.work_dir, 'hosts'))
  859. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.1',
  860. 'openshift_schedulable=True')
  861. #interactive 3.0 install confirm no HA hints
  862. @patch('ooinstall.openshift_ansible.run_main_playbook')
  863. @patch('ooinstall.openshift_ansible.load_system_facts')
  864. def test_ha_hint(self, load_facts_mock, run_playbook_mock):
  865. load_facts_mock.return_value = (MOCK_FACTS, 0)
  866. run_playbook_mock.return_value = 0
  867. cli_input = build_input(hosts=[
  868. ('10.0.0.1', True, False)],
  869. ssh_user='root',
  870. variant_num=2,
  871. confirm_facts='y')
  872. self.cli_args.append("install")
  873. result = self.runner.invoke(cli.cli, self.cli_args,
  874. input=cli_input)
  875. self.assert_result(result, 0)
  876. self.assertTrue("NOTE: Add a total of 3 or more Masters to perform an HA installation."
  877. not in result.output)
  878. @patch('ooinstall.openshift_ansible.run_main_playbook')
  879. @patch('ooinstall.openshift_ansible.load_system_facts')
  880. def test_gen_inventory(self, load_facts_mock, run_playbook_mock):
  881. load_facts_mock.return_value = (MOCK_FACTS, 0)
  882. run_playbook_mock.return_value = 0
  883. cli_input = build_input(hosts=[
  884. ('10.0.0.1', True, False),
  885. ('10.0.0.2', False, False),
  886. ('10.0.0.3', False, False)],
  887. ssh_user='root',
  888. variant_num=1,
  889. confirm_facts='y')
  890. self.cli_args.append("install")
  891. self.cli_args.append("--gen-inventory")
  892. result = self.runner.invoke(cli.cli, self.cli_args,
  893. input=cli_input)
  894. self.assert_result(result, 0)
  895. self._verify_load_facts(load_facts_mock)
  896. # Make sure run playbook wasn't called:
  897. self.assertEquals(0, len(run_playbook_mock.mock_calls))
  898. written_config = read_yaml(self.config_file)
  899. self._verify_config_hosts(written_config, 3)
  900. inventory = ConfigParser.ConfigParser(allow_no_value=True)
  901. inventory.read(os.path.join(self.work_dir, 'hosts'))
  902. self.assert_inventory_host_var(inventory, 'nodes', '10.0.0.1',
  903. 'openshift_schedulable=False')
  904. self.assert_inventory_host_var_unset(inventory, 'nodes', '10.0.0.2',
  905. 'openshift_schedulable')
  906. self.assert_inventory_host_var_unset(inventory, 'nodes', '10.0.0.3',
  907. 'openshift_schedulable')
  908. # TODO: test with config file, attended add node
  909. # TODO: test with config file, attended new node already in config file
  910. # TODO: test with config file, attended new node already in config file, plus manually added nodes
  911. # TODO: test with config file, attended reject facts