octavia 13.0.0__py3-none-any.whl → 13.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. octavia/amphorae/backends/agent/api_server/keepalivedlvs.py +9 -0
  2. octavia/amphorae/backends/agent/api_server/osutils.py +1 -2
  3. octavia/amphorae/backends/agent/api_server/util.py +35 -2
  4. octavia/amphorae/backends/utils/interface.py +4 -5
  5. octavia/amphorae/drivers/driver_base.py +16 -0
  6. octavia/amphorae/drivers/haproxy/rest_api_driver.py +13 -8
  7. octavia/amphorae/drivers/keepalived/jinja/jinja_cfg.py +0 -1
  8. octavia/amphorae/drivers/keepalived/jinja/templates/keepalived_base.template +0 -1
  9. octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py +2 -1
  10. octavia/amphorae/drivers/noop_driver/driver.py +3 -0
  11. octavia/api/common/pagination.py +1 -1
  12. octavia/api/v2/controllers/health_monitor.py +3 -2
  13. octavia/api/v2/controllers/l7policy.py +0 -1
  14. octavia/api/v2/controllers/l7rule.py +0 -1
  15. octavia/api/v2/controllers/listener.py +0 -1
  16. octavia/api/v2/controllers/load_balancer.py +13 -7
  17. octavia/api/v2/controllers/member.py +18 -5
  18. octavia/api/v2/controllers/pool.py +6 -7
  19. octavia/api/v2/types/pool.py +1 -1
  20. octavia/certificates/common/pkcs12.py +9 -9
  21. octavia/certificates/manager/barbican.py +24 -16
  22. octavia/certificates/manager/castellan_mgr.py +12 -7
  23. octavia/certificates/manager/noop.py +106 -0
  24. octavia/common/clients.py +22 -4
  25. octavia/common/config.py +21 -5
  26. octavia/common/constants.py +4 -0
  27. octavia/common/exceptions.py +6 -0
  28. octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +7 -5
  29. octavia/common/keystone.py +7 -7
  30. octavia/common/tls_utils/cert_parser.py +23 -9
  31. octavia/controller/worker/task_utils.py +28 -6
  32. octavia/controller/worker/v2/controller_worker.py +2 -2
  33. octavia/controller/worker/v2/flows/amphora_flows.py +41 -10
  34. octavia/controller/worker/v2/flows/flow_utils.py +6 -4
  35. octavia/controller/worker/v2/flows/load_balancer_flows.py +17 -3
  36. octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +114 -23
  37. octavia/controller/worker/v2/tasks/database_tasks.py +36 -47
  38. octavia/controller/worker/v2/tasks/lifecycle_tasks.py +96 -40
  39. octavia/controller/worker/v2/tasks/network_tasks.py +12 -13
  40. octavia/db/base_models.py +16 -4
  41. octavia/db/repositories.py +34 -33
  42. octavia/network/drivers/neutron/allowed_address_pairs.py +10 -8
  43. octavia/network/drivers/noop_driver/driver.py +1 -2
  44. octavia/tests/common/sample_certs.py +115 -0
  45. octavia/tests/functional/api/v2/base.py +1 -1
  46. octavia/tests/functional/api/v2/test_health_monitor.py +18 -0
  47. octavia/tests/functional/api/v2/test_listener.py +45 -0
  48. octavia/tests/functional/api/v2/test_member.py +32 -0
  49. octavia/tests/functional/db/base.py +9 -0
  50. octavia/tests/functional/db/test_repositories.py +45 -98
  51. octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +89 -1
  52. octavia/tests/unit/amphorae/backends/utils/test_interface.py +3 -1
  53. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py +3 -3
  54. octavia/tests/unit/amphorae/drivers/keepalived/jinja/test_jinja_cfg.py +0 -4
  55. octavia/tests/unit/amphorae/drivers/keepalived/test_vrrp_rest_driver.py +17 -0
  56. octavia/tests/unit/api/common/test_pagination.py +78 -1
  57. octavia/tests/unit/api/v2/types/test_pool.py +71 -0
  58. octavia/tests/unit/certificates/manager/test_barbican.py +3 -3
  59. octavia/tests/unit/certificates/manager/test_noop.py +53 -0
  60. octavia/tests/unit/cmd/test_prometheus_proxy.py +8 -1
  61. octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +16 -17
  62. octavia/tests/unit/common/test_config.py +35 -0
  63. octavia/tests/unit/common/test_keystone.py +32 -0
  64. octavia/tests/unit/controller/worker/test_task_utils.py +58 -2
  65. octavia/tests/unit/controller/worker/v2/flows/test_amphora_flows.py +28 -5
  66. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +10 -5
  67. octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +234 -17
  68. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +28 -6
  69. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +19 -19
  70. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +57 -2
  71. octavia/tests/unit/controller/worker/v2/test_controller_worker.py +56 -1
  72. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +24 -1
  73. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/AUTHORS +8 -0
  74. octavia-13.0.1.dist-info/METADATA +155 -0
  75. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/RECORD +90 -88
  76. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/WHEEL +1 -1
  77. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/entry_points.txt +1 -1
  78. octavia-13.0.1.dist-info/pbr.json +1 -0
  79. octavia-13.0.0.dist-info/METADATA +0 -158
  80. octavia-13.0.0.dist-info/pbr.json +0 -1
  81. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/LICENSE +0 -0
  82. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/README.rst +0 -0
  83. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  84. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  85. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  86. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  87. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  88. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/tox.ini +0 -0
  89. {octavia-13.0.0.data → octavia-13.0.1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  90. {octavia-13.0.0.data → octavia-13.0.1.data}/scripts/octavia-wsgi +0 -0
  91. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/LICENSE +0 -0
  92. {octavia-13.0.0.dist-info → octavia-13.0.1.dist-info}/top_level.txt +0 -0
@@ -370,13 +370,57 @@ class TestUtil(base.TestCase):
370
370
  self.assertEqual([], util.get_haproxy_vip_addresses(LB_ID1))
371
371
  mock_cfg_path.assert_called_once_with(LB_ID1)
372
372
 
373
+ @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
374
+ 'keepalived_lvs_cfg_path')
375
+ def test_get_lvs_vip_addresses(self, mock_cfg_path):
376
+ FAKE_PATH = 'fake_path'
377
+ mock_cfg_path.return_value = FAKE_PATH
378
+ self.useFixture(
379
+ test_utils.OpenFixture(FAKE_PATH, 'no match')).mock_open()
380
+
381
+ # Test with no matching lines in the config file
382
+ self.assertEqual([], util.get_lvs_vip_addresses(LB_ID1))
383
+ mock_cfg_path.assert_called_once_with(LB_ID1)
384
+
385
+ # Test with 2 matching lines
386
+ mock_cfg_path.reset_mock()
387
+ test_data = ('virtual_server_group ipv4-group {\n'
388
+ ' 203.0.113.43 1\n'
389
+ ' 203.0.113.44 1\n'
390
+ '}\n')
391
+ self.useFixture(
392
+ test_utils.OpenFixture(FAKE_PATH, test_data)).mock_open()
393
+ expected_result = ['203.0.113.43', '203.0.113.44']
394
+ self.assertEqual(expected_result,
395
+ util.get_lvs_vip_addresses(LB_ID1))
396
+ mock_cfg_path.assert_called_once_with(LB_ID1)
397
+
398
+ # Test with 2 groups
399
+ mock_cfg_path.reset_mock()
400
+ test_data = ('virtual_server_group ipv4-group {\n'
401
+ ' 203.0.113.43 1\n'
402
+ '}\n'
403
+ 'virtual_server_group ipv6-group {\n'
404
+ ' 2d01:27::1 2\n'
405
+ ' 2d01:27::2 2\n'
406
+ '}\n')
407
+ self.useFixture(
408
+ test_utils.OpenFixture(FAKE_PATH, test_data)).mock_open()
409
+ expected_result = ['203.0.113.43', '2d01:27::1', '2d01:27::2']
410
+ self.assertEqual(expected_result,
411
+ util.get_lvs_vip_addresses(LB_ID1))
412
+ mock_cfg_path.assert_called_once_with(LB_ID1)
413
+
373
414
  @mock.patch('octavia.amphorae.backends.utils.ip_advertisement.'
374
415
  'send_ip_advertisement')
