Container Infrastructure Management Service for OpenStack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1288 lines
58 KiB

  1. # Copyright 2015 Hewlett-Packard Development Company, L.P.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. # not use this file except in compliance with the License. You may obtain
  5. # a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. # License for the specific language governing permissions and limitations
  13. # under the License.
  14. import mock
  15. from mock import patch
  16. import magnum.conf
  17. from magnum.drivers.k8s_coreos_v1 import driver as k8s_coreos_dr
  18. from magnum.drivers.k8s_fedora_atomic_v1 import driver as k8s_dr
  19. from magnum import objects
  20. from magnum.tests import base
  21. CONF = magnum.conf.CONF
  22. class TestClusterConductorWithK8s(base.TestCase):
  23. def setUp(self):
  24. super(TestClusterConductorWithK8s, self).setUp()
  25. self.keystone_auth_default_policy = ('[{"match": [{"type": "role", '
  26. '"values": ["member"]}, {"type": '
  27. '"project", "values": '
  28. '["project_id"]}], "resource": '
  29. '{"namespace": "default", '
  30. '"resources": ["pods", '
  31. '"services", "deployments", '
  32. '"pvc"], "verbs": ["list"], '
  33. '"version": "*"}}]')
  34. self.cluster_template_dict = {
  35. 'image_id': 'image_id',
  36. 'flavor_id': 'flavor_id',
  37. 'master_flavor_id': 'master_flavor_id',
  38. 'keypair_id': 'keypair_id',
  39. 'dns_nameserver': 'dns_nameserver',
  40. 'external_network_id': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  41. 'fixed_network': 'fixed_network',
  42. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  43. 'network_driver': 'network_driver',
  44. 'volume_driver': 'volume_driver',
  45. 'docker_volume_size': 20,
  46. 'master_flavor_id': 'flavor_id',
  47. 'docker_storage_driver': 'devicemapper',
  48. 'cluster_distro': 'fedora-atomic',
  49. 'coe': 'kubernetes',
  50. 'token': None,
  51. 'http_proxy': 'http_proxy',
  52. 'https_proxy': 'https_proxy',
  53. 'no_proxy': 'no_proxy',
  54. 'labels': {'flannel_network_cidr': '10.101.0.0/16',
  55. 'flannel_network_subnetlen': '26',
  56. 'flannel_backend': 'vxlan',
  57. 'system_pods_initial_delay': '15',
  58. 'system_pods_timeout': '1',
  59. 'admission_control_list': 'fake_list',
  60. 'prometheus_monitoring': 'False',
  61. 'grafana_admin_passwd': 'fake_pwd',
  62. 'kube_dashboard_enabled': 'True',
  63. 'influx_grafana_dashboard_enabled': 'True',
  64. 'docker_volume_type': 'lvmdriver-1',
  65. 'etcd_volume_size': 0,
  66. 'availability_zone': 'az_1',
  67. 'service_cluster_ip_range': '10.254.0.0/16'},
  68. 'tls_disabled': False,
  69. 'server_type': 'vm',
  70. 'registry_enabled': False,
  71. 'insecure_registry': '10.0.0.1:5000',
  72. 'master_lb_enabled': False,
  73. 'floating_ip_enabled': False,
  74. }
  75. self.cluster_dict = {
  76. 'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
  77. 'cluster_template_id': 'xx-xx-xx-xx',
  78. 'keypair': 'keypair_id',
  79. 'name': 'cluster1',
  80. 'stack_id': 'xx-xx-xx-xx',
  81. 'api_address': '172.17.2.3',
  82. 'discovery_url': 'https://discovery.etcd.io/test',
  83. 'docker_volume_size': 20,
  84. 'flavor_id': 'flavor_id',
  85. 'ca_cert_ref': 'http://barbican/v1/containers/xx-xx-xx-xx',
  86. 'magnum_cert_ref': 'http://barbican/v1/containers/xx-xx-xx-xx',
  87. 'trustee_username': 'fake_trustee',
  88. 'trustee_password': 'fake_trustee_password',
  89. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  90. 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
  91. 'coe_version': 'fake-version',
  92. 'labels': {'flannel_network_cidr': '10.101.0.0/16',
  93. 'flannel_network_subnetlen': '26',
  94. 'flannel_backend': 'vxlan',
  95. 'system_pods_initial_delay': '15',
  96. 'system_pods_timeout': '1',
  97. 'admission_control_list': 'fake_list',
  98. 'prometheus_monitoring': 'False',
  99. 'grafana_admin_passwd': 'fake_pwd',
  100. 'kube_dashboard_enabled': 'True',
  101. 'docker_volume_type': 'lvmdriver-1',
  102. 'availability_zone': 'az_1',
  103. 'cert_manager_api': 'False',
  104. 'ingress_controller': 'i-controller',
  105. 'ingress_controller_role': 'i-controller-role',
  106. 'kubelet_options': '--kubelet',
  107. 'kubeapi_options': '--kubeapi',
  108. 'kubecontroller_options': '--kubecontroller',
  109. 'kubescheduler_options': '--kubescheduler',
  110. 'kubeproxy_options': '--kubeproxy',
  111. 'influx_grafana_dashboard_enabled': 'True',
  112. 'service_cluster_ip_range': '10.254.0.0/16',
  113. 'boot_volume_size': '60'},
  114. 'master_flavor_id': 'master_flavor_id',
  115. 'flavor_id': 'flavor_id',
  116. 'project_id': 'project_id',
  117. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  118. 'fixed_network': 'fixed_network',
  119. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  120. 'floating_ip_enabled': False,
  121. }
  122. self.worker_ng_dict = {
  123. 'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a53',
  124. 'name': 'worker_ng',
  125. 'cluster_id': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
  126. 'project_id': 'project_id',
  127. 'docker_volume_size': 20,
  128. 'labels': self.cluster_dict['labels'],
  129. 'flavor_id': 'flavor_id',
  130. 'image_id': 'image_id',
  131. 'node_addresses': ['172.17.2.4'],
  132. 'node_count': 1,
  133. 'role': 'worker',
  134. 'max_nodes': 5,
  135. 'min_nodes': 1,
  136. 'is_default': True
  137. }
  138. self.master_ng_dict = {
  139. 'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a54',
  140. 'name': 'master_ng',
  141. 'cluster_id': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
  142. 'project_id': 'project_id',
  143. 'docker_volume_size': 20,
  144. 'labels': self.cluster_dict['labels'],
  145. 'flavor_id': 'master_flavor_id',
  146. 'image_id': 'image_id',
  147. 'node_addresses': ['172.17.2.18'],
  148. 'node_count': 1,
  149. 'role': 'master',
  150. 'max_nodes': 5,
  151. 'min_nodes': 1,
  152. 'is_default': True
  153. }
  154. self.context.user_name = 'fake_user'
  155. self.context.project_id = 'fake_tenant'
  156. osc_patcher = mock.patch('magnum.common.clients.OpenStackClients')
  157. self.mock_osc_class = osc_patcher.start()
  158. self.addCleanup(osc_patcher.stop)
  159. self.mock_osc = mock.MagicMock()
  160. mock_keypair = mock.MagicMock()
  161. mock_keypair.public_key = 'ssh-rsa AAAAB3Nz'
  162. self.mock_nova = mock.MagicMock()
  163. self.mock_nova.keypairs.get.return_value = mock_keypair
  164. self.mock_osc.nova.return_value = self.mock_nova
  165. self.mock_osc.url_for.return_value = 'http://192.168.10.10:5000/v3'
  166. self.mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
  167. self.mock_osc.cinder_region_name.return_value = 'RegionOne'
  168. self.mock_keystone = mock.MagicMock()
  169. self.mock_keystone.trustee_domain_id = 'trustee_domain_id'
  170. self.mock_osc.keystone.return_value = self.mock_keystone
  171. self.mock_osc_class.return_value = self.mock_osc
  172. octavia_patcher = mock.patch(
  173. 'magnum.common.keystone.is_octavia_enabled'
  174. )
  175. self.mock_enable_octavia = octavia_patcher.start()
  176. self.mock_enable_octavia.return_value = False
  177. self.addCleanup(octavia_patcher.stop)
  178. CONF.set_override('default_boot_volume_type',
  179. 'lvmdriver-1', group='cinder')
  180. CONF.set_override('default_etcd_volume_type',
  181. 'lvmdriver-1', group='cinder')
  182. @patch('requests.get')
  183. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  184. @patch('magnum.objects.NodeGroup.list')
  185. @patch('magnum.drivers.common.driver.Driver.get_driver')
  186. @patch('magnum.conductor.handlers.common.cert_manager'
  187. '.sign_node_certificate')
  188. @patch('magnum.common.x509.operations.generate_csr_and_key')
  189. def test_extract_template_definition(
  190. self,
  191. mock_generate_csr_and_key,
  192. mock_sign_node_certificate,
  193. mock_driver,
  194. mock_objects_nodegroup_list,
  195. mock_objects_cluster_template_get_by_uuid,
  196. mock_get):
  197. self._test_extract_template_definition(
  198. mock_generate_csr_and_key, mock_sign_node_certificate,
  199. mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get,
  200. mock_objects_nodegroup_list)
  201. def _test_extract_template_definition(
  202. self,
  203. mock_generate_csr_and_key,
  204. mock_sign_node_certificate,
  205. mock_driver,
  206. mock_objects_cluster_template_get_by_uuid,
  207. mock_get,
  208. mock_objects_nodegroup_list,
  209. missing_attr=None):
  210. if missing_attr in self.cluster_template_dict:
  211. self.cluster_template_dict[missing_attr] = None
  212. elif missing_attr in self.cluster_dict:
  213. self.cluster_dict[missing_attr] = None
  214. if missing_attr == 'image_id':
  215. del self.worker_ng_dict['image_id']
  216. del self.master_ng_dict['image_id']
  217. cluster_template = objects.ClusterTemplate(
  218. self.context, **self.cluster_template_dict)
  219. mock_generate_csr_and_key.return_value = {'csr': 'csr',
  220. 'private_key': 'private_key',
  221. 'public_key': 'public_key'}
  222. mock_sign_node_certificate.return_value = 'signed_cert'
  223. mock_objects_cluster_template_get_by_uuid.return_value = \
  224. cluster_template
  225. expected_result = str('{"action":"get","node":{"key":"test","value":'
  226. '"1","modifiedIndex":10,"createdIndex":10}}')
  227. mock_resp = mock.MagicMock()
  228. mock_resp.text = expected_result
  229. mock_resp.status_code = 200
  230. mock_get.return_value = mock_resp
  231. cluster = objects.Cluster(self.context, **self.cluster_dict)
  232. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  233. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  234. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  235. mock_driver.return_value = k8s_dr.Driver()
  236. (template_path,
  237. definition,
  238. env_files) = mock_driver()._extract_template_definition(self.context,
  239. cluster)
  240. mapping = {
  241. 'dns_nameserver': 'dns_nameserver',
  242. 'flavor_id': 'minion_flavor',
  243. 'docker_volume_size': 'docker_volume_size',
  244. 'docker_storage_driver': 'docker_storage_driver',
  245. 'network_driver': 'network_driver',
  246. 'volume_driver': 'volume_driver',
  247. 'master_flavor_id': 'master_flavor',
  248. 'apiserver_port': '',
  249. 'node_count': 'number_of_minions',
  250. 'master_count': 'number_of_masters',
  251. 'discovery_url': 'discovery_url',
  252. 'labels': {'flannel_network_cidr': '10.101.0.0/16',
  253. 'flannel_network_subnetlen': '26',
  254. 'flannel_backend': 'vxlan',
  255. 'system_pods_initial_delay': '15',
  256. 'system_pods_timeout': '1',
  257. 'admission_control_list': 'fake_list',
  258. 'prometheus_monitoring': 'False',
  259. 'grafana_admin_passwd': 'fake_pwd',
  260. 'kube_dashboard_enabled': 'True',
  261. 'influx_grafana_dashboard_enabled': 'True',
  262. 'docker_volume_type': 'lvmdriver-1',
  263. 'boot_volume_type': 'lvmdriver-1',
  264. 'etcd_volume_type': 'lvmdriver-1',
  265. 'etcd_volume_size': None,
  266. 'availability_zone': 'az_1',
  267. 'cert_manager_api': 'False',
  268. 'ingress_controller': 'i-controller',
  269. 'ingress_controller_role': 'i-controller-role',
  270. 'kubelet_options': '--kubelet',
  271. 'kubeapi_options': '--kubeapi',
  272. 'kubecontroller_options': '--kubecontroller',
  273. 'kubescheduler_options': '--kubescheduler',
  274. 'kubeproxy_options': '--kubeproxy',
  275. 'service_cluster_ip_range': '10.254.0.0/16',
  276. },
  277. 'http_proxy': 'http_proxy',
  278. 'https_proxy': 'https_proxy',
  279. 'no_proxy': 'no_proxy',
  280. 'cluster_uuid': self.cluster_dict['uuid'],
  281. 'magnum_url': self.mock_osc.magnum_url.return_value,
  282. 'tls_disabled': False,
  283. 'insecure_registry': '10.0.0.1:5000',
  284. 'image_id': ['master_image', 'minion_image']
  285. }
  286. expected = {
  287. 'cloud_provider_enabled': 'false',
  288. 'ssh_key_name': 'keypair_id',
  289. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  290. 'fixed_network': 'fixed_network',
  291. 'fixed_network_name': 'fixed_network',
  292. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  293. 'network_driver': 'network_driver',
  294. 'volume_driver': 'volume_driver',
  295. 'dns_nameserver': 'dns_nameserver',
  296. 'master_image': 'image_id',
  297. 'minion_image': 'image_id',
  298. 'minion_flavor': 'flavor_id',
  299. 'master_flavor': 'master_flavor_id',
  300. 'number_of_minions': 1,
  301. 'number_of_masters': 1,
  302. 'docker_volume_size': 20,
  303. 'docker_volume_type': 'lvmdriver-1',
  304. 'docker_storage_driver': 'devicemapper',
  305. 'discovery_url': 'https://discovery.etcd.io/test',
  306. 'etcd_volume_size': None,
  307. 'flannel_network_cidr': '10.101.0.0/16',
  308. 'flannel_network_subnetlen': '26',
  309. 'flannel_backend': 'vxlan',
  310. 'system_pods_initial_delay': '15',
  311. 'system_pods_timeout': '1',
  312. 'admission_control_list': 'fake_list',
  313. 'prometheus_monitoring': 'False',
  314. 'grafana_admin_passwd': 'fake_pwd',
  315. 'kube_dashboard_enabled': 'True',
  316. 'influx_grafana_dashboard_enabled': 'True',
  317. 'http_proxy': 'http_proxy',
  318. 'https_proxy': 'https_proxy',
  319. 'no_proxy': 'no_proxy',
  320. 'username': 'fake_user',
  321. 'cluster_uuid': self.cluster_dict['uuid'],
  322. 'magnum_url': self.mock_osc.magnum_url.return_value,
  323. 'region_name': self.mock_osc.cinder_region_name.return_value,
  324. 'tls_disabled': False,
  325. 'registry_enabled': False,
  326. 'trustee_domain_id': self.mock_keystone.trustee_domain_id,
  327. 'trustee_username': 'fake_trustee',
  328. 'trustee_password': 'fake_trustee_password',
  329. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  330. 'trust_id': '',
  331. 'auth_url': 'http://192.168.10.10:5000/v3',
  332. 'insecure_registry_url': '10.0.0.1:5000',
  333. 'kube_version': 'fake-version',
  334. 'verify_ca': True,
  335. 'openstack_ca': '',
  336. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  337. "nodes_affinity_policy": "soft-anti-affinity",
  338. 'availability_zone': 'az_1',
  339. 'cert_manager_api': 'False',
  340. 'ingress_controller': 'i-controller',
  341. 'ingress_controller_role': 'i-controller-role',
  342. 'octavia_ingress_controller_tag': None,
  343. 'kubelet_options': '--kubelet',
  344. 'kubeapi_options': '--kubeapi',
  345. 'kubecontroller_options': '--kubecontroller',
  346. 'kubescheduler_options': '--kubescheduler',
  347. 'kubeproxy_options': '--kubeproxy',
  348. 'octavia_enabled': False,
  349. 'kube_service_account_key': 'public_key',
  350. 'kube_service_account_private_key': 'private_key',
  351. 'portal_network_cidr': '10.254.0.0/16',
  352. 'project_id': 'project_id',
  353. 'max_node_count': 2,
  354. 'master_image': 'image_id',
  355. 'minion_image': 'image_id',
  356. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  357. 'boot_volume_size': '60',
  358. 'boot_volume_type': 'lvmdriver-1',
  359. 'etcd_volume_type': 'lvmdriver-1',
  360. 'master_role': 'master',
  361. 'worker_role': 'worker',
  362. 'master_nodegroup_name': 'master_ng',
  363. 'worker_nodegroup_name': 'worker_ng',
  364. }
  365. if missing_attr is not None:
  366. attrs = mapping[missing_attr]
  367. if not isinstance(attrs, list):
  368. attrs = [attrs]
  369. for attr in attrs:
  370. expected.pop(attr, None)
  371. if missing_attr == 'node_count':
  372. expected['max_node_count'] = None
  373. self.assertEqual(expected, definition)
  374. self.assertEqual(
  375. ['../../common/templates/environments/no_private_network.yaml',
  376. '../../common/templates/environments/no_etcd_volume.yaml',
  377. '../../common/templates/environments/with_volume.yaml',
  378. '../../common/templates/environments/no_master_lb.yaml',
  379. '../../common/templates/environments/disable_floating_ip.yaml',
  380. '../../common/templates/environments/disable_lb_floating_ip.yaml',
  381. ],
  382. env_files)
  383. @patch('requests.get')
  384. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  385. @patch('magnum.objects.NodeGroup.list')
  386. @patch('magnum.drivers.common.driver.Driver.get_driver')
  387. @patch('magnum.conductor.handlers.common.cert_manager'
  388. '.sign_node_certificate')
  389. @patch('magnum.common.x509.operations.generate_csr_and_key')
  390. def test_extract_template_definition_with_registry(
  391. self,
  392. mock_generate_csr_and_key,
  393. mock_sign_node_certificate,
  394. mock_driver,
  395. mock_objects_nodegroup_list,
  396. mock_objects_cluster_template_get_by_uuid,
  397. mock_get):
  398. self.cluster_template_dict['registry_enabled'] = True
  399. cluster_template = objects.ClusterTemplate(
  400. self.context, **self.cluster_template_dict)
  401. mock_generate_csr_and_key.return_value = {'csr': 'csr',
  402. 'private_key': 'private_key',
  403. 'public_key': 'public_key'}
  404. mock_sign_node_certificate.return_value = 'signed_cert'
  405. mock_objects_cluster_template_get_by_uuid.return_value = \
  406. cluster_template
  407. expected_result = str('{"action":"get","node":{"key":"test","value":'
  408. '"1","modifiedIndex":10,"createdIndex":10}}')
  409. mock_resp = mock.MagicMock()
  410. mock_resp.text = expected_result
  411. mock_get.return_value = mock_resp
  412. cluster = objects.Cluster(self.context, **self.cluster_dict)
  413. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  414. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  415. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  416. mock_driver.return_value = k8s_dr.Driver()
  417. CONF.set_override('swift_region',
  418. 'RegionOne',
  419. group='docker_registry')
  420. CONF.set_override('cluster_user_trust',
  421. True,
  422. group='trust')
  423. (template_path,
  424. definition,
  425. env_files) = mock_driver()._extract_template_definition(self.context,
  426. cluster)
  427. expected = {
  428. 'auth_url': 'http://192.168.10.10:5000/v3',
  429. 'cloud_provider_enabled': 'true',
  430. 'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
  431. 'discovery_url': 'https://discovery.etcd.io/test',
  432. 'dns_nameserver': 'dns_nameserver',
  433. 'docker_storage_driver': 'devicemapper',
  434. 'docker_volume_size': 20,
  435. 'docker_volume_type': 'lvmdriver-1',
  436. 'etcd_volume_size': None,
  437. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  438. 'fixed_network': 'fixed_network',
  439. 'fixed_network_name': 'fixed_network',
  440. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  441. 'flannel_backend': 'vxlan',
  442. 'flannel_network_cidr': '10.101.0.0/16',
  443. 'flannel_network_subnetlen': '26',
  444. 'system_pods_initial_delay': '15',
  445. 'system_pods_timeout': '1',
  446. 'admission_control_list': 'fake_list',
  447. 'prometheus_monitoring': 'False',
  448. 'grafana_admin_passwd': 'fake_pwd',
  449. 'kube_dashboard_enabled': 'True',
  450. 'influx_grafana_dashboard_enabled': 'True',
  451. 'http_proxy': 'http_proxy',
  452. 'https_proxy': 'https_proxy',
  453. 'magnum_url': 'http://127.0.0.1:9511/v1',
  454. 'master_flavor': 'master_flavor_id',
  455. 'minion_flavor': 'flavor_id',
  456. 'network_driver': 'network_driver',
  457. 'no_proxy': 'no_proxy',
  458. 'number_of_masters': 1,
  459. 'number_of_minions': 1,
  460. 'region_name': 'RegionOne',
  461. 'registry_container': 'docker_registry',
  462. 'registry_enabled': True,
  463. 'master_image': 'image_id',
  464. 'minion_image': 'image_id',
  465. 'ssh_key_name': 'keypair_id',
  466. 'swift_region': 'RegionOne',
  467. 'tls_disabled': False,
  468. 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
  469. 'trustee_domain_id': self.mock_keystone.trustee_domain_id,
  470. 'trustee_password': 'fake_trustee_password',
  471. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  472. 'trustee_username': 'fake_trustee',
  473. 'username': 'fake_user',
  474. 'volume_driver': 'volume_driver',
  475. 'insecure_registry_url': '10.0.0.1:5000',
  476. 'kube_version': 'fake-version',
  477. 'verify_ca': True,
  478. 'openstack_ca': '',
  479. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  480. "nodes_affinity_policy": "soft-anti-affinity",
  481. 'availability_zone': 'az_1',
  482. 'cert_manager_api': 'False',
  483. 'ingress_controller': 'i-controller',
  484. 'ingress_controller_role': 'i-controller-role',
  485. 'octavia_ingress_controller_tag': None,
  486. 'kubelet_options': '--kubelet',
  487. 'kubeapi_options': '--kubeapi',
  488. 'kubecontroller_options': '--kubecontroller',
  489. 'kubescheduler_options': '--kubescheduler',
  490. 'kubeproxy_options': '--kubeproxy',
  491. 'octavia_enabled': False,
  492. 'kube_service_account_key': 'public_key',
  493. 'kube_service_account_private_key': 'private_key',
  494. 'portal_network_cidr': '10.254.0.0/16',
  495. 'project_id': 'project_id',
  496. 'max_node_count': 2,
  497. 'master_image': 'image_id',
  498. 'minion_image': 'image_id',
  499. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  500. 'boot_volume_size': '60',
  501. 'boot_volume_type': 'lvmdriver-1',
  502. 'etcd_volume_type': 'lvmdriver-1',
  503. 'master_role': 'master',
  504. 'worker_role': 'worker',
  505. 'master_nodegroup_name': 'master_ng',
  506. 'worker_nodegroup_name': 'worker_ng',
  507. }
  508. self.assertEqual(expected, definition)
  509. self.assertEqual(
  510. ['../../common/templates/environments/no_private_network.yaml',
  511. '../../common/templates/environments/no_etcd_volume.yaml',
  512. '../../common/templates/environments/with_volume.yaml',
  513. '../../common/templates/environments/no_master_lb.yaml',
  514. '../../common/templates/environments/disable_floating_ip.yaml',
  515. '../../common/templates/environments/disable_lb_floating_ip.yaml'
  516. ],
  517. env_files)
  518. @patch('requests.get')
  519. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  520. @patch('magnum.objects.NodeGroup.list')
  521. @patch('magnum.drivers.common.driver.Driver.get_driver')
  522. @patch('magnum.conductor.handlers.common.cert_manager'
  523. '.sign_node_certificate')
  524. @patch('magnum.common.x509.operations.generate_csr_and_key')
  525. def test_extract_template_definition_only_required(
  526. self,
  527. mock_generate_csr_and_key,
  528. mock_sign_node_certificate,
  529. mock_driver,
  530. mock_objects_nodegroup_list,
  531. mock_objects_cluster_template_get_by_uuid,
  532. mock_get):
  533. not_required = ['image_id', 'flavor_id', 'dns_nameserver',
  534. 'docker_volume_size', 'http_proxy',
  535. 'https_proxy', 'no_proxy', 'network_driver',
  536. 'master_flavor_id', 'docker_storage_driver',
  537. 'volume_driver', 'fixed_subnet']
  538. for key in not_required:
  539. self.cluster_template_dict[key] = None
  540. self.cluster_dict['discovery_url'] = 'https://discovery.etcd.io/test'
  541. cluster_template = objects.ClusterTemplate(
  542. self.context, **self.cluster_template_dict)
  543. mock_generate_csr_and_key.return_value = {'csr': 'csr',
  544. 'private_key': 'private_key',
  545. 'public_key': 'public_key'}
  546. mock_sign_node_certificate.return_value = 'signed_cert'
  547. mock_objects_cluster_template_get_by_uuid.return_value = \
  548. cluster_template
  549. expected_result = str('{"action":"get","node":{"key":"test","value":'
  550. '"1","modifiedIndex":10,"createdIndex":10}}')
  551. mock_resp = mock.MagicMock()
  552. mock_resp.text = expected_result
  553. mock_get.return_value = mock_resp
  554. mock_driver.return_value = k8s_dr.Driver()
  555. cluster = objects.Cluster(self.context, **self.cluster_dict)
  556. del self.worker_ng_dict['image_id']
  557. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  558. del self.master_ng_dict['image_id']
  559. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  560. master_ng.image_id = None
  561. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  562. (template_path,
  563. definition,
  564. env_files) = mock_driver()._extract_template_definition(self.context,
  565. cluster)
  566. expected = {
  567. 'auth_url': 'http://192.168.10.10:5000/v3',
  568. 'cloud_provider_enabled': 'false',
  569. 'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
  570. 'discovery_url': 'https://discovery.etcd.io/test',
  571. 'docker_volume_size': 20,
  572. 'master_flavor': 'master_flavor_id',
  573. 'minion_flavor': 'flavor_id',
  574. 'fixed_network': 'fixed_network',
  575. 'fixed_network_name': 'fixed_network',
  576. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  577. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  578. 'flannel_backend': 'vxlan',
  579. 'flannel_network_cidr': '10.101.0.0/16',
  580. 'flannel_network_subnetlen': '26',
  581. 'system_pods_initial_delay': '15',
  582. 'system_pods_timeout': '1',
  583. 'admission_control_list': 'fake_list',
  584. 'prometheus_monitoring': 'False',
  585. 'grafana_admin_passwd': 'fake_pwd',
  586. 'kube_dashboard_enabled': 'True',
  587. 'influx_grafana_dashboard_enabled': 'True',
  588. 'docker_volume_type': 'lvmdriver-1',
  589. 'etcd_volume_size': None,
  590. 'insecure_registry_url': '10.0.0.1:5000',
  591. 'kube_version': 'fake-version',
  592. 'magnum_url': 'http://127.0.0.1:9511/v1',
  593. 'number_of_masters': 1,
  594. 'number_of_minions': 1,
  595. 'region_name': 'RegionOne',
  596. 'registry_enabled': False,
  597. 'ssh_key_name': 'keypair_id',
  598. 'tls_disabled': False,
  599. 'trust_id': '',
  600. 'trustee_domain_id': 'trustee_domain_id',
  601. 'trustee_password': 'fake_trustee_password',
  602. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  603. 'trustee_username': 'fake_trustee',
  604. 'username': 'fake_user',
  605. 'verify_ca': True,
  606. 'openstack_ca': '',
  607. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  608. "nodes_affinity_policy": "soft-anti-affinity",
  609. 'availability_zone': 'az_1',
  610. 'cert_manager_api': 'False',
  611. 'ingress_controller': 'i-controller',
  612. 'ingress_controller_role': 'i-controller-role',
  613. 'octavia_ingress_controller_tag': None,
  614. 'kubelet_options': '--kubelet',
  615. 'kubeapi_options': '--kubeapi',
  616. 'kubecontroller_options': '--kubecontroller',
  617. 'kubescheduler_options': '--kubescheduler',
  618. 'kubeproxy_options': '--kubeproxy',
  619. 'octavia_enabled': False,
  620. 'kube_service_account_key': 'public_key',
  621. 'kube_service_account_private_key': 'private_key',
  622. 'portal_network_cidr': '10.254.0.0/16',
  623. 'project_id': 'project_id',
  624. 'max_node_count': 2,
  625. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  626. 'boot_volume_size': '60',
  627. 'boot_volume_type': 'lvmdriver-1',
  628. 'etcd_volume_type': 'lvmdriver-1',
  629. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  630. 'master_role': 'master',
  631. 'worker_role': 'worker',
  632. 'master_nodegroup_name': 'master_ng',
  633. 'worker_nodegroup_name': 'worker_ng',
  634. }
  635. self.assertEqual(expected, definition)
  636. self.assertEqual(
  637. ['../../common/templates/environments/no_private_network.yaml',
  638. '../../common/templates/environments/no_etcd_volume.yaml',
  639. '../../common/templates/environments/with_volume.yaml',
  640. '../../common/templates/environments/no_master_lb.yaml',
  641. '../../common/templates/environments/disable_floating_ip.yaml',
  642. '../../common/templates/environments/disable_lb_floating_ip.yaml'
  643. ],
  644. env_files)
  645. @patch('requests.get')
  646. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  647. @patch('magnum.objects.NodeGroup.list')
  648. @patch('magnum.drivers.common.driver.Driver.get_driver')
  649. def test_extract_template_definition_coreos_with_disovery(
  650. self,
  651. mock_driver,
  652. mock_objects_nodegroup_list,
  653. mock_objects_cluster_template_get_by_uuid,
  654. mock_get):
  655. self.cluster_template_dict['cluster_distro'] = 'coreos'
  656. cluster_template = objects.ClusterTemplate(
  657. self.context, **self.cluster_template_dict)
  658. mock_objects_cluster_template_get_by_uuid.return_value = \
  659. cluster_template
  660. expected_result = str('{"action":"get","node":{"key":"test","value":'
  661. '"1","modifiedIndex":10,"createdIndex":10}}')
  662. mock_resp = mock.MagicMock()
  663. mock_resp.text = expected_result
  664. mock_resp.status_code = 200
  665. mock_get.return_value = mock_resp
  666. cluster = objects.Cluster(self.context, **self.cluster_dict)
  667. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  668. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  669. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  670. mock_driver.return_value = k8s_coreos_dr.Driver()
  671. (template_path,
  672. definition,
  673. env_files) = mock_driver()._extract_template_definition(self.context,
  674. cluster)
  675. expected = {
  676. 'ssh_key_name': 'keypair_id',
  677. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  678. 'fixed_network': 'fixed_network',
  679. 'fixed_network_name': 'fixed_network',
  680. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  681. 'availability_zone': 'az_1',
  682. 'nodes_affinity_policy': 'soft-anti-affinity',
  683. 'dns_nameserver': 'dns_nameserver',
  684. 'docker_storage_driver': 'devicemapper',
  685. 'docker_volume_size': 20,
  686. 'docker_volume_type': 'lvmdriver-1',
  687. 'minion_flavor': 'flavor_id',
  688. 'master_flavor': 'master_flavor_id',
  689. 'master_image': 'image_id',
  690. 'minion_image': 'image_id',
  691. 'number_of_minions': 1,
  692. 'number_of_masters': 1,
  693. 'network_driver': 'network_driver',
  694. 'volume_driver': 'volume_driver',
  695. 'discovery_url': 'https://discovery.etcd.io/test',
  696. 'etcd_volume_size': None,
  697. 'http_proxy': 'http_proxy',
  698. 'https_proxy': 'https_proxy',
  699. 'no_proxy': 'no_proxy',
  700. 'flannel_network_cidr': '10.101.0.0/16',
  701. 'flannel_network_subnetlen': '26',
  702. 'flannel_backend': 'vxlan',
  703. 'system_pods_initial_delay': '15',
  704. 'system_pods_timeout': '1',
  705. 'admission_control_list': 'fake_list',
  706. 'prometheus_monitoring': 'False',
  707. 'region_name': 'RegionOne',
  708. 'grafana_admin_passwd': 'fake_pwd',
  709. 'kube_dashboard_enabled': 'True',
  710. 'influx_grafana_dashboard_enabled': 'True',
  711. 'tls_disabled': False,
  712. 'registry_enabled': False,
  713. 'trustee_domain_id': self.mock_keystone.trustee_domain_id,
  714. 'trustee_username': 'fake_trustee',
  715. 'trustee_password': 'fake_trustee_password',
  716. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  717. 'username': 'fake_user',
  718. 'trust_id': '',
  719. 'auth_url': 'http://192.168.10.10:5000/v3',
  720. 'cluster_uuid': self.cluster_dict['uuid'],
  721. 'magnum_url': self.mock_osc.magnum_url.return_value,
  722. 'insecure_registry_url': '10.0.0.1:5000',
  723. 'kube_version': 'fake-version',
  724. 'verify_ca': True,
  725. 'openstack_ca': '',
  726. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  727. 'openstack_ca_coreos': '',
  728. 'cert_manager_api': 'False',
  729. 'ingress_controller': 'i-controller',
  730. 'ingress_controller_role': 'i-controller-role',
  731. 'octavia_ingress_controller_tag': None,
  732. 'kubelet_options': '--kubelet',
  733. 'kubeapi_options': '--kubeapi',
  734. 'kubecontroller_options': '--kubecontroller',
  735. 'kubescheduler_options': '--kubescheduler',
  736. 'kubeproxy_options': '--kubeproxy',
  737. 'octavia_enabled': False,
  738. 'portal_network_cidr': '10.254.0.0/16',
  739. 'master_role': 'master',
  740. 'worker_role': 'worker',
  741. 'master_nodegroup_name': 'master_ng',
  742. 'worker_nodegroup_name': 'worker_ng',
  743. }
  744. self.assertEqual(expected, definition)
  745. self.assertEqual(
  746. ['../../common/templates/environments/no_private_network.yaml',
  747. '../../common/templates/environments/no_etcd_volume.yaml',
  748. '../../common/templates/environments/with_volume.yaml',
  749. '../../common/templates/environments/no_master_lb.yaml',
  750. '../../common/templates/environments/disable_floating_ip.yaml',
  751. '../../common/templates/environments/disable_lb_floating_ip.yaml'
  752. ],
  753. env_files)
  754. @patch('requests.get')
  755. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  756. @patch('magnum.objects.NodeGroup.list')
  757. @patch('magnum.drivers.common.driver.Driver.get_driver')
  758. def test_extract_template_definition_coreos_no_discoveryurl(
  759. self,
  760. mock_driver,
  761. mock_objects_nodegroup_list,
  762. mock_objects_cluster_template_get_by_uuid,
  763. reqget):
  764. self.cluster_template_dict['cluster_distro'] = 'coreos'
  765. self.cluster_dict['discovery_url'] = None
  766. mock_req = mock.MagicMock(text='http://tokentest/h1/h2/h3',
  767. status_code=200)
  768. reqget.return_value = mock_req
  769. cluster_template = objects.ClusterTemplate(
  770. self.context, **self.cluster_template_dict)
  771. mock_objects_cluster_template_get_by_uuid.return_value = \
  772. cluster_template
  773. cluster = objects.Cluster(self.context, **self.cluster_dict)
  774. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  775. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  776. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  777. mock_driver.return_value = k8s_coreos_dr.Driver()
  778. (template_path,
  779. definition,
  780. env_files) = mock_driver()._extract_template_definition(self.context,
  781. cluster)
  782. expected = {
  783. 'ssh_key_name': 'keypair_id',
  784. 'availability_zone': 'az_1',
  785. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  786. 'fixed_network': 'fixed_network',
  787. 'fixed_network_name': 'fixed_network',
  788. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  789. 'dns_nameserver': 'dns_nameserver',
  790. 'docker_storage_driver': u'devicemapper',
  791. 'docker_volume_size': 20,
  792. 'docker_volume_type': u'lvmdriver-1',
  793. 'master_image': 'image_id',
  794. 'minion_image': 'image_id',
  795. 'minion_flavor': 'flavor_id',
  796. 'master_flavor': 'master_flavor_id',
  797. 'number_of_minions': 1,
  798. 'number_of_masters': 1,
  799. 'network_driver': 'network_driver',
  800. 'volume_driver': 'volume_driver',
  801. 'discovery_url': 'http://tokentest/h1/h2/h3',
  802. 'etcd_volume_size': None,
  803. 'http_proxy': 'http_proxy',
  804. 'https_proxy': 'https_proxy',
  805. 'no_proxy': 'no_proxy',
  806. 'nodes_affinity_policy': 'soft-anti-affinity',
  807. 'flannel_network_cidr': '10.101.0.0/16',
  808. 'flannel_network_subnetlen': '26',
  809. 'flannel_backend': 'vxlan',
  810. 'system_pods_initial_delay': '15',
  811. 'system_pods_timeout': '1',
  812. 'admission_control_list': 'fake_list',
  813. 'prometheus_monitoring': 'False',
  814. 'region_name': self.mock_osc.cinder_region_name.return_value,
  815. 'grafana_admin_passwd': 'fake_pwd',
  816. 'kube_dashboard_enabled': 'True',
  817. 'influx_grafana_dashboard_enabled': 'True',
  818. 'tls_disabled': False,
  819. 'registry_enabled': False,
  820. 'trustee_domain_id': self.mock_keystone.trustee_domain_id,
  821. 'trustee_username': 'fake_trustee',
  822. 'username': 'fake_user',
  823. 'trustee_password': 'fake_trustee_password',
  824. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  825. 'trust_id': '',
  826. 'auth_url': 'http://192.168.10.10:5000/v3',
  827. 'cluster_uuid': self.cluster_dict['uuid'],
  828. 'magnum_url': self.mock_osc.magnum_url.return_value,
  829. 'insecure_registry_url': '10.0.0.1:5000',
  830. 'kube_version': 'fake-version',
  831. 'verify_ca': True,
  832. 'openstack_ca': '',
  833. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  834. 'openstack_ca_coreos': '',
  835. 'cert_manager_api': 'False',
  836. 'ingress_controller': 'i-controller',
  837. 'ingress_controller_role': 'i-controller-role',
  838. 'octavia_ingress_controller_tag': None,
  839. 'kubelet_options': '--kubelet',
  840. 'kubeapi_options': '--kubeapi',
  841. 'kubecontroller_options': '--kubecontroller',
  842. 'kubescheduler_options': '--kubescheduler',
  843. 'kubeproxy_options': '--kubeproxy',
  844. 'octavia_enabled': False,
  845. 'portal_network_cidr': '10.254.0.0/16',
  846. 'master_role': 'master',
  847. 'worker_role': 'worker',
  848. 'master_nodegroup_name': 'master_ng',
  849. 'worker_nodegroup_name': 'worker_ng',
  850. }
  851. self.assertEqual(expected, definition)
  852. self.assertEqual(
  853. ['../../common/templates/environments/no_private_network.yaml',
  854. '../../common/templates/environments/no_etcd_volume.yaml',
  855. '../../common/templates/environments/with_volume.yaml',
  856. '../../common/templates/environments/no_master_lb.yaml',
  857. '../../common/templates/environments/disable_floating_ip.yaml',
  858. '../../common/templates/environments/disable_lb_floating_ip.yaml'
  859. ],
  860. env_files)
  861. @patch('requests.get')
  862. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  863. @patch('magnum.objects.NodeGroup.list')
  864. @patch('magnum.drivers.common.driver.Driver.get_driver')
  865. @patch('magnum.conductor.handlers.common.cert_manager'
  866. '.sign_node_certificate')
  867. @patch('magnum.common.x509.operations.generate_csr_and_key')
  868. def test_extract_template_definition_without_dns(
  869. self,
  870. mock_generate_csr_and_key,
  871. mock_sign_node_certificate,
  872. mock_driver,
  873. mock_objects_nodegroup_list,
  874. mock_objects_cluster_template_get_by_uuid,
  875. mock_get):
  876. mock_driver.return_value = k8s_dr.Driver()
  877. self._test_extract_template_definition(
  878. mock_generate_csr_and_key,
  879. mock_sign_node_certificate,
  880. mock_driver,
  881. mock_objects_cluster_template_get_by_uuid,
  882. mock_get,
  883. mock_objects_nodegroup_list,
  884. missing_attr='dns_nameserver')
  885. @patch('requests.get')
  886. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  887. @patch('magnum.objects.NodeGroup.list')
  888. @patch('magnum.drivers.common.driver.Driver.get_driver')
  889. @patch('magnum.conductor.handlers.common.cert_manager'
  890. '.sign_node_certificate')
  891. @patch('magnum.common.x509.operations.generate_csr_and_key')
  892. def test_extract_template_definition_without_server_image(
  893. self,
  894. mock_generate_csr_and_key,
  895. mock_sign_node_certificate,
  896. mock_driver,
  897. mock_objects_nodegroup_list,
  898. mock_objects_cluster_template_get_by_uuid,
  899. mock_get):
  900. mock_driver.return_value = k8s_dr.Driver()
  901. self._test_extract_template_definition(
  902. mock_generate_csr_and_key,
  903. mock_sign_node_certificate,
  904. mock_driver,
  905. mock_objects_cluster_template_get_by_uuid,
  906. mock_get,
  907. mock_objects_nodegroup_list,
  908. missing_attr='image_id')
  909. @patch('requests.get')
  910. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  911. @patch('magnum.objects.NodeGroup.list')
  912. @patch('magnum.drivers.common.driver.Driver.get_driver')
  913. @patch('magnum.conductor.handlers.common.cert_manager'
  914. '.sign_node_certificate')
  915. @patch('magnum.common.x509.operations.generate_csr_and_key')
  916. def test_extract_template_definition_without_docker_storage_driver(
  917. self,
  918. mock_generate_csr_and_key,
  919. mock_sign_node_certificate,
  920. mock_driver,
  921. mock_objects_nodegroup_list,
  922. mock_objects_cluster_template_get_by_uuid,
  923. mock_get):
  924. mock_driver.return_value = k8s_dr.Driver()
  925. self._test_extract_template_definition(
  926. mock_generate_csr_and_key,
  927. mock_sign_node_certificate,
  928. mock_driver,
  929. mock_objects_cluster_template_get_by_uuid,
  930. mock_get,
  931. mock_objects_nodegroup_list,
  932. missing_attr='docker_storage_driver')
  933. @patch('requests.get')
  934. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  935. @patch('magnum.objects.NodeGroup.list')
  936. @patch('magnum.drivers.common.driver.Driver.get_driver')
  937. @patch('magnum.conductor.handlers.common.cert_manager'
  938. '.sign_node_certificate')
  939. @patch('magnum.common.x509.operations.generate_csr_and_key')
  940. def test_extract_template_definition_without_apiserver_port(
  941. self,
  942. mock_generate_csr_and_key,
  943. mock_sign_node_certificate,
  944. mock_driver,
  945. mock_objects_nodegroup_list,
  946. mock_objects_cluster_template_get_by_uuid,
  947. mock_get):
  948. mock_driver.return_value = k8s_dr.Driver()
  949. self._test_extract_template_definition(
  950. mock_generate_csr_and_key,
  951. mock_sign_node_certificate,
  952. mock_driver,
  953. mock_objects_cluster_template_get_by_uuid,
  954. mock_get,
  955. mock_objects_nodegroup_list,
  956. missing_attr='apiserver_port')
  957. @patch('requests.get')
  958. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  959. @patch('magnum.objects.NodeGroup.list')
  960. @patch('magnum.drivers.common.driver.Driver.get_driver')
  961. @patch('magnum.conductor.handlers.common.cert_manager'
  962. '.sign_node_certificate')
  963. @patch('magnum.common.x509.operations.generate_csr_and_key')
  964. def test_extract_template_definition_without_discovery_url(
  965. self,
  966. mock_generate_csr_and_key,
  967. mock_sign_node_certificate,
  968. mock_driver,
  969. mock_objects_nodegroup_list,
  970. mock_objects_cluster_template_get_by_uuid,
  971. reqget):
  972. cluster_template = objects.ClusterTemplate(
  973. self.context, **self.cluster_template_dict)
  974. mock_generate_csr_and_key.return_value = {'csr': 'csr',
  975. 'private_key': 'private_key',
  976. 'public_key': 'public_key'}
  977. mock_sign_node_certificate.return_value = 'signed_cert'
  978. mock_objects_cluster_template_get_by_uuid.return_value = \
  979. cluster_template
  980. cluster_dict = self.cluster_dict
  981. cluster_dict['discovery_url'] = None
  982. cluster = objects.Cluster(self.context, **cluster_dict)
  983. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  984. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  985. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  986. mock_driver.return_value = k8s_dr.Driver()
  987. CONF.set_override('etcd_discovery_service_endpoint_format',
  988. 'http://etcd/test?size=%(size)d',
  989. group='cluster')
  990. mock_req = mock.MagicMock(text='https://address/token',
  991. status_code=200)
  992. reqget.return_value = mock_req
  993. (template_path,
  994. definition,
  995. env_files) = mock_driver()._extract_template_definition(self.context,
  996. cluster)
  997. expected = {
  998. 'cloud_provider_enabled': 'false',
  999. 'ssh_key_name': 'keypair_id',
  1000. 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
  1001. 'fixed_network': 'fixed_network',
  1002. 'fixed_network_name': 'fixed_network',
  1003. 'fixed_subnet': 'c2a6c8b0-a3c2-42a3-b3f4-01400a30896f',
  1004. 'dns_nameserver': 'dns_nameserver',
  1005. 'master_image': 'image_id',
  1006. 'minion_image': 'image_id',
  1007. 'master_flavor': 'master_flavor_id',
  1008. 'minion_flavor': 'flavor_id',
  1009. 'number_of_minions': 1,
  1010. 'number_of_masters': 1,
  1011. 'network_driver': 'network_driver',
  1012. 'volume_driver': 'volume_driver',
  1013. 'docker_volume_size': 20,
  1014. 'docker_volume_type': 'lvmdriver-1',
  1015. 'docker_storage_driver': 'devicemapper',
  1016. 'discovery_url': 'https://address/token',
  1017. 'etcd_volume_size': None,
  1018. 'http_proxy': 'http_proxy',
  1019. 'https_proxy': 'https_proxy',
  1020. 'no_proxy': 'no_proxy',
  1021. 'flannel_network_cidr': '10.101.0.0/16',
  1022. 'flannel_network_subnetlen': '26',
  1023. 'flannel_backend': 'vxlan',
  1024. 'system_pods_initial_delay': '15',
  1025. 'system_pods_timeout': '1',
  1026. 'admission_control_list': 'fake_list',
  1027. 'prometheus_monitoring': 'False',
  1028. 'grafana_admin_passwd': 'fake_pwd',
  1029. 'kube_dashboard_enabled': 'True',
  1030. 'influx_grafana_dashboard_enabled': 'True',
  1031. 'username': 'fake_user',
  1032. 'cluster_uuid': self.cluster_dict['uuid'],
  1033. 'magnum_url': self.mock_osc.magnum_url.return_value,
  1034. 'region_name': self.mock_osc.cinder_region_name.return_value,
  1035. 'tls_disabled': False,
  1036. 'registry_enabled': False,
  1037. 'trustee_domain_id': self.mock_keystone.trustee_domain_id,
  1038. 'trustee_username': 'fake_trustee',
  1039. 'trustee_password': 'fake_trustee_password',
  1040. 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
  1041. 'trust_id': '',
  1042. 'auth_url': 'http://192.168.10.10:5000/v3',
  1043. 'insecure_registry_url': '10.0.0.1:5000',
  1044. 'kube_version': 'fake-version',
  1045. 'verify_ca': True,
  1046. 'openstack_ca': '',
  1047. 'ssh_public_key': 'ssh-rsa AAAAB3Nz',
  1048. "nodes_affinity_policy": "soft-anti-affinity",
  1049. 'availability_zone': 'az_1',
  1050. 'cert_manager_api': 'False',
  1051. 'ingress_controller': 'i-controller',
  1052. 'ingress_controller_role': 'i-controller-role',
  1053. 'octavia_ingress_controller_tag': None,
  1054. 'kubelet_options': '--kubelet',
  1055. 'kubeapi_options': '--kubeapi',
  1056. 'kubecontroller_options': '--kubecontroller',
  1057. 'kubescheduler_options': '--kubescheduler',
  1058. 'kubeproxy_options': '--kubeproxy',
  1059. 'octavia_enabled': False,
  1060. 'kube_service_account_key': 'public_key',
  1061. 'kube_service_account_private_key': 'private_key',
  1062. 'portal_network_cidr': '10.254.0.0/16',
  1063. 'project_id': 'project_id',
  1064. 'max_node_count': 2,
  1065. 'master_image': 'image_id',
  1066. 'minion_image': 'image_id',
  1067. 'keystone_auth_default_policy': self.keystone_auth_default_policy,
  1068. 'boot_volume_size': '60',
  1069. 'boot_volume_type': 'lvmdriver-1',
  1070. 'etcd_volume_type': 'lvmdriver-1',
  1071. 'master_role': 'master',
  1072. 'worker_role': 'worker',
  1073. 'master_nodegroup_name': 'master_ng',
  1074. 'worker_nodegroup_name': 'worker_ng',
  1075. }
  1076. self.assertEqual(expected, definition)
  1077. self.assertEqual(
  1078. ['../../common/templates/environments/no_private_network.yaml',
  1079. '../../common/templates/environments/no_etcd_volume.yaml',
  1080. '../../common/templates/environments/with_volume.yaml',
  1081. '../../common/templates/environments/no_master_lb.yaml',
  1082. '../../common/templates/environments/disable_floating_ip.yaml',
  1083. '../../common/templates/environments/disable_lb_floating_ip.yaml',
  1084. ],
  1085. env_files)
  1086. reqget.assert_called_once_with('http://etcd/test?size=1')
  1087. @patch('magnum.common.short_id.generate_id')
  1088. @patch('heatclient.common.template_utils.get_template_contents')
  1089. @patch('magnum.drivers.k8s_fedora_atomic_v1.driver.Driver.'
  1090. '_extract_template_definition')
  1091. @patch('magnum.common.clients.OpenStackClients')
  1092. def test_create_stack(self,
  1093. mock_osc,
  1094. mock_extract_template_definition,
  1095. mock_get_template_contents,
  1096. mock_generate_id):
  1097. mock_generate_id.return_value = 'xx-xx-xx-xx'
  1098. expected_stack_name = 'expected-stack-name-xx-xx-xx-xx'
  1099. expected_template_contents = 'template_contents'
  1100. dummy_cluster_name = 'expected_stack_name'
  1101. expected_timeout = 15
  1102. mock_tpl_files = {}
  1103. mock_get_template_contents.return_value = [
  1104. mock_tpl_files, expected_template_contents]
  1105. mock_extract_template_definition.return_value = ('template/path',
  1106. {}, [])
  1107. mock_heat_client = mock.MagicMock()
  1108. mock_osc.return_value.heat.return_value = mock_heat_client
  1109. mock_cluster = mock.MagicMock()
  1110. mock_cluster.name = dummy_cluster_name
  1111. k8s_dr.Driver().create_cluster(self.context, mock_cluster,
  1112. expected_timeout)
  1113. expected_args = {
  1114. 'stack_name': expected_stack_name,
  1115. 'parameters': {'is_cluster_stack': True},
  1116. 'template': expected_template_contents,
  1117. 'files': {},
  1118. 'environment_files': [],
  1119. 'timeout_mins': expected_timeout
  1120. }
  1121. mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
  1122. @patch('magnum.common.short_id.generate_id')
  1123. @patch('heatclient.common.template_utils.get_template_contents')
  1124. @patch('magnum.drivers.k8s_fedora_atomic_v1.driver.Driver.'
  1125. '_extract_template_definition')
  1126. @patch('magnum.common.clients.OpenStackClients')
  1127. def test_create_stack_no_timeout_specified(
  1128. self,
  1129. mock_osc,
  1130. mock_extract_template_definition,
  1131. mock_get_template_contents,
  1132. mock_generate_id):
  1133. mock_generate_id.return_value = 'xx-xx-xx-xx'
  1134. expected_stack_name = 'expected-stack-name-xx-xx-xx-xx'
  1135. expected_template_contents = 'template_contents'
  1136. dummy_cluster_name = 'expected_stack_name'
  1137. expected_timeout = CONF.cluster_heat.create_timeout
  1138. mock_tpl_files = {}
  1139. mock_get_template_contents.return_value = [
  1140. mock_tpl_files, expected_template_contents]
  1141. mock_extract_template_definition.return_value = ('template/path',
  1142. {}, [])
  1143. mock_heat_client = mock.MagicMock()
  1144. mock_osc.return_value.heat.return_value = mock_heat_client
  1145. mock_cluster = mock.MagicMock()
  1146. mock_cluster.name = dummy_cluster_name
  1147. k8s_dr.Driver().create_cluster(self.context, mock_cluster, None)
  1148. expected_args = {
  1149. 'stack_name': expected_stack_name,
  1150. 'parameters': {'is_cluster_stack': True},
  1151. 'template': expected_template_contents,
  1152. 'files': {},
  1153. 'environment_files': [],
  1154. 'timeout_mins': expected_timeout
  1155. }
  1156. mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
  1157. @patch('magnum.common.short_id.generate_id')
  1158. @patch('heatclient.common.template_utils.get_template_contents')
  1159. @patch('magnum.drivers.k8s_fedora_atomic_v1.driver.Driver.'
  1160. '_extract_template_definition')
  1161. @patch('magnum.common.clients.OpenStackClients')
  1162. def test_create_stack_timeout_is_zero(
  1163. self,
  1164. mock_osc,
  1165. mock_extract_template_definition,
  1166. mock_get_template_contents,
  1167. mock_generate_id):
  1168. mock_generate_id.return_value = 'xx-xx-xx-xx'
  1169. expected_stack_name = 'expected-stack-name-xx-xx-xx-xx'
  1170. expected_template_contents = 'template_contents'
  1171. dummy_cluster_name = 'expected_stack_name'
  1172. cluster_timeout = 0
  1173. expected_timeout = CONF.cluster_heat.create_timeout
  1174. mock_tpl_files = {}
  1175. mock_get_template_contents.return_value = [
  1176. mock_tpl_files, expected_template_contents]
  1177. mock_extract_template_definition.return_value = ('template/path',
  1178. {}, [])
  1179. mock_heat_client = mock.MagicMock()
  1180. mock_osc.return_value.heat.return_value = mock_heat_client
  1181. mock_cluster = mock.MagicMock()
  1182. mock_cluster.name = dummy_cluster_name
  1183. k8s_dr.Driver().create_cluster(self.context, mock_cluster,
  1184. cluster_timeout)
  1185. expected_args = {
  1186. 'stack_name': expected_stack_name,
  1187. 'parameters': {'is_cluster_stack': True},
  1188. 'template': expected_template_contents,
  1189. 'files': {},
  1190. 'environment_files': [],
  1191. 'timeout_mins': expected_timeout
  1192. }
  1193. mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
  1194. @patch('heatclient.common.template_utils.get_template_contents')
  1195. @patch('magnum.drivers.k8s_fedora_atomic_v1.driver.Driver.'
  1196. '_extract_template_definition')
  1197. @patch('magnum.common.clients.OpenStackClients')
  1198. @patch('magnum.objects.ClusterTemplate.get_by_uuid')
  1199. @patch('magnum.objects.NodeGroup.list')
  1200. def test_update_stack(self,
  1201. mock_objects_nodegroup_list,
  1202. mock_objects_cluster_template_get_by_uuid,
  1203. mock_osc,
  1204. mock_extract_template_definition,
  1205. mock_get_template_contents):
  1206. mock_stack_id = 'xx-xx-xx-xx'
  1207. mock_stack = mock.MagicMock(parameters={'number_of_minions': 1})
  1208. mock_stacks = mock.MagicMock()
  1209. mock_stacks.get.return_value = mock_stack
  1210. mock_heat_client = mock.MagicMock(stacks=mock_stacks)
  1211. mock_osc.return_value.heat.return_value = mock_heat_client
  1212. mock_template = objects.ClusterTemplate(
  1213. self.context, **self.cluster_template_dict)
  1214. mock_objects_cluster_template_get_by_uuid.return_value = mock_template
  1215. mock_cluster = objects.Cluster(self.context, **self.cluster_dict)
  1216. mock_cluster.cluster_template = mock_template
  1217. self.worker_ng_dict['node_count'] = 2
  1218. worker_ng = objects.NodeGroup(self.context, **self.worker_ng_dict)
  1219. master_ng = objects.NodeGroup(self.context, **self.master_ng_dict)
  1220. mock_objects_nodegroup_list.return_value = [master_ng, worker_ng]
  1221. k8s_dr.Driver().update_cluster({}, mock_cluster)
  1222. expected_args = {
  1223. 'parameters': {'number_of_minions': '2'},
  1224. 'existing': True,
  1225. 'disable_rollback': True
  1226. }
  1227. mock_heat_client.stacks.update.assert_called_once_with(mock_stack_id,
  1228. **expected_args)