b200d368cd
This patch adds support for Network Policy on services. It applies pods' security groups onto the services in front of them. It makes the next assumptions: - All the pods pointed by one svc have the same labels, thus the same sgs being enforced - Only copies the SG rules that have the same protocol and direction as the listener being created - Adds a default rule to NP to enable traffic from services subnet CIDR Partially Implements: blueprint k8s-network-policies Change-Id: Ibd4b51ff40b69af26ab7e7b81d18e63abddf775b
980 lines
41 KiB
Python
980 lines
41 KiB
Python
# Copyright (c) 2016 Mirantis, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, 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 itertools
|
|
import mock
|
|
import uuid
|
|
|
|
import os_vif.objects.network as osv_network
|
|
import os_vif.objects.subnet as osv_subnet
|
|
|
|
from kuryr_kubernetes import constants as k_const
|
|
from kuryr_kubernetes.controller.drivers import base as drv_base
|
|
from kuryr_kubernetes.controller.handlers import lbaas as h_lbaas
|
|
from kuryr_kubernetes import exceptions as k_exc
|
|
from kuryr_kubernetes.objects import lbaas as obj_lbaas
|
|
from kuryr_kubernetes.tests import base as test_base
|
|
|
|
_SUPPORTED_LISTENER_PROT = ('HTTP', 'HTTPS', 'TCP')
|
|
|
|
|
|
class TestLBaaSSpecHandler(test_base.TestCase):
|
|
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.ServiceSecurityGroupsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.ServiceSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.ServiceProjectDriver.get_instance')
|
|
def test_init(self, m_get_drv_project, m_get_drv_subnets, m_get_drv_sg):
|
|
m_get_drv_project.return_value = mock.sentinel.drv_project
|
|
m_get_drv_subnets.return_value = mock.sentinel.drv_subnets
|
|
m_get_drv_sg.return_value = mock.sentinel.drv_sg
|
|
handler = h_lbaas.LBaaSSpecHandler()
|
|
|
|
self.assertEqual(mock.sentinel.drv_project, handler._drv_project)
|
|
self.assertEqual(mock.sentinel.drv_subnets, handler._drv_subnets)
|
|
self.assertEqual(mock.sentinel.drv_sg, handler._drv_sg)
|
|
|
|
def test_on_present(self):
|
|
svc_event = mock.sentinel.svc_event
|
|
old_spec = mock.sentinel.old_spec
|
|
new_spec = mock.sentinel.new_spec
|
|
|
|
project_id = mock.sentinel.project_id
|
|
m_drv_project = mock.Mock()
|
|
m_drv_project.get_project.return_value = project_id
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_handler._get_lbaas_spec.return_value = old_spec
|
|
m_handler._has_lbaas_spec_changes.return_value = True
|
|
m_handler._generate_lbaas_spec.return_value = new_spec
|
|
m_handler._should_ignore.return_value = False
|
|
m_handler._drv_project = m_drv_project
|
|
|
|
h_lbaas.LBaaSSpecHandler.on_present(m_handler, svc_event)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(svc_event)
|
|
m_handler._has_lbaas_spec_changes.assert_called_once_with(svc_event,
|
|
old_spec)
|
|
m_handler._generate_lbaas_spec.assert_called_once_with(svc_event)
|
|
m_handler._set_lbaas_spec.assert_called_once_with(svc_event, new_spec)
|
|
|
|
def test_on_present_no_changes(self):
|
|
svc_event = mock.sentinel.svc_event
|
|
old_spec = mock.sentinel.old_spec
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_handler._get_lbaas_spec.return_value = old_spec
|
|
m_handler._has_lbaas_spec_changes.return_value = False
|
|
m_handler._should_ignore.return_value = False
|
|
|
|
h_lbaas.LBaaSSpecHandler.on_present(m_handler, svc_event)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(svc_event)
|
|
m_handler._has_lbaas_spec_changes.assert_called_once_with(svc_event,
|
|
old_spec)
|
|
m_handler._generate_lbaas_spec.assert_not_called()
|
|
m_handler._set_lbaas_spec.assert_not_called()
|
|
|
|
def test_on_present_no_selector(self):
|
|
svc_event = {'metadata': {'name': 'dummy_name'}}
|
|
old_spec = mock.sentinel.old_spec
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_handler._get_lbaas_spec.return_value = old_spec
|
|
m_handler._should_ignore.return_value = True
|
|
|
|
h_lbaas.LBaaSSpecHandler.on_present(m_handler, svc_event)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(svc_event)
|
|
m_handler._has_lbaas_spec_changes.assert_not_called()
|
|
m_handler._generate_lbaas_spec.assert_not_called()
|
|
m_handler._set_lbaas_spec.assert_not_called()
|
|
|
|
def test_get_service_ip(self):
|
|
svc_body = {'spec': {'type': 'ClusterIP',
|
|
'clusterIP': mock.sentinel.cluster_ip}}
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._get_service_ip(m_handler, svc_body)
|
|
self.assertEqual(mock.sentinel.cluster_ip, ret)
|
|
|
|
svc_body = {'spec': {'type': 'LoadBalancer',
|
|
'clusterIP': mock.sentinel.cluster_ip}}
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._get_service_ip(m_handler, svc_body)
|
|
self.assertEqual(mock.sentinel.cluster_ip, ret)
|
|
|
|
def test_is_supported_type_clusterip(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
svc_body = {'spec': {'type': 'ClusterIP',
|
|
'clusterIP': mock.sentinel.cluster_ip}}
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._is_supported_type(m_handler, svc_body)
|
|
self.assertEqual(ret, True)
|
|
|
|
def test_is_supported_type_loadbalancer(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
svc_body = {'spec': {'type': 'LoadBalancer',
|
|
'clusterIP': mock.sentinel.cluster_ip}}
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._is_supported_type(m_handler, svc_body)
|
|
self.assertEqual(ret, True)
|
|
|
|
def _make_test_net_obj(self, cidr_list):
|
|
subnets = [osv_subnet.Subnet(cidr=cidr) for cidr in cidr_list]
|
|
subnets_list = osv_subnet.SubnetList(objects=subnets)
|
|
return osv_network.Network(subnets=subnets_list)
|
|
|
|
def test_generate_lbaas_spec(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
|
|
service = mock.sentinel.service
|
|
project_id = mock.sentinel.project_id
|
|
ip = mock.sentinel.ip
|
|
subnet_id = mock.sentinel.subnet_id
|
|
ports = mock.sentinel.ports
|
|
sg_ids = mock.sentinel.sg_ids
|
|
|
|
m_drv_project = mock.Mock()
|
|
m_drv_project.get_project.return_value = project_id
|
|
m_drv_sg = mock.Mock()
|
|
m_drv_sg.get_security_groups.return_value = sg_ids
|
|
m_handler._drv_project = m_drv_project
|
|
m_handler._drv_sg = m_drv_sg
|
|
m_handler._get_service_ip.return_value = ip
|
|
m_handler._get_subnet_id.return_value = subnet_id
|
|
m_handler._generate_lbaas_port_specs.return_value = ports
|
|
|
|
spec_ctor_path = 'kuryr_kubernetes.objects.lbaas.LBaaSServiceSpec'
|
|
with mock.patch(spec_ctor_path) as m_spec_ctor:
|
|
m_spec_ctor.return_value = mock.sentinel.ret_obj
|
|
service = {'spec': {'type': 'ClusterIP'}}
|
|
|
|
ret_obj = h_lbaas.LBaaSSpecHandler._generate_lbaas_spec(
|
|
m_handler, service)
|
|
self.assertEqual(mock.sentinel.ret_obj, ret_obj)
|
|
m_spec_ctor.assert_called_once_with(
|
|
ip=ip,
|
|
project_id=project_id,
|
|
subnet_id=subnet_id,
|
|
ports=ports,
|
|
security_groups_ids=sg_ids,
|
|
type='ClusterIP',
|
|
lb_ip=None)
|
|
|
|
m_drv_project.get_project.assert_called_once_with(service)
|
|
m_handler._get_service_ip.assert_called_once_with(service)
|
|
m_handler._get_subnet_id.assert_called_once_with(
|
|
service, project_id, ip)
|
|
m_handler._generate_lbaas_port_specs.assert_called_once_with(service)
|
|
m_drv_sg.get_security_groups.assert_called_once_with(
|
|
service, project_id)
|
|
|
|
def test_has_lbaas_spec_changes(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
service = mock.sentinel.service
|
|
lbaas_spec = mock.sentinel.lbaas_spec
|
|
|
|
for has_ip_changes in (True, False):
|
|
for has_port_changes in (True, False):
|
|
m_handler._has_ip_changes.return_value = has_ip_changes
|
|
m_handler._has_port_changes.return_value = has_port_changes
|
|
ret = h_lbaas.LBaaSSpecHandler._has_lbaas_spec_changes(
|
|
m_handler, service, lbaas_spec)
|
|
self.assertEqual(has_ip_changes or has_port_changes, ret)
|
|
|
|
def test_get_service_ports(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
service = {'spec': {'ports': [
|
|
{'port': 1},
|
|
{'port': 2, 'name': 'X', 'protocol': 'UDP'}
|
|
]}}
|
|
expected_ret = [
|
|
{'port': 1, 'name': None, 'protocol': 'TCP'},
|
|
{'port': 2, 'name': 'X', 'protocol': 'UDP'}]
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._get_service_ports(m_handler, service)
|
|
self.assertEqual(expected_ret, ret)
|
|
|
|
def test_has_port_changes(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ports.return_value = [
|
|
{'port': 1, 'name': 'X', 'protocol': 'TCP'},
|
|
]
|
|
|
|
m_lbaas_spec = mock.MagicMock()
|
|
m_lbaas_spec.ports = [
|
|
obj_lbaas.LBaaSPortSpec(name='X', protocol='TCP', port=1),
|
|
obj_lbaas.LBaaSPortSpec(name='Y', protocol='TCP', port=2),
|
|
]
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_port_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
|
|
self.assertTrue(ret)
|
|
|
|
def test_has_port_changes__no_changes(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ports.return_value = [
|
|
{'port': 1, 'name': 'X', 'protocol': 'TCP'},
|
|
{'port': 2, 'name': 'Y', 'protocol': 'TCP'}
|
|
]
|
|
|
|
m_lbaas_spec = mock.MagicMock()
|
|
m_lbaas_spec.ports = [
|
|
obj_lbaas.LBaaSPortSpec(name='X', protocol='TCP', port=1),
|
|
obj_lbaas.LBaaSPortSpec(name='Y', protocol='TCP', port=2),
|
|
]
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_port_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
|
|
self.assertFalse(ret)
|
|
|
|
def test_has_ip_changes(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ip.return_value = '1.1.1.1'
|
|
m_lbaas_spec = mock.MagicMock()
|
|
m_lbaas_spec.ip.__str__.return_value = '2.2.2.2'
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_ip_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
self.assertTrue(ret)
|
|
|
|
def test_has_ip_changes__no_changes(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ip.return_value = '1.1.1.1'
|
|
m_lbaas_spec = mock.MagicMock()
|
|
m_lbaas_spec.ip.__str__.return_value = '1.1.1.1'
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_ip_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
self.assertFalse(ret)
|
|
|
|
def test_has_ip_changes__no_spec(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ip.return_value = '1.1.1.1'
|
|
m_lbaas_spec = None
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_ip_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
self.assertTrue(ret)
|
|
|
|
def test_has_ip_changes__no_nothing(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_service = mock.MagicMock()
|
|
m_handler._get_service_ip.return_value = None
|
|
m_lbaas_spec = None
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._has_ip_changes(
|
|
m_handler, m_service, m_lbaas_spec)
|
|
self.assertFalse(ret)
|
|
|
|
def test_generate_lbaas_port_specs(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_handler._get_service_ports.return_value = [
|
|
{'port': 1, 'name': 'X', 'protocol': 'TCP'},
|
|
{'port': 2, 'name': 'Y', 'protocol': 'TCP'}
|
|
]
|
|
expected_ports = [
|
|
obj_lbaas.LBaaSPortSpec(name='X', protocol='TCP', port=1),
|
|
obj_lbaas.LBaaSPortSpec(name='Y', protocol='TCP', port=2),
|
|
]
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._generate_lbaas_port_specs(
|
|
m_handler, mock.sentinel.service)
|
|
self.assertEqual(expected_ports, ret)
|
|
m_handler._get_service_ports.assert_called_once_with(
|
|
mock.sentinel.service)
|
|
|
|
def test_generate_lbaas_port_specs_udp(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
m_handler._get_service_ports.return_value = [
|
|
{'port': 1, 'name': 'X', 'protocol': 'TCP'},
|
|
{'port': 2, 'name': 'Y', 'protocol': 'UDP'}
|
|
]
|
|
expected_ports = [
|
|
obj_lbaas.LBaaSPortSpec(name='X', protocol='TCP', port=1),
|
|
obj_lbaas.LBaaSPortSpec(name='Y', protocol='UDP', port=2),
|
|
]
|
|
|
|
ret = h_lbaas.LBaaSSpecHandler._generate_lbaas_port_specs(
|
|
m_handler, mock.sentinel.service)
|
|
self.assertEqual(expected_ports, ret)
|
|
m_handler._get_service_ports.assert_called_once_with(
|
|
mock.sentinel.service)
|
|
|
|
def test_get_endpoints_link(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
service = {'metadata': {
|
|
'selfLink': "/api/v1/namespaces/default/services/test"}}
|
|
ret = h_lbaas.LBaaSSpecHandler._get_endpoints_link(m_handler, service)
|
|
expected_link = "/api/v1/namespaces/default/endpoints/test"
|
|
self.assertEqual(expected_link, ret)
|
|
|
|
def test_get_endpoints_link__integrity_error(self):
|
|
m_handler = mock.Mock(spec=h_lbaas.LBaaSSpecHandler)
|
|
service = {'metadata': {
|
|
'selfLink': "/api/v1/namespaces/default/not-services/test"}}
|
|
self.assertRaises(k_exc.IntegrityError,
|
|
h_lbaas.LBaaSSpecHandler._get_endpoints_link,
|
|
m_handler, service)
|
|
|
|
def test_set_lbaas_spec(self):
|
|
self.skipTest("skipping until generalised annotation handling is "
|
|
"implemented")
|
|
|
|
def test_get_lbaas_spec(self):
|
|
self.skipTest("skipping until generalised annotation handling is "
|
|
"implemented")
|
|
|
|
|
|
class FakeLBaaSDriver(drv_base.LBaaSDriver):
|
|
|
|
def ensure_loadbalancer(self, name, project_id, subnet_id, ip,
|
|
security_groups_ids, service_type, provider=None):
|
|
return obj_lbaas.LBaaSLoadBalancer(name=name,
|
|
project_id=project_id,
|
|
subnet_id=subnet_id,
|
|
ip=ip,
|
|
id=str(uuid.uuid4()),
|
|
provider=provider)
|
|
|
|
def ensure_listener(self, loadbalancer, protocol, port,
|
|
service_type='ClusterIP'):
|
|
if protocol not in _SUPPORTED_LISTENER_PROT:
|
|
return None
|
|
|
|
name = "%s:%s:%s" % (loadbalancer.name, protocol, port)
|
|
return obj_lbaas.LBaaSListener(name=name,
|
|
project_id=loadbalancer.project_id,
|
|
loadbalancer_id=loadbalancer.id,
|
|
protocol=protocol,
|
|
port=port,
|
|
id=str(uuid.uuid4()))
|
|
|
|
def ensure_pool(self, loadbalancer, listener):
|
|
return obj_lbaas.LBaaSPool(name=listener.name,
|
|
project_id=loadbalancer.project_id,
|
|
loadbalancer_id=loadbalancer.id,
|
|
listener_id=listener.id,
|
|
protocol=listener.protocol,
|
|
id=str(uuid.uuid4()))
|
|
|
|
def ensure_member(self, loadbalancer, pool, subnet_id, ip, port,
|
|
target_ref_namespace, target_ref_name, listener_port=None
|
|
):
|
|
name = "%s:%s:%s" % (loadbalancer.name, ip, port)
|
|
return obj_lbaas.LBaaSMember(name=name,
|
|
project_id=pool.project_id,
|
|
pool_id=pool.id,
|
|
subnet_id=subnet_id,
|
|
ip=ip,
|
|
port=port,
|
|
id=str(uuid.uuid4()))
|
|
|
|
def release_loadbalancer(self, loadbalancer):
|
|
pass
|
|
|
|
def release_listener(self, loadbalancer, listener):
|
|
pass
|
|
|
|
def release_pool(self, loadbalancer, pool):
|
|
pass
|
|
|
|
def release_member(self, loadbalancer, member):
|
|
pass
|
|
|
|
def get_service_loadbalancer_name(self, namespace, svc_name):
|
|
return "%s/%s" % (namespace, svc_name)
|
|
|
|
def get_loadbalancer_pool_name(self, lb_name, namespace, svc_name):
|
|
return "%s/%s/%s" % (lb_name, namespace, svc_name)
|
|
|
|
def ensure_l7_policy(self, namespace, route_name,
|
|
loadbalancer, pool,
|
|
listener_id):
|
|
pass
|
|
|
|
def release_l7_policy(self, loadbalancer, l7_policy):
|
|
pass
|
|
|
|
def ensure_l7_rule(self, loadbalancer, l7_policy, compare_type,
|
|
type, value):
|
|
pass
|
|
|
|
def release_l7_rule(self, loadbalancer, l7_rule):
|
|
pass
|
|
|
|
def update_l7_rule(self, l7_rule, new_value):
|
|
pass
|
|
|
|
def ensure_pool_attached_to_lb(self, loadbalancer, namespace,
|
|
svc_name, protocol):
|
|
return obj_lbaas.LBaaSPool(id=str(uuid.uuid4()),
|
|
loadbalancer_id=loadbalancer.id,
|
|
project_id=loadbalancer.project_id,
|
|
protocol=protocol)
|
|
|
|
def get_pool_by_name(self, pool_name, project_id):
|
|
pass
|
|
|
|
def get_lb_by_uuid(self, vip):
|
|
pass
|
|
|
|
def is_pool_used_by_other_l7policies(l7policy, pool):
|
|
pass
|
|
|
|
|
|
class TestLoadBalancerHandler(test_base.TestCase):
|
|
@mock.patch('kuryr_kubernetes.config.CONF')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.ServicePubIpDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_init(self, m_get_drv_lbaas, m_get_drv_project,
|
|
m_get_drv_subnets, m_get_drv_service_pub_ip, m_cfg):
|
|
m_get_drv_lbaas.return_value = mock.sentinel.drv_lbaas
|
|
m_get_drv_project.return_value = mock.sentinel.drv_project
|
|
m_get_drv_subnets.return_value = mock.sentinel.drv_subnets
|
|
m_get_drv_service_pub_ip.return_value = mock.sentinel.drv_lb_ip
|
|
m_cfg.kubernetes.endpoints_driver_octavia_provider = 'default'
|
|
handler = h_lbaas.LoadBalancerHandler()
|
|
|
|
self.assertEqual(mock.sentinel.drv_lbaas, handler._drv_lbaas)
|
|
self.assertEqual(mock.sentinel.drv_project, handler._drv_pod_project)
|
|
self.assertEqual(mock.sentinel.drv_subnets, handler._drv_pod_subnets)
|
|
self.assertEqual(mock.sentinel.drv_lb_ip, handler._drv_service_pub_ip)
|
|
self.assertIsNone(handler._lb_provider)
|
|
|
|
@mock.patch('kuryr_kubernetes.config.CONF')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.ServicePubIpDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_init_provider_ovn(self, m_get_drv_lbaas, m_get_drv_project,
|
|
m_get_drv_subnets, m_get_drv_service_pub_ip,
|
|
m_cfg):
|
|
m_get_drv_lbaas.return_value = mock.sentinel.drv_lbaas
|
|
m_get_drv_project.return_value = mock.sentinel.drv_project
|
|
m_get_drv_subnets.return_value = mock.sentinel.drv_subnets
|
|
m_get_drv_service_pub_ip.return_value = mock.sentinel.drv_lb_ip
|
|
m_cfg.kubernetes.endpoints_driver_octavia_provider = 'ovn'
|
|
handler = h_lbaas.LoadBalancerHandler()
|
|
|
|
self.assertEqual(mock.sentinel.drv_lbaas, handler._drv_lbaas)
|
|
self.assertEqual(mock.sentinel.drv_project, handler._drv_pod_project)
|
|
self.assertEqual(mock.sentinel.drv_subnets, handler._drv_pod_subnets)
|
|
self.assertEqual(mock.sentinel.drv_lb_ip, handler._drv_service_pub_ip)
|
|
self.assertEqual('ovn', handler._lb_provider)
|
|
|
|
def test_on_present(self):
|
|
lbaas_spec = mock.sentinel.lbaas_spec
|
|
lbaas_spec.type = 'DummyType'
|
|
lbaas_spec.lb_ip = "1.2.3.4"
|
|
lbaas_spec.project_id = 12345678
|
|
|
|
lbaas_state = mock.sentinel.lbaas_state
|
|
lbaas_state.service_pub_ip_info = None
|
|
loadbalancer = mock.Mock()
|
|
loadbalancer.port_id = 12345678
|
|
lbaas_state.loadbalancer = loadbalancer
|
|
endpoints = mock.sentinel.endpoints
|
|
|
|
m_drv_service_pub_ip = mock.Mock()
|
|
m_drv_service_pub_ip.acquire_service_pub_ip_info.return_value = None
|
|
m_drv_service_pub_ip.associate_pub_ip.return_value = True
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._get_lbaas_spec.return_value = lbaas_spec
|
|
m_handler._should_ignore.return_value = False
|
|
m_handler._get_lbaas_state.return_value = lbaas_state
|
|
m_handler._sync_lbaas_members.return_value = True
|
|
m_handler._drv_service_pub_ip = m_drv_service_pub_ip
|
|
|
|
h_lbaas.LoadBalancerHandler.on_present(m_handler, endpoints)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(endpoints)
|
|
m_handler._should_ignore.assert_called_once_with(endpoints, lbaas_spec)
|
|
m_handler._get_lbaas_state.assert_called_once_with(endpoints)
|
|
m_handler._sync_lbaas_members.assert_called_once_with(
|
|
endpoints, lbaas_state, lbaas_spec)
|
|
m_handler._set_lbaas_state.assert_called_once_with(
|
|
endpoints, lbaas_state)
|
|
m_handler._update_lb_status.assert_not_called()
|
|
|
|
def _fake_sync_lbaas_members(self, endpoints, lbaas_state, lbaas_spec):
|
|
loadbalancer = mock.Mock()
|
|
loadbalancer.port_id = 12345678
|
|
lbaas_state.loadbalancer = loadbalancer
|
|
lbaas_state.service_pub_ip_info = None
|
|
return True
|
|
|
|
def test_on_present_loadbalancer_service(self):
|
|
lbaas_spec = mock.sentinel.lbaas_spec
|
|
lbaas_spec.type = 'LoadBalancer'
|
|
lbaas_spec.lb_ip = "1.2.3.4"
|
|
lbaas_spec.project_id = 12345678
|
|
|
|
lbaas_state = mock.sentinel.lbaas_state
|
|
lbaas_state.service_pub_ip_info = None
|
|
endpoints = mock.sentinel.endpoints
|
|
|
|
floating_ip = {'floating_ip_address': '1.2.3.5',
|
|
'id': 'ec29d641-fec4-4f67-928a-124a76b3a888'}
|
|
|
|
service_pub_ip_info = obj_lbaas.LBaaSPubIp(
|
|
ip_id=floating_ip['id'],
|
|
ip_addr=floating_ip['floating_ip_address'], alloc_method='kk')
|
|
|
|
m_drv_service_pub_ip = mock.Mock()
|
|
m_drv_service_pub_ip.acquire_service_pub_ip_info.return_value = (
|
|
service_pub_ip_info)
|
|
m_drv_service_pub_ip.associate_pub_ip.return_value = True
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._get_lbaas_spec.return_value = lbaas_spec
|
|
m_handler._should_ignore.return_value = False
|
|
m_handler._get_lbaas_state.return_value = lbaas_state
|
|
m_handler._sync_lbaas_members = self._fake_sync_lbaas_members
|
|
m_handler._drv_service_pub_ip = m_drv_service_pub_ip
|
|
|
|
h_lbaas.LoadBalancerHandler.on_present(m_handler, endpoints)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(endpoints)
|
|
m_handler._should_ignore.assert_called_once_with(endpoints, lbaas_spec)
|
|
m_handler._get_lbaas_state.assert_called_once_with(endpoints)
|
|
m_handler._set_lbaas_state.assert_called_once_with(
|
|
endpoints, lbaas_state)
|
|
m_handler._update_lb_status.assert_called()
|
|
|
|
def test_on_present_rollback(self):
|
|
lbaas_spec = mock.sentinel.lbaas_spec
|
|
lbaas_spec.type = 'ClusterIp'
|
|
lbaas_spec.lb_ip = '1.2.3.4'
|
|
lbaas_spec.project_id = '12345678'
|
|
lbaas_state = mock.sentinel.lbaas_state
|
|
lbaas_state.service_pub_ip_info = None
|
|
loadbalancer = mock.Mock()
|
|
loadbalancer.port_id = 12345678
|
|
lbaas_state.loadbalancer = loadbalancer
|
|
m_drv_service_pub_ip = mock.Mock()
|
|
m_drv_service_pub_ip.acquire_service_pub_ip_info.return_value = None
|
|
m_drv_service_pub_ip.associate_pub_ip.return_value = True
|
|
|
|
endpoints = mock.sentinel.endpoints
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._get_lbaas_spec.return_value = lbaas_spec
|
|
m_handler._should_ignore.return_value = False
|
|
m_handler._get_lbaas_state.return_value = lbaas_state
|
|
m_handler._sync_lbaas_members.return_value = True
|
|
m_handler._set_lbaas_state.side_effect = (
|
|
k_exc.K8sResourceNotFound('ep'))
|
|
m_handler._drv_service_pub_ip = m_drv_service_pub_ip
|
|
h_lbaas.LoadBalancerHandler.on_present(m_handler, endpoints)
|
|
|
|
m_handler._get_lbaas_spec.assert_called_once_with(endpoints)
|
|
m_handler._should_ignore.assert_called_once_with(endpoints, lbaas_spec)
|
|
m_handler._get_lbaas_state.assert_called_once_with(endpoints)
|
|
m_handler._sync_lbaas_members.assert_called_once_with(
|
|
endpoints, lbaas_state, lbaas_spec)
|
|
m_handler._set_lbaas_state.assert_called_once_with(
|
|
endpoints, lbaas_state)
|
|
m_handler.on_deleted.assert_called_once_with(
|
|
endpoints, lbaas_state)
|
|
|
|
@mock.patch('kuryr_kubernetes.objects.lbaas'
|
|
'.LBaaSServiceSpec')
|
|
def test_on_deleted(self, m_svc_spec_ctor):
|
|
endpoints = mock.sentinel.endpoints
|
|
empty_spec = mock.sentinel.empty_spec
|
|
lbaas_state = mock.sentinel.lbaas_state
|
|
m_svc_spec_ctor.return_value = empty_spec
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._get_lbaas_state.return_value = lbaas_state
|
|
m_handler._drv_lbaas = mock.Mock()
|
|
m_handler._drv_lbaas.cascading_capable = False
|
|
|
|
h_lbaas.LoadBalancerHandler.on_deleted(m_handler, endpoints)
|
|
|
|
m_handler._get_lbaas_state.assert_called_once_with(endpoints)
|
|
m_handler._sync_lbaas_members.assert_called_once_with(
|
|
endpoints, lbaas_state, empty_spec)
|
|
|
|
@mock.patch('kuryr_kubernetes.objects.lbaas'
|
|
'.LBaaSServiceSpec')
|
|
def test_on_cascade_deleted_lb_service(self, m_svc_spec_ctor):
|
|
endpoints = mock.sentinel.endpoints
|
|
empty_spec = mock.sentinel.empty_spec
|
|
lbaas_state = mock.Mock()
|
|
lbaas_state.loadbalancer = mock.sentinel.loadbalancer
|
|
lbaas_state.service_pub_ip_info = mock.sentinel.pub_ip
|
|
m_svc_spec_ctor.return_value = empty_spec
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._get_lbaas_state.return_value = lbaas_state
|
|
m_handler._drv_lbaas = mock.Mock()
|
|
m_handler._drv_service_pub_ip = mock.Mock()
|
|
m_handler._drv_lbaas.cascading_capable = True
|
|
|
|
h_lbaas.LoadBalancerHandler.on_deleted(m_handler, endpoints)
|
|
|
|
m_handler._drv_lbaas.release_loadbalancer.assert_called_once_with(
|
|
loadbalancer=lbaas_state.loadbalancer)
|
|
m_handler._drv_service_pub_ip.release_pub_ip.assert_called_once_with(
|
|
lbaas_state.service_pub_ip_info)
|
|
|
|
def test_should_ignore(self):
|
|
endpoints = mock.sentinel.endpoints
|
|
lbaas_spec = mock.sentinel.lbaas_spec
|
|
|
|
# REVISIT(ivc): ddt?
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_handler._has_pods.return_value = True
|
|
m_handler._is_lbaas_spec_in_sync.return_value = True
|
|
|
|
ret = h_lbaas.LoadBalancerHandler._should_ignore(
|
|
m_handler, endpoints, lbaas_spec)
|
|
self.assertEqual(False, ret)
|
|
|
|
m_handler._has_pods.assert_called_once_with(endpoints)
|
|
m_handler._is_lbaas_spec_in_sync.assert_called_once_with(
|
|
endpoints, lbaas_spec)
|
|
|
|
def test_is_lbaas_spec_in_sync(self):
|
|
names = ['a', 'b', 'c']
|
|
endpoints = {'subsets': [{'ports': [{'name': n} for n in names]}]}
|
|
lbaas_spec = obj_lbaas.LBaaSServiceSpec(ports=[
|
|
obj_lbaas.LBaaSPortSpec(name=n) for n in reversed(names)])
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
ret = h_lbaas.LoadBalancerHandler._is_lbaas_spec_in_sync(
|
|
m_handler, endpoints, lbaas_spec)
|
|
|
|
self.assertEqual(True, ret)
|
|
|
|
def test_has_pods(self):
|
|
# REVISIT(ivc): ddt?
|
|
endpoints = {'subsets': [
|
|
{},
|
|
{'addresses': []},
|
|
{'addresses': [{'targetRef': {}}]},
|
|
{'addresses': [{'targetRef': {'kind': k_const.K8S_OBJ_POD}}]}
|
|
]}
|
|
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
|
|
ret = h_lbaas.LoadBalancerHandler._has_pods(m_handler, endpoints)
|
|
|
|
self.assertEqual(True, ret)
|
|
|
|
def test_get_pod_subnet(self):
|
|
subnet_id = mock.sentinel.subnet_id
|
|
project_id = mock.sentinel.project_id
|
|
target_ref = {'kind': k_const.K8S_OBJ_POD,
|
|
'name': 'pod-name',
|
|
'namespace': 'default'}
|
|
ip = '1.2.3.4'
|
|
m_handler = mock.Mock(spec=h_lbaas.LoadBalancerHandler)
|
|
m_drv_pod_project = mock.Mock()
|
|
m_drv_pod_project.get_project.return_value = project_id
|
|
m_handler._drv_pod_project = m_drv_pod_project
|
|
m_drv_pod_subnets = mock.Mock()
|
|
m_drv_pod_subnets.get_subnets.return_value = {
|
|
subnet_id: osv_network.Network(subnets=osv_subnet.SubnetList(
|
|
objects=[osv_subnet.Subnet(cidr='1.2.3.0/24')]))}
|
|
m_handler._drv_pod_subnets = m_drv_pod_subnets
|
|
|
|
observed_subnet_id = h_lbaas.LoadBalancerHandler._get_pod_subnet(
|
|
m_handler, target_ref, ip)
|
|
|
|
self.assertEqual(subnet_id, observed_subnet_id)
|
|
|
|
def _generate_lbaas_state(self, vip, targets, project_id, subnet_id):
|
|
name = 'DUMMY_NAME'
|
|
drv = FakeLBaaSDriver()
|
|
lb = drv.ensure_loadbalancer(
|
|
name, project_id, subnet_id, vip, None, 'ClusterIP')
|
|
listeners = {}
|
|
pools = {}
|
|
members = {}
|
|
for ip, (listen_port, target_port) in targets.items():
|
|
lsnr = listeners.setdefault(listen_port, drv.ensure_listener(
|
|
lb, 'TCP', listen_port))
|
|
pool = pools.setdefault(listen_port, drv.ensure_pool(lb, lsnr))
|
|
members.setdefault((ip, listen_port, target_port),
|
|
drv.ensure_member(lb, pool,
|
|
subnet_id, ip,
|
|
target_port, None, None))
|
|
return obj_lbaas.LBaaSState(
|
|
loadbalancer=lb,
|
|
listeners=list(listeners.values()),
|
|
pools=list(pools.values()),
|
|
members=list(members.values()))
|
|
|
|
def _generate_lbaas_spec(self, vip, targets, project_id,
|
|
subnet_id, prot='TCP', lbaas_type='ClusterIP'):
|
|
return obj_lbaas.LBaaSServiceSpec(
|
|
ip=vip,
|
|
project_id=project_id,
|
|
subnet_id=subnet_id,
|
|
ports=[obj_lbaas.LBaaSPortSpec(name=str(port),
|
|
protocol=prot,
|
|
port=port)
|
|
for port in set(t[0] for t in targets.values())],
|
|
type=lbaas_type)
|
|
|
|
def _generate_endpoints(self, targets):
|
|
def _target_to_port(item):
|
|
_, (listen_port, target_port) = item
|
|
return {'port': target_port, 'name': str(listen_port)}
|
|
port_with_addrs = [
|
|
(p, [e[0] for e in grp])
|
|
for p, grp in itertools.groupby(
|
|
sorted(targets.items()), _target_to_port)]
|
|
return {
|
|
'metadata': {
|
|
'name': 'ep_name',
|
|
'namespace': 'default'
|
|
},
|
|
'subsets': [
|
|
{
|
|
'addresses': [
|
|
{
|
|
'ip': ip,
|
|
'targetRef': {
|
|
'kind': k_const.K8S_OBJ_POD,
|
|
'name': ip,
|
|
'namespace': 'default'
|
|
}
|
|
}
|
|
for ip in addrs
|
|
],
|
|
'ports': [port]
|
|
}
|
|
for port, addrs in port_with_addrs
|
|
]
|
|
}
|
|
|
|
def _sync_lbaas_members_impl(self, m_get_drv_lbaas, m_get_drv_project,
|
|
m_get_drv_subnets, subnet_id, project_id,
|
|
endpoints, state, spec):
|
|
m_drv_lbaas = mock.Mock(wraps=FakeLBaaSDriver())
|
|
m_drv_project = mock.Mock()
|
|
m_drv_project.get_project.return_value = project_id
|
|
m_drv_subnets = mock.Mock()
|
|
m_drv_subnets.get_subnets.return_value = {
|
|
subnet_id: mock.sentinel.subnet}
|
|
m_get_drv_lbaas.return_value = m_drv_lbaas
|
|
m_get_drv_project.return_value = m_drv_project
|
|
m_get_drv_subnets.return_value = m_drv_subnets
|
|
|
|
handler = h_lbaas.LoadBalancerHandler()
|
|
|
|
with mock.patch.object(handler, '_get_pod_subnet') as m_get_pod_subnet:
|
|
m_get_pod_subnet.return_value = subnet_id
|
|
handler._sync_lbaas_members(endpoints, state, spec)
|
|
|
|
lsnrs = {lsnr.id: lsnr for lsnr in state.listeners}
|
|
pools = {pool.id: pool for pool in state.pools}
|
|
observed_targets = sorted(
|
|
(str(member.ip), (
|
|
lsnrs[pools[member.pool_id].listener_id].port,
|
|
member.port))
|
|
for member in state.members)
|
|
return observed_targets
|
|
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_sync_lbaas_members(self, m_get_drv_lbaas, m_get_drv_project,
|
|
m_get_drv_subnets):
|
|
# REVISIT(ivc): test methods separately and verify ensure/release
|
|
project_id = str(uuid.uuid4())
|
|
subnet_id = str(uuid.uuid4())
|
|
current_ip = '1.1.1.1'
|
|
current_targets = {
|
|
'1.1.1.101': (1001, 10001),
|
|
'1.1.1.111': (1001, 10001),
|
|
'1.1.1.201': (2001, 20001)}
|
|
expected_ip = '2.2.2.2'
|
|
expected_targets = {
|
|
'2.2.2.101': (1201, 12001),
|
|
'2.2.2.111': (1201, 12001),
|
|
'2.2.2.201': (2201, 22001)}
|
|
endpoints = self._generate_endpoints(expected_targets)
|
|
state = self._generate_lbaas_state(
|
|
current_ip, current_targets, project_id, subnet_id)
|
|
spec = self._generate_lbaas_spec(expected_ip, expected_targets,
|
|
project_id, subnet_id)
|
|
|
|
observed_targets = self._sync_lbaas_members_impl(
|
|
m_get_drv_lbaas, m_get_drv_project, m_get_drv_subnets,
|
|
subnet_id, project_id, endpoints, state, spec)
|
|
|
|
self.assertEqual(sorted(expected_targets.items()), observed_targets)
|
|
self.assertEqual(expected_ip, str(state.loadbalancer.ip))
|
|
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_sync_lbaas_members_udp(self, m_get_drv_lbaas,
|
|
m_get_drv_project, m_get_drv_subnets):
|
|
# REVISIT(ivc): test methods separately and verify ensure/release
|
|
project_id = str(uuid.uuid4())
|
|
subnet_id = str(uuid.uuid4())
|
|
current_ip = '1.1.1.1'
|
|
current_targets = {
|
|
'1.1.1.101': (1001, 10001),
|
|
'1.1.1.111': (1001, 10001),
|
|
'1.1.1.201': (2001, 20001)}
|
|
expected_ip = '2.2.2.2'
|
|
expected_targets = {
|
|
'2.2.2.101': (1201, 12001),
|
|
'2.2.2.111': (1201, 12001),
|
|
'2.2.2.201': (2201, 22001)}
|
|
endpoints = self._generate_endpoints(expected_targets)
|
|
state = self._generate_lbaas_state(
|
|
current_ip, current_targets, project_id, subnet_id)
|
|
spec = self._generate_lbaas_spec(expected_ip, expected_targets,
|
|
project_id, subnet_id, 'UDP')
|
|
|
|
observed_targets = self._sync_lbaas_members_impl(
|
|
m_get_drv_lbaas, m_get_drv_project, m_get_drv_subnets,
|
|
subnet_id, project_id, endpoints, state, spec)
|
|
|
|
self.assertEqual([], observed_targets)
|
|
self.assertEqual(expected_ip, str(state.loadbalancer.ip))
|
|
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_sync_lbaas_members_svc_listener_port_edit(
|
|
self, m_get_drv_lbaas, m_get_drv_project, m_get_drv_subnets):
|
|
# REVISIT(ivc): test methods separately and verify ensure/release
|
|
project_id = str(uuid.uuid4())
|
|
subnet_id = str(uuid.uuid4())
|
|
current_ip = '1.1.1.1'
|
|
current_targets = {
|
|
'1.1.1.101': (1001, 10001)}
|
|
expected_ip = '1.1.1.1'
|
|
expected_targets = {
|
|
'1.1.1.101': (1201, 10001)}
|
|
endpoints = self._generate_endpoints(expected_targets)
|
|
state = self._generate_lbaas_state(
|
|
current_ip, current_targets, project_id, subnet_id)
|
|
spec = self._generate_lbaas_spec(expected_ip, expected_targets,
|
|
project_id, subnet_id)
|
|
|
|
m_drv_lbaas = mock.Mock(wraps=FakeLBaaSDriver())
|
|
m_drv_project = mock.Mock()
|
|
m_drv_project.get_project.return_value = project_id
|
|
m_drv_subnets = mock.Mock()
|
|
m_drv_subnets.get_subnets.return_value = {
|
|
subnet_id: mock.sentinel.subnet}
|
|
m_get_drv_lbaas.return_value = m_drv_lbaas
|
|
m_get_drv_project.return_value = m_drv_project
|
|
m_get_drv_subnets.return_value = m_drv_subnets
|
|
|
|
handler = h_lbaas.LoadBalancerHandler()
|
|
|
|
with mock.patch.object(handler, '_get_pod_subnet') as m_get_pod_subnet:
|
|
m_get_pod_subnet.return_value = subnet_id
|
|
handler._sync_lbaas_members(endpoints, state, spec)
|
|
|
|
self.assertEqual(expected_ip, str(state.loadbalancer.ip))
|
|
m_drv_lbaas.release_pool.assert_called_once()
|
|
|
|
def test_get_lbaas_spec(self):
|
|
self.skipTest("skipping until generalised annotation handling is "
|
|
"implemented")
|
|
|
|
def test_get_lbaas_state(self):
|
|
self.skipTest("skipping until generalised annotation handling is "
|
|
"implemented")
|
|
|
|
def test_set_lbaas_state(self):
|
|
self.skipTest("skipping until generalised annotation handling is "
|
|
"implemented")
|
|
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodSubnetsDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.PodProjectDriver.get_instance')
|
|
@mock.patch('kuryr_kubernetes.controller.drivers.base'
|
|
'.LBaaSDriver.get_instance')
|
|
def test_add_new_members_udp(self, m_get_drv_lbaas,
|
|
m_get_drv_project, m_get_drv_subnets):
|
|
project_id = str(uuid.uuid4())
|
|
subnet_id = str(uuid.uuid4())
|
|
current_ip = '1.1.1.1'
|
|
current_targets = {
|
|
'1.1.1.101': (1001, 10001),
|
|
'1.1.1.111': (1001, 10001),
|
|
'1.1.1.201': (2001, 20001)}
|
|
expected_ip = '2.2.2.2'
|
|
expected_targets = {
|
|
'2.2.2.101': (1201, 12001),
|
|
'2.2.2.111': (1201, 12001),
|
|
'2.2.2.201': (2201, 22001)}
|
|
endpoints = self._generate_endpoints(expected_targets)
|
|
state = self._generate_lbaas_state(
|
|
current_ip, current_targets, project_id, subnet_id)
|
|
spec = self._generate_lbaas_spec(expected_ip, expected_targets,
|
|
project_id, subnet_id, 'UDP')
|
|
|
|
m_drv_lbaas = mock.Mock(wraps=FakeLBaaSDriver())
|
|
m_drv_project = mock.Mock()
|
|
m_drv_project.get_project.return_value = project_id
|
|
m_drv_subnets = mock.Mock()
|
|
m_drv_subnets.get_subnets.return_value = {
|
|
subnet_id: mock.sentinel.subnet}
|
|
m_get_drv_lbaas.return_value = m_drv_lbaas
|
|
m_get_drv_project.return_value = m_drv_project
|
|
m_get_drv_subnets.return_value = m_drv_subnets
|
|
|
|
handler = h_lbaas.LoadBalancerHandler()
|
|
member_added = handler._add_new_members(endpoints, state, spec)
|
|
|
|
self.assertEqual(member_added, False)
|
|
m_drv_lbaas.ensure_member.assert_not_called()
|