375
416
  @mock.patch('octavia.amphorae.backends.utils.network_utils.'
376
417
  'get_interface_name')
377
418
  @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
378
419
  'get_haproxy_vip_addresses')
379
- def test_send_vip_advertisements(self, mock_get_vip_addrs,
420
+ @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
421
+ 'get_lvs_vip_addresses')
422
+ def test_send_vip_advertisements(self, mock_get_lvs_vip_addrs,
423
+ mock_get_vip_addrs,
380
424
  mock_get_int_name, mock_send_advert):
381
425
  mock_get_vip_addrs.side_effect = [[], ['203.0.113.46'],
382
426
  Exception('boom')]
@@ -385,6 +429,7 @@ class TestUtil(base.TestCase):
385
429
  # Test no VIPs
386
430
  util.send_vip_advertisements(LB_ID1)
387
431
  mock_get_vip_addrs.assert_called_once_with(LB_ID1)
432
+ mock_get_lvs_vip_addrs.assert_not_called()
388
433
  mock_get_int_name.assert_not_called()
389
434
  mock_send_advert.assert_not_called()
390
435
 
@@ -394,6 +439,7 @@ class TestUtil(base.TestCase):
394
439
  mock_send_advert.reset_mock()
395
440
  util.send_vip_advertisements(LB_ID1)
396
441
  mock_get_vip_addrs.assert_called_once_with(LB_ID1)
