diff --git a/provides.py b/provides.py index 3d13816..5a3b6dd 100644 --- a/provides.py +++ b/provides.py @@ -83,6 +83,8 @@ class BGPEndpoint(reactive.Endpoint): for a in rel_network['bind-addresses'][0]['addresses']] actual_bindings = [] + if bindings is None: + continue for binding in bindings: bind_network = ch_core.hookenv.network_get( binding, diff --git a/tox.ini b/tox.ini index 4c73ef6..dabda0d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,3 +1,6 @@ +# Source charm: ./tox.ini +# This file is managed centrally by release-tools and should not be modified +# within individual charm repos. [tox] skipsdist = True envlist = pep8,py35 @@ -6,9 +9,21 @@ envlist = pep8,py35 setenv = VIRTUAL_ENV={envdir} PYTHONHASHSEED=0 TERM=linux + LAYER_PATH={toxinidir}/layers + INTERFACE_PATH={toxinidir}/interfaces + JUJU_REPOSITORY={toxinidir}/build +passenv = http_proxy https_proxy install_command = pip install {opts} {packages} +[testenv:py27] +basepython = python2.7 +# Reactive source charms are Python3-only, but a py27 unit test target +# is required by OpenStack Governance. Remove this shim as soon as +# permitted. http://governance.openstack.org/reference/cti/python_cti.html +whitelist_externals = true +commands = true + [testenv:py35] basepython = python3 deps = -r{toxinidir}/test-requirements.txt @@ -17,7 +32,7 @@ commands = ostestr {posargs} [testenv:pep8] basepython = python3 deps = -r{toxinidir}/test-requirements.txt -commands = flake8 {posargs} . unit_tests +commands = flake8 {posargs} unit_tests [testenv:venv] commands = {posargs} diff --git a/unit_tests/test_provides.py b/unit_tests/test_provides.py index 2fd9e55..ff5bfe5 100644 --- a/unit_tests/test_provides.py +++ b/unit_tests/test_provides.py @@ -11,6 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import mock +import yaml import unit_tests.utils as ut_utils import provides @@ -30,3 +32,194 @@ class TestBGPProvides(ut_utils.BaseTestCase): endpoint = provides.BGPEndpoint('bgpserver') asn = endpoint.generate_asn() self.assertEqual(asn, 4294967294) + + _network_get_side_effect = [ + yaml.load(''' +bind-addresses: +- macaddress: 52:54:00:0a:97:58 + interfacename: ens6 + addresses: + - address: 172.16.122.251 + cidr: 172.16.122.0/24 +ingress-addresses: +- 172.16.122.251 +'''), # bgpserver + yaml.load(''' +bind-addresses: +- macaddress: 52:54:01:0a:97:58 + interfacename: ens7 + addresses: + - address: 172.16.100.1 + cidr: 172.16.100.0/30 + - address: 2001:db8:100::1:0:0 + cidr: 2001:db8:100::/64 +ingress-addresses: +- 172.16.100.1 +- 2001:db8:100::1:0:0 +'''), # ptp0 + yaml.load(''' +bind-addresses: +- macaddress: 52:54:02:0a:97:58 + interfacename: ens8 + addresses: + - address: 172.16.110.1 + cidr: 172.16.110.0/30 + - address: 2001:db8:110::1:0:0 + cidr: 2001:db8:110::/64 +ingress-addresses: +- 172.16.110.1 +- 2001:db8:110::1:0:0 +'''), # ptp1 + yaml.load(''' +bind-addresses: +- macaddress: 52:54:03:0a:97:58 + interfacename: ens9 + addresses: + - address: 172.16.120.1 + cidr: 172.16.120.0/30 + - address: 2001:db8:120::1:0:0 + cidr: 2001:db8:120::/64 +ingress-addresses: +- 172.16.120.1 +- 2001:db8:120::1:0:0 +'''), # ptp2 + yaml.load(''' +bind-addresses: +- macaddress: 52:54:00:0a:97:58 + interfacename: ens6 + addresses: + - address: 172.16.122.251 + cidr: 172.16.122.0/24 +ingress-addresses: +- 172.16.122.251 +'''), # ptp3 + yaml.load(''' +bind-addresses: +- macaddress: 52:54:00:0a:97:58 + interfacename: ens6 + addresses: + - address: 172.16.122.251 + cidr: 172.16.122.0/24 +ingress-addresses: +- 172.16.122.251 +'''), # lan0 + ] + + _relation = mock.Mock() + _relation.relation_id = 0 + _relation.units = [] + _relation.to_publish = {} + + def test_publish_info(self): + self.maxDiff = None + self.patch_object(provides, 'ch_core') + self.ch_core.hookenv.unit_get.return_value = '172.16.122.251' + self.ch_core.hookenv.network_get.side_effect = \ + self._network_get_side_effect + endpoint = provides.BGPEndpoint('bgpserver') + endpoint._relations = [self._relation] + endpoint.publish_info(bindings=['ptp0', 'ptp1', 'ptp2', 'ptp3', + 'lan0']) + self.assertEqual( + endpoint.relations[0].to_publish, + { + 'asn': 4279270138, + 'bindings': [ + { + 'address': '172.16.100.1', + 'cidr': '172.16.100.0/30' + }, + { + 'address': '2001:db8:100::1:0:0', + 'cidr': '2001:db8:100::/64' + }, + { + 'address': '172.16.110.1', + 'cidr': '172.16.110.0/30' + }, + { + 'address': '2001:db8:110::1:0:0', + 'cidr': '2001:db8:110::/64' + }, + { + 'address': '172.16.120.1', + 'cidr': '172.16.120.0/30' + }, + { + 'address': '2001:db8:120::1:0:0', + 'cidr': '2001:db8:120::/64' + }, + ], + 'passive': False, + } + ) + + def test_get_received_info(self): + self.maxDiff = None + self.patch_object(provides, 'ch_core') + self.patch_object(provides, 'ch_net_ip') + self.ch_core.hookenv.unit_get.return_value = '172.16.122.251' + self.ch_core.hookenv.network_get.side_effect = \ + self._network_get_side_effect + endpoint = provides.BGPEndpoint('bgpserver') + endpoint._relations = [self._relation] + endpoint.publish_info(bindings=['ptp0', 'ptp1', 'ptp2', 'ptp3', + 'lan0']) + _unit = mock.Mock() + _unit.unit_name = None + _unit.received = endpoint.relations[0].to_publish + endpoint._relations[0].units.append(_unit) + neighbors = endpoint.get_received_info() + self.assertEqual(neighbors, [ + { + 'remote_unit_name': None, + 'links': [ + { + 'cidr': '172.16.100.0/30', + 'local': self.ch_net_ip.get_address_in_network( + '172.16.100.0/30' + ), + 'remote': '172.16.100.1' + }, + { + 'cidr': '2001:db8:100::/64', + 'local': self.ch_net_ip.get_address_in_network( + '2001:db8:100::/64' + ), + 'remote': '2001:db8:100::1:0:0' + }, + { + 'cidr': '172.16.110.0/30', + 'local': self.ch_net_ip.get_address_in_network( + '172.16.110.0/30' + ), + 'remote': '172.16.110.1' + }, + { + 'cidr': '2001:db8:110::/64', + 'local': self.ch_net_ip.get_address_in_network( + '2001:db8:110::/64' + ), + 'remote': '2001:db8:110::1:0:0' + }, + { + 'cidr': '172.16.120.0/30', + 'local': self.ch_net_ip.get_address_in_network( + '172.16.120.0/30' + ), + 'remote': '172.16.120.1' + }, + { + 'cidr': '2001:db8:120::/64', + 'local': self.ch_net_ip.get_address_in_network( + '2001:db8:120::/64' + ), + 'remote': '2001:db8:120::1:0:0' + }, + ], + 'passive': False, + 'asn': 4279270138, + 'relation_id': 0, + }, + ] + )