octavia 13.0.0.0rc1__py3-none-any.whl → 14.0.0__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.
- octavia/amphorae/backends/agent/api_server/lvs_listener_base.py +1 -1
- octavia/amphorae/backends/agent/api_server/osutils.py +5 -5
- octavia/amphorae/backends/agent/api_server/plug.py +3 -2
- octavia/amphorae/backends/agent/api_server/rules_schema.py +52 -0
- octavia/amphorae/backends/agent/api_server/server.py +28 -1
- octavia/amphorae/backends/utils/interface.py +45 -6
- octavia/amphorae/backends/utils/interface_file.py +9 -6
- octavia/amphorae/backends/utils/nftable_utils.py +125 -0
- octavia/amphorae/drivers/driver_base.py +27 -0
- octavia/amphorae/drivers/haproxy/rest_api_driver.py +42 -10
- octavia/amphorae/drivers/health/heartbeat_udp.py +2 -2
- octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py +2 -1
- octavia/amphorae/drivers/noop_driver/driver.py +25 -0
- octavia/api/app.py +3 -0
- octavia/api/common/pagination.py +2 -2
- octavia/api/drivers/amphora_driver/flavor_schema.py +6 -1
- octavia/api/root_controller.py +4 -1
- octavia/api/v2/controllers/health_monitor.py +0 -1
- octavia/api/v2/controllers/l7policy.py +0 -1
- octavia/api/v2/controllers/l7rule.py +0 -1
- octavia/api/v2/controllers/listener.py +0 -1
- octavia/api/v2/controllers/load_balancer.py +13 -7
- octavia/api/v2/controllers/member.py +6 -3
- octavia/api/v2/controllers/pool.py +6 -7
- octavia/api/v2/types/load_balancer.py +5 -1
- octavia/api/v2/types/pool.py +1 -1
- octavia/certificates/common/pkcs12.py +9 -9
- octavia/certificates/manager/barbican.py +24 -16
- octavia/certificates/manager/castellan_mgr.py +12 -7
- octavia/certificates/manager/local.py +4 -4
- octavia/certificates/manager/noop.py +106 -0
- octavia/cmd/driver_agent.py +1 -1
- octavia/cmd/health_checker.py +0 -4
- octavia/cmd/health_manager.py +1 -5
- octavia/cmd/house_keeping.py +1 -1
- octavia/cmd/interface.py +0 -4
- octavia/cmd/octavia_worker.py +0 -4
- octavia/cmd/prometheus_proxy.py +0 -5
- octavia/cmd/status.py +0 -6
- octavia/common/base_taskflow.py +1 -1
- octavia/common/clients.py +15 -3
- octavia/common/config.py +24 -6
- octavia/common/constants.py +34 -0
- octavia/common/data_models.py +3 -1
- octavia/common/exceptions.py +11 -0
- octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +7 -5
- octavia/common/keystone.py +7 -7
- octavia/common/tls_utils/cert_parser.py +24 -10
- octavia/common/utils.py +6 -0
- octavia/common/validate.py +2 -2
- octavia/compute/drivers/nova_driver.py +23 -5
- octavia/controller/worker/task_utils.py +28 -6
- octavia/controller/worker/v2/controller_worker.py +49 -15
- octavia/controller/worker/v2/flows/amphora_flows.py +120 -21
- octavia/controller/worker/v2/flows/flow_utils.py +15 -13
- octavia/controller/worker/v2/flows/listener_flows.py +95 -5
- octavia/controller/worker/v2/flows/load_balancer_flows.py +74 -30
- octavia/controller/worker/v2/taskflow_jobboard_driver.py +17 -1
- octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +145 -24
- octavia/controller/worker/v2/tasks/compute_tasks.py +1 -1
- octavia/controller/worker/v2/tasks/database_tasks.py +72 -41
- octavia/controller/worker/v2/tasks/lifecycle_tasks.py +97 -41
- octavia/controller/worker/v2/tasks/network_tasks.py +57 -60
- octavia/controller/worker/v2/tasks/shim_tasks.py +28 -0
- octavia/db/migration/alembic_migrations/versions/55874a4ceed6_add_l7policy_action_redirect_prefix.py +1 -1
- octavia/db/migration/alembic_migrations/versions/5a3ee5472c31_add_cert_expiration__infor_in_amphora_table.py +1 -1
- octavia/db/migration/alembic_migrations/versions/6742ca1b27c2_add_l7policy_redirect_http_code.py +1 -1
- octavia/db/migration/alembic_migrations/versions/db2a73e82626_add_vnic_type_for_vip.py +36 -0
- octavia/db/models.py +1 -0
- octavia/db/prepare.py +1 -1
- octavia/db/repositories.py +53 -34
- octavia/distributor/drivers/driver_base.py +1 -1
- octavia/network/base.py +3 -16
- octavia/network/data_models.py +4 -1
- octavia/network/drivers/neutron/allowed_address_pairs.py +27 -26
- octavia/network/drivers/noop_driver/driver.py +10 -23
- octavia/tests/common/sample_certs.py +115 -0
- octavia/tests/common/sample_haproxy_prometheus +1 -1
- octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +37 -0
- octavia/tests/functional/api/test_healthcheck.py +2 -2
- octavia/tests/functional/api/v2/base.py +1 -1
- octavia/tests/functional/api/v2/test_listener.py +45 -0
- octavia/tests/functional/api/v2/test_load_balancer.py +17 -0
- octavia/tests/functional/db/base.py +9 -0
- octavia/tests/functional/db/test_models.py +2 -1
- octavia/tests/functional/db/test_repositories.py +55 -99
- octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +4 -2
- octavia/tests/unit/amphorae/backends/utils/test_interface.py +201 -1
- octavia/tests/unit/amphorae/backends/utils/test_keepalivedlvs_query.py +1 -1
- octavia/tests/unit/amphorae/backends/utils/test_nftable_utils.py +194 -0
- octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py +27 -5
- octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +15 -2
- octavia/tests/unit/amphorae/drivers/keepalived/test_vrrp_rest_driver.py +17 -0
- octavia/tests/unit/amphorae/drivers/noop_driver/test_driver.py +2 -1
- octavia/tests/unit/api/v2/types/test_pool.py +71 -0
- octavia/tests/unit/certificates/manager/test_barbican.py +3 -3
- octavia/tests/unit/certificates/manager/test_noop.py +53 -0
- octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +16 -17
- octavia/tests/unit/common/sample_configs/sample_configs_combined.py +5 -3
- octavia/tests/unit/common/test_config.py +35 -0
- octavia/tests/unit/common/test_keystone.py +32 -0
- octavia/tests/unit/common/test_utils.py +39 -0
- octavia/tests/unit/compute/drivers/test_nova_driver.py +22 -0
- octavia/tests/unit/controller/worker/test_task_utils.py +58 -2
- octavia/tests/unit/controller/worker/v2/flows/test_amphora_flows.py +28 -5
- octavia/tests/unit/controller/worker/v2/flows/test_listener_flows.py +64 -16
- octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +49 -9
- octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +265 -17
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +101 -1
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +19 -19
- octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +105 -42
- octavia/tests/unit/controller/worker/v2/tasks/test_shim_tasks.py +33 -0
- octavia/tests/unit/controller/worker/v2/test_controller_worker.py +85 -42
- octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +48 -51
- octavia/tests/unit/network/drivers/neutron/test_utils.py +2 -0
- octavia/tests/unit/network/drivers/noop_driver/test_driver.py +0 -7
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/README.rst +6 -1
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/diskimage-create.sh +10 -4
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/requirements.txt +0 -2
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/tox.ini +30 -13
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/AUTHORS +5 -0
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/METADATA +6 -6
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/RECORD +134 -126
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/entry_points.txt +1 -1
- octavia-14.0.0.dist-info/pbr.json +1 -0
- octavia-13.0.0.0rc1.dist-info/pbr.json +0 -1
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/LICENSE +0 -0
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/README.rst +0 -0
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/version.txt +0 -0
- {octavia-13.0.0.0rc1.data → octavia-14.0.0.data}/scripts/octavia-wsgi +0 -0
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/LICENSE +0 -0
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/WHEEL +0 -0
- {octavia-13.0.0.0rc1.dist-info → octavia-14.0.0.dist-info}/top_level.txt +0 -0
@@ -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('
|
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 = [
|
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)
|
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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,
|
@@ -670,9 +670,11 @@ def sample_vrrp_group_tuple():
|
|
670
670
|
smtp_connect_timeout='')
|
671
671
|
|
672
672
|
|
673
|
-
def sample_vip_tuple(ip_address='10.0.0.2', subnet_id='vip_subnet_uuid'
|
674
|
-
|
675
|
-
|
673
|
+
def sample_vip_tuple(ip_address='10.0.0.2', subnet_id='vip_subnet_uuid',
|
674
|
+
vnic_type='normal'):
|
675
|
+
vip = collections.namedtuple('vip', ('ip_address', 'subnet_id',
|
676
|
+
'vnic_type'))
|
677
|
+
return vip(ip_address=ip_address, subnet_id=subnet_id, vnic_type=vnic_type)
|
676
678
|
|
677
679
|
|
678
680
|
def sample_listener_tuple(proto=None, monitor=True, alloc_default_pool=True,
|
@@ -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)
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# under the License.
|
14
14
|
from unittest import mock
|
15
15
|
|
16
|
+
from octavia_lib.common import constants as lib_consts
|
16
17
|
from oslo_utils import uuidutils
|
17
18
|
|
18
19
|
from octavia.common import constants
|
@@ -139,3 +140,41 @@ class TestConfig(base.TestCase):
|
|
139
140
|
expected_sg_name = constants.VIP_SECURITY_GROUP_PREFIX + FAKE_LB_ID
|
140
141
|
self.assertEqual(expected_sg_name,
|
141
142
|
utils.get_vip_security_group_name(FAKE_LB_ID))
|
143
|
+
|
144
|
+
def test_map_protocol_to_nftable_protocol(self):
|
145
|
+
result = utils.map_protocol_to_nftable_protocol(
|
146
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_TCP})
|
147
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
148
|
+
|
149
|
+
result = utils.map_protocol_to_nftable_protocol(
|
150
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_HTTP})
|
151
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
152
|
+
|
153
|
+
result = utils.map_protocol_to_nftable_protocol(
|
154
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_HTTPS})
|
155
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
156
|
+
|
157
|
+
result = utils.map_protocol_to_nftable_protocol(
|
158
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_TERMINATED_HTTPS})
|
159
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
160
|
+
|
161
|
+
result = utils.map_protocol_to_nftable_protocol(
|
162
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_PROXY})
|
163
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
164
|
+
|
165
|
+
result = utils.map_protocol_to_nftable_protocol(
|
166
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_PROXYV2})
|
167
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
168
|
+
|
169
|
+
result = utils.map_protocol_to_nftable_protocol(
|
170
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_UDP})
|
171
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_UDP}, result)
|
172
|
+
|
173
|
+
result = utils.map_protocol_to_nftable_protocol(
|
174
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_SCTP})
|
175
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_SCTP},
|
176
|
+
result)
|
177
|
+
|
178
|
+
result = utils.map_protocol_to_nftable_protocol(
|
179
|
+
{constants.PROTOCOL: lib_consts.PROTOCOL_PROMETHEUS})
|
180
|
+
self.assertEqual({constants.PROTOCOL: lib_consts.PROTOCOL_TCP}, result)
|
@@ -457,6 +457,28 @@ class TestNovaClient(base.TestCase):
|
|
457
457
|
self.manager.attach_network_or_port,
|
458
458
|
self.compute_id, self.network_id)
|
459
459
|
|
460
|
+
def test_attach_network_or_port_fail_claim_pci_exception(self):
|
461
|
+
self.manager.manager.interface_attach.side_effect = [
|
462
|
+
nova_exceptions.BadRequest('Failed to claim PCI device'),
|
463
|
+
nova_exceptions.BadRequest('NotAClaimFailure')]
|
464
|
+
self.assertRaises(exceptions.ComputeNoResourcesException,
|
465
|
+
self.manager.attach_network_or_port,
|
466
|
+
self.compute_id, self.network_id)
|
467
|
+
self.assertRaises(nova_exceptions.BadRequest,
|
468
|
+
self.manager.attach_network_or_port,
|
469
|
+
self.compute_id, self.network_id)
|
470
|
+
|
471
|
+
def test_attach_network_or_port_port_bind_fail_exception(self):
|
472
|
+
self.manager.manager.interface_attach.side_effect = [
|
473
|
+
nova_exceptions.ClientException('PortBindingFailed'),
|
474
|
+
nova_exceptions.ClientException('NotABindFailure')]
|
475
|
+
self.assertRaises(exceptions.ComputeNoResourcesException,
|
476
|
+
self.manager.attach_network_or_port,
|
477
|
+
self.compute_id, self.network_id)
|
478
|
+
self.assertRaises(nova_exceptions.ClientException,
|
479
|
+
self.manager.attach_network_or_port,
|
480
|
+
self.compute_id, self.network_id)
|
481
|
+
|
460
482
|
def test_attach_network_or_port_unknown_exception(self):
|
461
483
|
self.manager.manager.interface_attach.side_effect = [Exception('boom')]
|
462
484
|
self.assertRaises(exceptions.ComputeUnknownException,
|
@@ -14,6 +14,7 @@
|
|
14
14
|
from unittest import mock
|
15
15
|
|
16
16
|
from oslo_utils import uuidutils
|
17
|
+
import tenacity
|
17
18
|
|
18
19
|
from octavia.common import constants
|
19
20
|
from octavia.controller.worker import task_utils as task_utilities
|
@@ -183,7 +184,13 @@ class TestTaskUtils(base.TestCase):
|
|
183
184
|
|
184
185
|
@mock.patch('octavia.db.api.session')
|
185
186
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
187
|
+
@mock.patch('tenacity.nap.time')
|
188
|
+
# mock LOG so we don't fill the console with log messages from
|
189
|
+
# tenacity.retry
|
190
|
+
@mock.patch('octavia.controller.worker.task_utils.LOG')
|
186
191
|
def test_mark_loadbalancer_prov_status_active(self,
|
192
|
+
mock_LOG,
|
193
|
+
mock_time,
|
187
194
|
mock_lb_repo_update,
|
188
195
|
mock_get_session):
|
189
196
|
|
@@ -202,14 +209,42 @@ class TestTaskUtils(base.TestCase):
|
|
202
209
|
mock_lb_repo_update.reset_mock()
|
203
210
|
mock_get_session.side_effect = Exception('fail')
|
204
211
|
|
205
|
-
self.
|
212
|
+
self.assertRaises(
|
213
|
+
tenacity.RetryError,
|
214
|
+
self.task_utils.mark_loadbalancer_prov_status_active,
|
206
215
|
self.LOADBALANCER_ID)
|
207
216
|
|
208
217
|
self.assertFalse(mock_lb_repo_update.called)
|
209
218
|
|
219
|
+
# Exceptions then happy path
|
220
|
+
mock_get_session.reset_mock(side_effect=True)
|
221
|
+
mock_lb_repo_update.reset_mock()
|
222
|
+
|
223
|
+
mock_session = mock_get_session()
|
224
|
+
mock_session_context = mock_session.begin().__enter__()
|
225
|
+
mock_get_session.side_effect = [
|
226
|
+
Exception('fail'),
|
227
|
+
Exception('fail'),
|
228
|
+
Exception('fail'),
|
229
|
+
mock_session]
|
230
|
+
|
231
|
+
self.task_utils.mark_loadbalancer_prov_status_active(
|
232
|
+
self.LOADBALANCER_ID)
|
233
|
+
|
234
|
+
mock_lb_repo_update.assert_called_once_with(
|
235
|
+
mock_session_context,
|
236
|
+
id=self.LOADBALANCER_ID,
|
237
|
+
provisioning_status=constants.ACTIVE)
|
238
|
+
|
210
239
|
@mock.patch('octavia.db.api.session')
|
211
240
|
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
241
|
+
@mock.patch('tenacity.nap.time')
|
242
|
+
# mock LOG so we don't fill the console with log messages from
|
243
|
+
# tenacity.retry
|
244
|
+
@mock.patch('octavia.controller.worker.task_utils.LOG')
|
212
245
|
def test_mark_loadbalancer_prov_status_error(self,
|
246
|
+
mock_LOG,
|
247
|
+
mock_time,
|
213
248
|
mock_lb_repo_update,
|
214
249
|
mock_get_session):
|
215
250
|
|
@@ -228,10 +263,31 @@ class TestTaskUtils(base.TestCase):
|
|
228
263
|
mock_lb_repo_update.reset_mock()
|
229
264
|
mock_get_session.side_effect = Exception('fail')
|
230
265
|
|
266
|
+
self.assertRaises(tenacity.RetryError,
|
267
|
+
self.task_utils.mark_loadbalancer_prov_status_error,
|
268
|
+
self.LOADBALANCER_ID)
|
269
|
+
|
270
|
+
self.assertFalse(mock_lb_repo_update.called)
|
271
|
+
|
272
|
+
# Exceptions then happy path
|
273
|
+
mock_get_session.reset_mock(side_effect=True)
|
274
|
+
mock_lb_repo_update.reset_mock()
|
275
|
+
|
276
|
+
mock_session = mock_get_session()
|
277
|
+
mock_session_context = mock_session.begin().__enter__()
|
278
|
+
mock_get_session.side_effect = [
|
279
|
+
Exception('fail'),
|
280
|
+
Exception('fail'),
|
281
|
+
Exception('fail'),
|
282
|
+
mock_session]
|
283
|
+
|
231
284
|
self.task_utils.mark_loadbalancer_prov_status_error(
|
232
285
|
self.LOADBALANCER_ID)
|
233
286
|
|
234
|
-
|
287
|
+
mock_lb_repo_update.assert_called_once_with(
|
288
|
+
mock_session_context,
|
289
|
+
id=self.LOADBALANCER_ID,
|
290
|
+
provisioning_status=constants.ERROR)
|
235
291
|
|
236
292
|
@mock.patch('octavia.db.api.session')
|
237
293
|
@mock.patch('octavia.db.repositories.MemberRepository.update')
|
@@ -286,6 +286,7 @@ class TestAmphoraFlows(base.TestCase):
|
|
286
286
|
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
287
287
|
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
288
288
|
self.assertIn(constants.AMPHORAE, amp_flow.provides)
|
289
|
+
self.assertIn(constants.AMPHORAE_STATUS, amp_flow.provides)
|
289
290
|
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG, amp_flow.provides)
|
290
291
|
self.assertIn(constants.BASE_PORT, amp_flow.provides)
|
291
292
|
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
@@ -296,7 +297,7 @@ class TestAmphoraFlows(base.TestCase):
|
|
296
297
|
self.assertIn(constants.VIP_SG_ID, amp_flow.provides)
|
297
298
|
|
298
299
|
self.assertEqual(8, len(amp_flow.requires))
|
299
|
-
self.assertEqual(
|
300
|
+
self.assertEqual(14, len(amp_flow.provides))
|
300
301
|
|
301
302
|
def test_get_failover_flow_standalone(self, mock_get_net_driver):
|
302
303
|
failed_amphora = data_models.Amphora(
|
@@ -320,6 +321,7 @@ class TestAmphoraFlows(base.TestCase):
|
|
320
321
|
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
321
322
|
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
322
323
|
self.assertIn(constants.AMPHORAE, amp_flow.provides)
|
324
|
+
self.assertIn(constants.AMPHORAE_STATUS, amp_flow.provides)
|
323
325
|
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG, amp_flow.provides)
|
324
326
|
self.assertIn(constants.BASE_PORT, amp_flow.provides)
|
325
327
|
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
@@ -330,7 +332,7 @@ class TestAmphoraFlows(base.TestCase):
|
|
330
332
|
self.assertIn(constants.VIP_SG_ID, amp_flow.provides)
|
331
333
|
|
332
334
|
self.assertEqual(8, len(amp_flow.requires))
|
333
|
-
self.assertEqual(
|
335
|
+
self.assertEqual(13, len(amp_flow.provides))
|
334
336
|
|
335
337
|
def test_get_failover_flow_bogus_role(self, mock_get_net_driver):
|
336
338
|
failed_amphora = data_models.Amphora(id=uuidutils.generate_uuid(),
|
@@ -366,14 +368,33 @@ class TestAmphoraFlows(base.TestCase):
|
|
366
368
|
|
367
369
|
self.assertIsInstance(vrrp_subflow, flow.Flow)
|
368
370
|
|
371
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG, vrrp_subflow.provides)
|
372
|
+
self.assertIn(constants.AMP_VRRP_INT, vrrp_subflow.provides)
|
373
|
+
self.assertIn(constants.AMPHORAE_STATUS, vrrp_subflow.provides)
|
374
|
+
|
375
|
+
self.assertIn(constants.LOADBALANCER_ID, vrrp_subflow.requires)
|
376
|
+
self.assertIn(constants.AMPHORAE, vrrp_subflow.requires)
|
377
|
+
self.assertIn(constants.AMPHORA_ID, vrrp_subflow.requires)
|
378
|
+
|
379
|
+
self.assertEqual(3, len(vrrp_subflow.provides))
|
380
|
+
self.assertEqual(3, len(vrrp_subflow.requires))
|
381
|
+
|
382
|
+
def test_get_vrrp_subflow_dont_get_status(self, mock_get_net_driver):
|
383
|
+
vrrp_subflow = self.AmpFlow.get_vrrp_subflow('123',
|
384
|
+
get_amphorae_status=False)
|
385
|
+
|
386
|
+
self.assertIsInstance(vrrp_subflow, flow.Flow)
|
387
|
+
|
369
388
|
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG, vrrp_subflow.provides)
|
370
389
|
self.assertIn(constants.AMP_VRRP_INT, vrrp_subflow.provides)
|
371
390
|
|
372
391
|
self.assertIn(constants.LOADBALANCER_ID, vrrp_subflow.requires)
|
373
392
|
self.assertIn(constants.AMPHORAE, vrrp_subflow.requires)
|
393
|
+
self.assertIn(constants.AMPHORA_ID, vrrp_subflow.requires)
|
394
|
+
self.assertIn(constants.AMPHORAE_STATUS, vrrp_subflow.requires)
|
374
395
|
|
375
396
|
self.assertEqual(2, len(vrrp_subflow.provides))
|
376
|
-
self.assertEqual(
|
397
|
+
self.assertEqual(4, len(vrrp_subflow.requires))
|
377
398
|
|
378
399
|
def test_get_vrrp_subflow_dont_create_vrrp_group(
|
379
400
|
self, mock_get_net_driver):
|
@@ -384,12 +405,14 @@ class TestAmphoraFlows(base.TestCase):
|
|
384
405
|
|
385
406
|
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG, vrrp_subflow.provides)
|
386
407
|
self.assertIn(constants.AMP_VRRP_INT, vrrp_subflow.provides)
|
408
|
+
self.assertIn(constants.AMPHORAE_STATUS, vrrp_subflow.provides)
|
387
409
|
|
388
410
|
self.assertIn(constants.LOADBALANCER_ID, vrrp_subflow.requires)
|
389
411
|
self.assertIn(constants.AMPHORAE, vrrp_subflow.requires)
|
412
|
+
self.assertIn(constants.AMPHORA_ID, vrrp_subflow.requires)
|
390
413
|
|
391
|
-
self.assertEqual(
|
392
|
-
self.assertEqual(
|
414
|
+
self.assertEqual(3, len(vrrp_subflow.provides))
|
415
|
+
self.assertEqual(3, len(vrrp_subflow.requires))
|
393
416
|
|
394
417
|
def test_update_amphora_config_flow(self, mock_get_net_driver):
|
395
418
|
|
@@ -34,45 +34,77 @@ class TestListenerFlows(base.TestCase):
|
|
34
34
|
|
35
35
|
def test_get_create_listener_flow(self, mock_get_net_driver):
|
36
36
|
|
37
|
-
|
37
|
+
flavor_dict = {
|
38
|
+
constants.SRIOV_VIP: True,
|
39
|
+
constants.LOADBALANCER_TOPOLOGY: constants.TOPOLOGY_SINGLE}
|
40
|
+
listener_flow = self.ListenerFlow.get_create_listener_flow(
|
41
|
+
flavor_dict=flavor_dict)
|
38
42
|
|
39
43
|
self.assertIsInstance(listener_flow, flow.Flow)
|
40
44
|
|
41
45
|
self.assertIn(constants.LISTENERS, listener_flow.requires)
|
42
46
|
self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
|
47
|
+
self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
|
43
48
|
|
44
|
-
self.
|
45
|
-
|
49
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
|
50
|
+
listener_flow.provides)
|
51
|
+
self.assertIn(constants.AMPHORAE, listener_flow.provides)
|
52
|
+
self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
|
46
53
|
|
47
|
-
|
54
|
+
self.assertEqual(3, len(listener_flow.requires))
|
55
|
+
self.assertEqual(3, len(listener_flow.provides))
|
48
56
|
|
49
|
-
|
57
|
+
def test_get_delete_listener_flow(self, mock_get_net_driver):
|
58
|
+
flavor_dict = {
|
59
|
+
constants.SRIOV_VIP: True,
|
60
|
+
constants.LOADBALANCER_TOPOLOGY: constants.TOPOLOGY_SINGLE}
|
61
|
+
listener_flow = self.ListenerFlow.get_delete_listener_flow(
|
62
|
+
flavor_dict=flavor_dict)
|
50
63
|
|
51
64
|
self.assertIsInstance(listener_flow, flow.Flow)
|
52
65
|
|
53
66
|
self.assertIn(constants.LISTENER, listener_flow.requires)
|
54
67
|
self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
|
55
68
|
self.assertIn(constants.PROJECT_ID, listener_flow.requires)
|
69
|
+
self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
|
56
70
|
|
57
|
-
self.
|
58
|
-
|
71
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
|
72
|
+
listener_flow.provides)
|
73
|
+
self.assertIn(constants.AMPHORAE, listener_flow.provides)
|
74
|
+
self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
|
75
|
+
|
76
|
+
self.assertEqual(4, len(listener_flow.requires))
|
77
|
+
self.assertEqual(3, len(listener_flow.provides))
|
59
78
|
|
60
79
|
def test_get_delete_listener_internal_flow(self, mock_get_net_driver):
|
80
|
+
flavor_dict = {
|
81
|
+
constants.SRIOV_VIP: True,
|
82
|
+
constants.LOADBALANCER_TOPOLOGY: constants.TOPOLOGY_SINGLE}
|
61
83
|
fake_listener = {constants.LISTENER_ID: uuidutils.generate_uuid()}
|
62
84
|
listener_flow = self.ListenerFlow.get_delete_listener_internal_flow(
|
63
|
-
fake_listener)
|
85
|
+
fake_listener, flavor_dict=flavor_dict)
|
64
86
|
|
65
87
|
self.assertIsInstance(listener_flow, flow.Flow)
|
66
88
|
|
67
89
|
self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
|
68
90
|
self.assertIn(constants.PROJECT_ID, listener_flow.requires)
|
91
|
+
self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
|
92
|
+
|
93
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
|
94
|
+
listener_flow.provides)
|
95
|
+
self.assertIn(constants.AMPHORAE, listener_flow.provides)
|
96
|
+
self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
|
69
97
|
|
70
|
-
self.assertEqual(
|
71
|
-
self.assertEqual(
|
98
|
+
self.assertEqual(3, len(listener_flow.requires))
|
99
|
+
self.assertEqual(3, len(listener_flow.provides))
|
72
100
|
|
73
101
|
def test_get_update_listener_flow(self, mock_get_net_driver):
|
102
|
+
flavor_dict = {
|
103
|
+
constants.SRIOV_VIP: True,
|
104
|
+
constants.LOADBALANCER_TOPOLOGY: constants.TOPOLOGY_SINGLE}
|
74
105
|
|
75
|
-
listener_flow = self.ListenerFlow.get_update_listener_flow(
|
106
|
+
listener_flow = self.ListenerFlow.get_update_listener_flow(
|
107
|
+
flavor_dict=flavor_dict)
|
76
108
|
|
77
109
|
self.assertIsInstance(listener_flow, flow.Flow)
|
78
110
|
|
@@ -80,15 +112,31 @@ class TestListenerFlows(base.TestCase):
|
|
80
112
|
self.assertIn(constants.UPDATE_DICT, listener_flow.requires)
|
81
113
|
self.assertIn(constants.LISTENERS, listener_flow.requires)
|
82
114
|
self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
|
115
|
+
self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
|
83
116
|
|
84
|
-
self.
|
85
|
-
|
117
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
|
118
|
+
listener_flow.provides)
|
119
|
+
self.assertIn(constants.AMPHORAE, listener_flow.provides)
|
120
|
+
self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
|
121
|
+
|
122
|
+
self.assertEqual(5, len(listener_flow.requires))
|
123
|
+
self.assertEqual(3, len(listener_flow.provides))
|
86
124
|
|
87
125
|
def test_get_create_all_listeners_flow(self, mock_get_net_driver):
|
88
|
-
|
126
|
+
flavor_dict = {
|
127
|
+
constants.SRIOV_VIP: True,
|
128
|
+
constants.LOADBALANCER_TOPOLOGY: constants.TOPOLOGY_ACTIVE_STANDBY}
|
129
|
+
listeners_flow = self.ListenerFlow.get_create_all_listeners_flow(
|
130
|
+
flavor_dict=flavor_dict)
|
89
131
|
self.assertIsInstance(listeners_flow, flow.Flow)
|
90
132
|
self.assertIn(constants.LOADBALANCER, listeners_flow.requires)
|
91
133
|
self.assertIn(constants.LOADBALANCER_ID, listeners_flow.requires)
|
134
|
+
self.assertIn(constants.AMPHORAE_STATUS, listeners_flow.requires)
|
92
135
|
self.assertIn(constants.LOADBALANCER, listeners_flow.provides)
|
93
|
-
self.
|
94
|
-
|
136
|
+
self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
|
137
|
+
listeners_flow.provides)
|
138
|
+
self.assertIn(constants.AMPHORAE, listeners_flow.provides)
|
139
|
+
self.assertIn(constants.AMPHORA_FIREWALL_RULES,
|
140
|
+
listeners_flow.provides)
|
141
|
+
self.assertEqual(3, len(listeners_flow.requires))
|
142
|
+
self.assertEqual(5, len(listeners_flow.provides))
|