442
+ mock_get_lvs_vip_addrs.assert_not_called()
397
443
  mock_get_int_name.assert_called_once_with(
398
444
  '203.0.113.46', net_ns=consts.AMPHORA_NAMESPACE)
399
445
  mock_send_advert.assert_called_once_with(
@@ -407,6 +453,48 @@ class TestUtil(base.TestCase):
407
453
  mock_get_int_name.assert_not_called()
408
454
  mock_send_advert.assert_not_called()
409
455
 
456
+ @mock.patch('octavia.amphorae.backends.utils.ip_advertisement.'
457
+ 'send_ip_advertisement')
458
+ @mock.patch('octavia.amphorae.backends.utils.network_utils.'
459
+ 'get_interface_name')
460
+ @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
461
+ 'get_haproxy_vip_addresses')
462
+ @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
463
+ 'get_lvs_vip_addresses')
464
+ def test_send_vip_advertisements_udp(self, mock_get_lvs_vip_addrs,
465
+ mock_get_vip_addrs,
466
+ mock_get_int_name, mock_send_advert):
467
+ mock_get_lvs_vip_addrs.side_effect = [[], ['203.0.113.46'],
468
+ Exception('boom')]
469
+ mock_get_int_name.return_value = 'fake0'
470
+
471
+ # Test no VIPs
472
+ util.send_vip_advertisements(listener_id=LISTENER_ID1)
473
+ mock_get_lvs_vip_addrs.assert_called_once_with(LISTENER_ID1)
474
+ mock_get_vip_addrs.assert_not_called()
475
+ mock_get_int_name.assert_not_called()
476
+ mock_send_advert.assert_not_called()
477
+
478
+ # Test with a VIP
479
+ mock_get_lvs_vip_addrs.reset_mock()
480
+ mock_get_int_name.reset_mock()
481
+ mock_send_advert.reset_mock()
482
+ util.send_vip_advertisements(listener_id=LISTENER_ID1)
483
+ mock_get_lvs_vip_addrs.assert_called_once_with(LISTENER_ID1)
484
+ mock_get_vip_addrs.assert_not_called()
485
+ mock_get_int_name.assert_called_once_with(
486
+ '203.0.113.46', net_ns=consts.AMPHORA_NAMESPACE)
487
+ mock_send_advert.assert_called_once_with(
488
+ 'fake0', '203.0.113.46', net_ns=consts.AMPHORA_NAMESPACE)
489
+
490
+ # Test with an exception (should not raise)
491
+ mock_get_lvs_vip_addrs.reset_mock()
492
+ mock_get_int_name.reset_mock()
493
+ mock_send_advert.reset_mock()
494
+ util.send_vip_advertisements(listener_id=LISTENER_ID1)
495
+ mock_get_int_name.assert_not_called()
496
+ mock_send_advert.assert_not_called()
497
+
410
498
  @mock.patch('octavia.amphorae.backends.utils.ip_advertisement.'
411
499
  'send_ip_advertisement')
412
500
  @mock.patch('octavia.amphorae.backends.utils.network_utils.'
@@ -714,7 +714,9 @@ class TestInterface(base.TestCase):
714
714
  table=254,
715
715
  family=socket.AF_INET)])
716
716
 
717
- mock_check_output.assert_not_called()
717
+ mock_check_output.assert_has_calls([
718
+ mock.call(["post-up", "eth1"])
719
+ ])
718
720
 
719
721
  @mock.patch('pyroute2.IPRoute.rule')
720
722
  @mock.patch('pyroute2.IPRoute.route')
@@ -76,9 +76,9 @@ class TestHAProxyAmphoraDriver(base.TestCase):
76
76
  mock_api_version.reset_mock()
77
77
  client_mock.reset_mock()
78
78
 
79
- result = self.driver.get_interface_from_ip(amphora_mock, IP_ADDRESS)
80
-
81
- self.assertIsNone(result)
79
+ self.assertRaises(
80
+ exc.NotFound,
81
+ self.driver.get_interface_from_ip, amphora_mock, IP_ADDRESS)
82
82
  mock_api_version.assert_called_once_with(amphora_mock, None)
83
83
  client_mock.get_interface.assert_called_once_with(
84
84
  amphora_mock, IP_ADDRESS, None, log_error=False)
@@ -71,7 +71,6 @@ class TestVRRPRestDriver(base.TestCase):
71
71
  "}\n"
72
72
  "\n"
73
73
  "vrrp_instance TESTGROUP {\n"
74
- " state MASTER\n"
75
74
  " interface eth1\n"
76
75
  " virtual_router_id 1\n"
77
76
  " priority 100\n"
@@ -124,7 +123,6 @@ class TestVRRPRestDriver(base.TestCase):
124
123
  "}\n"
125
124
  "\n"
126
125
  "vrrp_instance TESTGROUP {\n"
127
- " state MASTER\n"
128
126
  " interface eth1\n"
129
127
  " virtual_router_id 1\n"
130
128
  " priority 100\n"
@@ -170,7 +168,6 @@ class TestVRRPRestDriver(base.TestCase):
170
168
  "}\n"
171
169
  "\n"
172
170
  "vrrp_instance TESTGROUP {\n"
173
- " state MASTER\n"
174
171
  " interface eth1\n"
175
172
  " virtual_router_id 1\n"
176
173
  " priority 100\n"
@@ -220,7 +217,6 @@ class TestVRRPRestDriver(base.TestCase):
220
217
  "}\n"
221
218
  "\n"
222
219
  "vrrp_instance TESTGROUP {\n"
223
- " state MASTER\n"
224
220
  " interface eth1\n"
225
221
  " virtual_router_id 1\n"
226
222
  " priority 100\n"
@@ -107,6 +107,9 @@ class TestVRRPRestDriver(base.TestCase):
107
107
 
108
108
  self.keepalived_mixin.start_vrrp_service(self.amphora_mock)
109
109
 
110
+ populate_mock = self.keepalived_mixin._populate_amphora_api_version
111
+ populate_mock.assert_called_once_with(self.amphora_mock,
112
+ timeout_dict=None)
110
113
  self.clients[API_VERSION].start_vrrp.assert_called_once_with(
111
114
  self.amphora_mock, timeout_dict=None)
112
115
 
@@ -121,6 +124,20 @@ class TestVRRPRestDriver(base.TestCase):
121
124
 
122
125
  self.clients[API_VERSION].start_vrrp.assert_not_called()
123
126
 
127
+ # With timeout_dict
128
+ self.clients[API_VERSION].start_vrrp.reset_mock()
129
+ populate_mock.reset_mock()
130
+
131
+ timeout_dict = mock.Mock()
132
+ self.keepalived_mixin.start_vrrp_service(self.amphora_mock,
133
+ timeout_dict=timeout_dict)
134
+
135
+ populate_mock = self.keepalived_mixin._populate_amphora_api_version
136
+ populate_mock.assert_called_once_with(self.amphora_mock,
137
+ timeout_dict=timeout_dict)
138
+ self.clients[API_VERSION].start_vrrp.assert_called_once_with(
139
+ self.amphora_mock, timeout_dict=timeout_dict)
140
+
124
141
  def test_reload_vrrp_service(self):
125
142
 
126
143
  self.keepalived_mixin.reload_vrrp_service(self.lb_mock)
@@ -103,6 +103,16 @@ class TestPaginationHelper(base.TestCase):
103
103
  helper.apply(query_mock, models.LoadBalancer)
104
104
  self.assertEqual(params, helper.filters)
105
105
 
106
+ @mock.patch('octavia.api.common.pagination.request')
107
+ def test_filter_with_booleans(self, request_mock):
108
+ params = {'backup': 'True', 'admin_state_up': 'false'}
109
+ expected_params = {'backup': True, 'enabled': False}
110
+ helper = pagination.PaginationHelper(params)
111
+ query_mock = mock.MagicMock()
112
+
113
+ helper.apply(query_mock, models.Member)
114
+ self.assertEqual(expected_params, helper.filters)
115
+
106
116
  @mock.patch('octavia.api.common.pagination.request')
107
117
  def test_filter_mismatched_params(self, request_mock):
108
118
  params = {
@@ -227,12 +237,46 @@ class TestPaginationHelper(base.TestCase):
227
237
  helper = pagination.PaginationHelper(params)
228
238
  links = helper._make_links(model_list)
229
239
  self.assertEqual(links[0].rel, "previous")
240
+ self.assertEqual(
241
+ links[0].href,
242
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
243
+ "&page_reverse=True").format(
244
+ base_uri=api_base_uri,
245
+ path=request_mock.path,
246
+ limit=params['limit'],
247
+ marker=member1.id
248
+ ))
249
+ self.assertEqual(links[1].rel, "next")
230
250
  self.assertEqual(
231
251
  links[1].href,
232
252
  "{base_uri}{path}?limit={limit}&marker={marker}".format(
233
253
  base_uri=api_base_uri,
234
254
  path=request_mock.path,
235
255
  limit=params['limit'],
256
+ marker=member1.id))
257
+
258
+ @mock.patch('octavia.api.common.pagination.request')
259
+ def test_make_links_with_zero_limit(self, request_mock):
260
+ request_mock.path = "/lbaas/v2/pools/1/members"
261
+ request_mock.path_url = "http://localhost" + request_mock.path
262
+ api_base_uri = "https://127.0.0.1"
263
+ conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
264
+ conf.config(group='api_settings', api_base_uri=api_base_uri)
265
+ member1 = models.Member()
266
+ member1.id = uuidutils.generate_uuid()
267
+ model_list = [member1]
268
+
269
+ params = {'limit': 0, 'marker': member1.id}
270
+ helper = pagination.PaginationHelper(params)
271
+ links = helper._make_links(model_list)
272
+ self.assertEqual(links[0].rel, "previous")
273
+ self.assertEqual(
274
+ links[0].href,
275
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
276
+ "&page_reverse=True").format(
277
+ base_uri=api_base_uri,
278
+ path=request_mock.path,
279
+ limit=None,
236
280
  marker=member1.id
237
281
  ))
238
282
  self.assertEqual(links[1].rel, "next")
@@ -241,5 +285,38 @@ class TestPaginationHelper(base.TestCase):
241
285
  "{base_uri}{path}?limit={limit}&marker={marker}".format(
242
286
  base_uri=api_base_uri,
243
287
  path=request_mock.path,
244
- limit=params['limit'],
288
+ limit=None,
289
+ marker=member1.id))
290
+
291
+ @mock.patch('octavia.api.common.pagination.request')
292
+ def test_make_links_with_negative_limit(self, request_mock):
293
+ request_mock.path = "/lbaas/v2/pools/1/members"
294
+ request_mock.path_url = "http://localhost" + request_mock.path
295
+ api_base_uri = "https://127.0.0.1"
296
+ conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
297
+ conf.config(group='api_settings', api_base_uri=api_base_uri)
298
+ member1 = models.Member()
299
+ member1.id = uuidutils.generate_uuid()
300
+ model_list = [member1]
301
+
302
+ params = {'limit': -1, 'marker': member1.id}
303
+ helper = pagination.PaginationHelper(params)
304
+ links = helper._make_links(model_list)
305
+ self.assertEqual(links[0].rel, "previous")
306
+ self.assertEqual(
307
+ links[0].href,
308
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
309
+ "&page_reverse=True").format(
310
+ base_uri=api_base_uri,
311
+ path=request_mock.path,
312
+ limit=None,
313
+ marker=member1.id
314
+ ))
315
+ self.assertEqual(links[1].rel, "next")
316
+ self.assertEqual(
317
+ links[1].href,
318
+ "{base_uri}{path}?limit={limit}&marker={marker}".format(
319
+ base_uri=api_base_uri,
320
+ path=request_mock.path,
321
+ limit=None,
245
322
  marker=member1.id))
@@ -17,8 +17,12 @@ from wsme import exc
17
17
  from wsme.rest import json as wsme_json
18
18
  from wsme import types as wsme_types
19
19
 
20
+ from octavia.api.common import types
21
+ from octavia.api.v2.types import health_monitor as health_monitor_type
22
+ from octavia.api.v2.types import member as member_type
20
23
  from octavia.api.v2.types import pool as pool_type
21
24
  from octavia.common import constants
25
+ from octavia.common import data_models
22
26
  from octavia.tests.unit.api.common import base
23
27
 
24
28
 
@@ -224,3 +228,70 @@ class TestSessionPersistencePUT(base.BaseTypesTest, TestSessionPersistence):
224
228
  body = {"cookie_name": "cookie\nmonster"}
225
229
  self.assertRaises(exc.InvalidInput, wsme_json.fromjson, self._type,
226
230
  body)
231
+
232
+
233
+ class TestPoolResponse(base.BaseTypesTest):
234
+
235
+ _type = pool_type.PoolResponse
236
+
237
+ def test_pool_response_with_health_monitor(self):
238
+ health_monitor_id = uuidutils.generate_uuid()
239
+ health_monitor_model = data_models.HealthMonitor(id=health_monitor_id)
240
+ pool_model = data_models.Pool(health_monitor=health_monitor_model)
241
+ pool = self._type.from_data_model(data_model=pool_model)
242
+ self.assertEqual(pool.healthmonitor_id, health_monitor_id)
243
+
244
+ def test_pool_response_with_members(self):
245
+ member_id = uuidutils.generate_uuid()
246
+ members = [data_models.Member(id=member_id)]
247
+ pool_model = data_models.Pool(members=members)
248
+ pool = self._type.from_data_model(data_model=pool_model)
249
+ self.assertIsInstance(pool.members[0], types.IdOnlyType)
250
+ self.assertEqual(pool.members[0].id, member_id)
251
+
252
+ def test_pool_response_with_load_balancer(self):
253
+ load_balancer_id = uuidutils.generate_uuid()
254
+ load_balancer = data_models.LoadBalancer(id=load_balancer_id)
255
+ pool_model = data_models.Pool(load_balancer=load_balancer)
256
+ pool = self._type.from_data_model(data_model=pool_model)
257
+ self.assertIsInstance(pool.loadbalancers[0], types.IdOnlyType)
258
+ self.assertEqual(pool.loadbalancers[0].id, load_balancer_id)
259
+
260
+ def test_pool_response_with_session_persistence(self):
261
+ session_persistence = data_models.SessionPersistence(
262
+ cookie_name="test"
263
+ )
264
+ pool_model = data_models.Pool(session_persistence=session_persistence)
265
+ pool = self._type.from_data_model(data_model=pool_model)
266
+ self.assertEqual(pool.session_persistence.cookie_name, "test")
267
+
268
+ def test_pool_response_without_children(self):
269
+ pool = self._type.from_data_model(data_model=data_models.Pool())
270
+ self.assertEqual(len(pool.loadbalancers), 0)
271
+ self.assertIsNone(pool.session_persistence)
272
+ self.assertEqual(len(pool.members), 0)
273
+ self.assertEqual(len(pool.listeners), 0)
274
+ self.assertEqual(pool.healthmonitor_id, wsme_types.Unset)
275
+
276
+
277
+ class TestPoolFullResponse(base.BaseTypesTest):
278
+
279
+ _type = pool_type.PoolFullResponse
280
+
281
+ def test_pool_full_response_with_health_monitor(self):
282
+ health_monitor_model = data_models.HealthMonitor()
283
+ pool_model = data_models.Pool(health_monitor=health_monitor_model)
284
+ pool = self._type.from_data_model(data_model=pool_model)
285
+ self.assertIsInstance(
286
+ pool.healthmonitor, health_monitor_type.HealthMonitorFullResponse
287
+ )
288
+
289
+ def test_pool_full_response_with_members(self):
290
+ members = [data_models.Member()]
291
+ pool_model = data_models.Pool(members=members)
292
+ pool = self._type.from_data_model(data_model=pool_model)
293
+ self.assertIsInstance(pool.members[0], member_type.MemberFullResponse)
294
+
295
+ def test_pool_full_response_without_children(self):
296
+ pool = self._type.from_data_model(data_model=data_models.Pool())
297
+ self.assertIsNone(pool.healthmonitor)
@@ -15,7 +15,6 @@ from unittest import mock
15
15
  import uuid
16
16
 
17
17
  from barbicanclient.v1 import secrets
18
- from OpenSSL import crypto
19
18
 
20
19
  import octavia.certificates.common.barbican as barbican_common
21
20
  import octavia.certificates.common.cert as cert
@@ -138,10 +137,11 @@ class TestBarbicanManager(base.TestCase):
138
137
  sorted(data.get_intermediates()))
139
138
  self.assertIsNone(data.get_private_key_passphrase())
140
139
 
141
- @mock.patch('OpenSSL.crypto.load_pkcs12')
140
+ @mock.patch('cryptography.hazmat.primitives.serialization.pkcs12.'
141
+ 'load_pkcs12')
142
142
  def test_get_cert_bad_pkcs12(self, mock_load_pkcs12):
143
143
 
144
- mock_load_pkcs12.side_effect = [crypto.Error]
144
+ mock_load_pkcs12.side_effect = [ValueError]
145
145
 
146
146
  # Mock out the client
147
147
  self.bc.secrets.get.return_value = self.secret_pkcs12
@@ -0,0 +1,53 @@
1
+ # Copyright 2023 Red Hat
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
+
15
+ from oslo_utils import uuidutils
16
+
17
+ from octavia.certificates.common import cert
18
+ from octavia.certificates.manager import noop as noop_cert_mgr
19
+ from octavia.tests.common import sample_certs
20
+ import octavia.tests.unit.base as base
21
+
22
+
23
+ class TestNoopManager(base.TestCase):
24
+
25
+ def setUp(self):
26
+ super().setUp()
27
+ self.manager = noop_cert_mgr.NoopCertManager()
28
+
29
+ def test_store_cert(self):
30
+ certificate = self.manager.store_cert(
31
+ None,
32
+ sample_certs.X509_CERT,
33
+ sample_certs.X509_CERT_KEY_ENCRYPTED,
34
+ sample_certs.X509_IMDS,
35
+ private_key_passphrase=sample_certs.X509_CERT_KEY_PASSPHRASE)
36
+ self.assertIsNotNone(certificate)
37
+ self.assertIsInstance(certificate, cert.Cert)
38
+
39
+ def test_get_cert(self):
40
+ cert_ref = uuidutils.generate_uuid()
41
+ certificate = self.manager.get_cert(
42
+ context=None,
43
+ cert_ref=cert_ref)
44
+ self.assertIsNotNone(certificate)
45
+ self.assertIsInstance(certificate, cert.Cert)
46
+
47
+ def test_get_secret(self):
48
+ secret_ref = uuidutils.generate_uuid()
49
+ secret = self.manager.get_secret(
50
+ context=None,
51
+ secret_ref=secret_ref)
52
+ self.assertIsNotNone(secret)
53
+ self.assertIsInstance(secret, cert.Cert)
@@ -147,6 +147,7 @@ class TestPrometheusProxyCMD(base.TestCase):
147
147
  mock_http.shutdown.assert_called_once()
148
148
 
149
149
  @mock.patch('threading.Thread')
150
+ @mock.patch('http.server.ThreadingHTTPServer.__init__')
150
151
  @mock.patch('http.server.ThreadingHTTPServer.serve_forever')
151
152
  @mock.patch('octavia.amphorae.backends.utils.network_namespace.'
152
153
  'NetworkNamespace.__exit__')
@@ -155,12 +156,18 @@ class TestPrometheusProxyCMD(base.TestCase):
155
156
  @mock.patch('octavia.cmd.prometheus_proxy.EXIT_EVENT')
156
157
  @mock.patch('octavia.cmd.prometheus_proxy.SignalHandler')
157
158
  def test_main(self, mock_signal_handler, mock_exit_event, mock_netns_enter,
158
- mock_netns_exit, mock_serve_forever, mock_thread):
159
+ mock_netns_exit, mock_serve_forever, mock_server_init,
160
+ mock_thread):
159
161
 
160
162
  mock_exit_event.is_set.side_effect = [False, False, True]
161
163
  mock_netns_enter.side_effect = [Exception('boom'), True]
162
164
 
165
+ mock_server_init.return_value = None
166
+
163
167
  prometheus_proxy.main()
164
168
 
165
169
  mock_signal_handler.assert_called_once()
170
+ mock_server_init.assert_called_once_with(
171
+ ('127.0.0.1', 9102),
172
+ prometheus_proxy.PrometheusProxy)
166
173
  mock_serve_forever.assert_called_once()
@@ -813,7 +813,6 @@ class TestHaproxyCfg(base.TestCase):
813
813
  " balance roundrobin\n"
814
814
  " cookie SRV insert indirect nocache\n"
815
815
  " timeout check 31s\n"
816
- " option ssl-hello-chk\n"
817
816
  " fullconn {maxconn}\n"
818
817
  " option allbackups\n"
819
818
  " timeout connect 5000\n"
@@ -1331,11 +1330,11 @@ class TestHaproxyCfg(base.TestCase):
1331
1330
  " timeout connect 5000\n"
1332
1331
  " timeout server 50000\n"
1333
1332
  " server sample_member_id_1 10.0.0.99:82 weight 13 "
1334
- "check inter 30s fall 3 rise 2 cookie sample_member_id_1 "
1335
- "{opts} alpn {alpn}\n"
1333
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1334
+ "sample_member_id_1 {opts} alpn {alpn}\n"
1336
1335
  " server sample_member_id_2 10.0.0.98:82 weight 13 "
1337
- "check inter 30s fall 3 rise 2 cookie sample_member_id_2 "
1338
- "{opts} alpn {alpn}\n\n").format(
1336
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1337
+ "sample_member_id_2 {opts} alpn {alpn}\n\n").format(
1339
1338
  maxconn=constants.HAPROXY_DEFAULT_MAXCONN,
1340
1339
  opts="ssl crt %s verify none sni ssl_fc_sni" % cert_file_path +
1341
1340
  " ciphers " + constants.CIPHERS_OWASP_SUITE_B +
@@ -1410,11 +1409,11 @@ class TestHaproxyCfg(base.TestCase):
1410
1409
  " timeout connect 5000\n"
1411
1410
  " timeout server 50000\n"
1412
1411
  " server sample_member_id_1 10.0.0.99:82 weight 13 "
1413
- "check inter 30s fall 3 rise 2 cookie sample_member_id_1 "
1414
- "{opts} alpn {alpn}\n"
1412
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1413
+ "sample_member_id_1 {opts} alpn {alpn}\n"
1415
1414
  " server sample_member_id_2 10.0.0.98:82 weight 13 "
1416
- "check inter 30s fall 3 rise 2 cookie sample_member_id_2 "
1417
- "{opts} alpn {alpn}\n\n").format(
1415
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1416
+ "sample_member_id_2 {opts} alpn {alpn}\n\n").format(
1418
1417
  maxconn=constants.HAPROXY_DEFAULT_MAXCONN,
1419
1418
  opts="ssl crt %s verify none sni ssl_fc_sni" % cert_file_path +
1420
1419
  " ciphers " + constants.CIPHERS_OWASP_SUITE_B,
@@ -1450,11 +1449,11 @@ class TestHaproxyCfg(base.TestCase):
1450
1449
  " timeout connect 5000\n"
1451
1450
  " timeout server 50000\n"
1452
1451
  " server sample_member_id_1 10.0.0.99:82 weight 13 "
1453
- "check inter 30s fall 3 rise 2 cookie sample_member_id_1 "
1454
- "{opts} alpn {alpn}\n"
1452
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1453
+ "sample_member_id_1 {opts} alpn {alpn}\n"
1455
1454
  " server sample_member_id_2 10.0.0.98:82 weight 13 "
1456
- "check inter 30s fall 3 rise 2 cookie sample_member_id_2 "
1457
- "{opts} alpn {alpn}\n\n").format(
1455
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1456
+ "sample_member_id_2 {opts} alpn {alpn}\n\n").format(
1458
1457
  maxconn=constants.HAPROXY_DEFAULT_MAXCONN,
1459
1458
  opts="ssl crt %s verify none sni ssl_fc_sni" % cert_file_path +
1460
1459
  " no-sslv3 no-tlsv10 no-tlsv11",
@@ -1550,11 +1549,11 @@ class TestHaproxyCfg(base.TestCase):
1550
1549
  " timeout connect 5000\n"
1551
1550
  " timeout server 50000\n"
1552
1551
  " server sample_member_id_1 10.0.0.99:82 weight 13 "
1553
- "check inter 30s fall 3 rise 2 cookie sample_member_id_1 "
1554
- "{opts} alpn {alpn}\n"
1552
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1553
+ "sample_member_id_1 {opts} alpn {alpn}\n"
1555
1554
  " server sample_member_id_2 10.0.0.98:82 weight 13 "
1556
- "check inter 30s fall 3 rise 2 cookie sample_member_id_2 "
1557
- "{opts} alpn {alpn}\n\n").format(
1555
+ "check check-alpn {alpn} inter 30s fall 3 rise 2 cookie "
1556
+ "sample_member_id_2 {opts} alpn {alpn}\n\n").format(
1558
1557
  maxconn=constants.HAPROXY_DEFAULT_MAXCONN,
1559
1558
  opts="%s %s %s %s %s %s" % (
1560
1559
  "ssl", "crt", pool_client_cert,
@@ -78,3 +78,38 @@ class TestConfig(base.TestCase):
78
78
  self.assertEqual(
79
79
  3,
80
80
  conf.conf.haproxy_amphora.active_connection_retry_interval)
81
+
82
+ def test_handle_neutron_deprecations(self):
83
+ conf = self.useFixture(oslo_fixture.Config(config.cfg.CONF))
84
+
85
+ # The deprecated settings are copied to the new settings
86
+ conf.config(endpoint='my_endpoint',
87
+ endpoint_type='internal',
88
+ ca_certificates_file='/path/to/certs',
89
+ group='neutron')
90
+
91
+ config.handle_neutron_deprecations()
92
+
93
+ self.assertEqual('my_endpoint', conf.conf.neutron.endpoint_override)
94
+ self.assertEqual(['internal'], conf.conf.neutron.valid_interfaces)
95
+ self.assertEqual('/path/to/certs', conf.conf.neutron.cafile)
96
+
97
+ # Test case for https://bugs.launchpad.net/octavia/+bug/2051604
98
+ def test_handle_neutron_deprecations_with_precedence(self):
99
+ conf = self.useFixture(oslo_fixture.Config(config.cfg.CONF))
100
+
101
+ # The deprecated settings should not override the new settings when
102
+ # they exist
103
+ conf.config(endpoint='my_old_endpoint',
104
+ endpoint_type='old_type',
105
+ ca_certificates_file='/path/to/old_certs',
106
+ endpoint_override='my_endpoint',
107
+ valid_interfaces=['internal'],
108
+ cafile='/path/to/certs',
109
+ group='neutron')
110
+
111
+ config.handle_neutron_deprecations()
112
+
113
+ self.assertEqual('my_endpoint', conf.conf.neutron.endpoint_override)
114
+ self.assertEqual(['internal'], conf.conf.neutron.valid_interfaces)
115
+ self.assertEqual('/path/to/certs', conf.conf.neutron.cafile)
@@ -52,3 +52,35 @@ class TestKeystoneSession(base.TestCase):
52
52
  [call("Overriding [%s].%s with '%s'", 'neutron', 'cafile',
53
53
  'bar')]
54
54
  )
55
+
56
+ # Test case for https://bugs.launchpad.net/octavia/+bug/2051604
57
+ @mock.patch("octavia.common.keystone.ks_loading"
58
+ ".load_auth_from_conf_options")
59
+ @mock.patch("octavia.common.keystone.LOG")
60
+ def test_get_auth_neutron_override_endpoint(self,
61
+ mock_log,
62
+ mock_load_auth):
63
+ opt_mock = mock.MagicMock()
64
+ opt_mock.dest = "foo"
65
+ conf = oslo_fixture.Config(cfg.CONF)
66
+ conf.conf.set_default('endpoint_override', 'default_endpoint',
67
+ 'service_auth')
68
+ conf.conf.set_default('endpoint_override', 'new_endpoint',
69
+ 'neutron')
70
+
71
+ mock_load_auth.side_effect = [
72
+ ks_exceptions.auth_plugins.MissingRequiredOptions(
73
+ [opt_mock]),
74
+ None,
75
+ None
76
+ ]
77
+
78
+ sess = ks.KeystoneSession("neutron")
79
+ sess.get_auth()
80
+
81
+ # [service_auth].endpoint_override should not override
82
+ # [neutron].endpoint_override
83
+ self.assertNotIn(
84
+ call("Overriding [%s].%s with '%s'", 'neutron',
85
+ 'endpoint_override', 'default_endpoint'),
86
+ mock_log.debug.mock_calls)