Ensure lb sg rules are updated upon namespace label updates

This patch ensures lb sg rules are updated when NPs reference to
namespace labels through namespace selectors. The affected svc
will be updated after namespace label is updated and due to that it
either starts or stops being referenced by the NP.

Closes-Bug: 1845977
Change-Id: I2d454f387676201066decce9f99d2f59b1ff6a66
This commit is contained in:
Luis Tomas Bolivar 2019-09-30 18:16:37 +02:00
parent de68d1e9d8
commit 232509ee66
3 changed files with 52 additions and 10 deletions

View File

@ -509,6 +509,7 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
LOG.debug("Deleting sg rule for namespace: %s",
ns_name)
crd_selectors = []
knp_crds = driver_utils.get_kuryrnetpolicy_crds()
for crd in knp_crds.get('items'):
crd_selector = crd['spec'].get('podSelector')
@ -523,11 +524,14 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
if i_matched or e_matched:
driver_utils.patch_kuryrnetworkpolicy_crd(
crd, i_rules, e_rules, crd_selector)
crd_selectors.append(crd_selector)
return crd_selectors
def create_namespace_sg_rules(self, namespace):
kubernetes = clients.get_kubernetes_client()
ns_name = namespace['metadata']['name']
LOG.debug("Creating sg rule for namespace: %s", ns_name)
crd_selectors = []
namespace = kubernetes.get(
'{}/namespaces/{}'.format(constants.K8S_API_BASE, ns_name))
knp_crds = driver_utils.get_kuryrnetpolicy_crds()
@ -543,12 +547,16 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
driver_utils.patch_kuryrnetworkpolicy_crd(crd, i_rules,
e_rules,
crd_selector)
crd_selectors.append(crd_selector)
return crd_selectors
def update_namespace_sg_rules(self, namespace):
LOG.debug("Updating sg rule for namespace: %s",
namespace['metadata']['name'])
self.delete_namespace_sg_rules(namespace)
self.create_namespace_sg_rules(namespace)
crd_selectors = []
crd_selectors.extend(self.delete_namespace_sg_rules(namespace))
crd_selectors.extend(self.create_namespace_sg_rules(namespace))
return crd_selectors
def create_namespace_sg(self, namespace, project_id, crd_spec):
LOG.debug("Security group driver does not create SGs for the "

View File

@ -20,7 +20,7 @@ from oslo_serialization import jsonutils
from kuryr_kubernetes import clients
from kuryr_kubernetes import constants
from kuryr_kubernetes.controller.drivers import base as drivers
from kuryr_kubernetes.controller.drivers import utils as drivers_utils
from kuryr_kubernetes.controller.drivers import utils as driver_utils
from kuryr_kubernetes import exceptions
from kuryr_kubernetes.handlers import k8s_base
from kuryr_kubernetes import utils
@ -57,20 +57,28 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
self._drv_vif_pool = drivers.VIFPoolDriver.get_instance(
specific_driver='multi_pool')
self._drv_vif_pool.set_vif_driver()
if self._is_network_policy_enabled():
self._drv_lbaas = drivers.LBaaSDriver.get_instance()
self._drv_svc_sg = (
drivers.ServiceSecurityGroupsDriver.get_instance())
def on_present(self, namespace):
ns_name = namespace['metadata']['name']
current_namespace_labels = namespace['metadata'].get('labels')
previous_namespace_labels = drivers_utils.get_annotated_labels(
previous_namespace_labels = driver_utils.get_annotated_labels(
namespace, constants.K8S_ANNOTATION_NAMESPACE_LABEL)
LOG.debug("Got previous namespace labels from annotation: %r",
previous_namespace_labels)
if current_namespace_labels != previous_namespace_labels:
self._drv_sg.update_namespace_sg_rules(namespace)
self._set_namespace_labels(namespace, current_namespace_labels)
project_id = self._drv_project.get_project(namespace)
if current_namespace_labels != previous_namespace_labels:
crd_selectors = self._drv_sg.update_namespace_sg_rules(namespace)
self._set_namespace_labels(namespace, current_namespace_labels)
if (self._is_network_policy_enabled() and crd_selectors and
oslo_cfg.CONF.octavia_defaults.enforce_sg_rules):
services = driver_utils.get_services()
self._update_services(services, crd_selectors, project_id)
net_crd_id = self._get_net_crd_id(namespace)
if net_crd_id:
LOG.debug("CRD existing at the new namespace")
@ -149,7 +157,13 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
LOG.debug("There is no security group associated with the "
"namespace to be deleted")
self._del_kuryrnet_crd(net_crd_name)
self._drv_sg.delete_namespace_sg_rules(namespace)
crd_selectors = self._drv_sg.delete_namespace_sg_rules(namespace)
if (self._is_network_policy_enabled() and crd_selectors and
oslo_cfg.CONF.octavia_defaults.enforce_sg_rules):
project_id = self._drv_project.get_project(namespace)
services = driver_utils.get_services()
self._update_services(services, crd_selectors, project_id)
def is_ready(self, quota):
if not utils.has_kuryr_crd(constants.K8S_API_CRD_KURYRNETS):
@ -253,3 +267,17 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
k8s.annotate(namespace['metadata']['selfLink'],
{constants.K8S_ANNOTATION_NAMESPACE_LABEL: annotation},
resource_version=namespace['metadata']['resourceVersion'])
def _update_services(self, services, crd_selectors, project_id):
for service in services.get('items'):
if not driver_utils.service_matches_affected_pods(
service, crd_selectors):
continue
sgs = self._drv_svc_sg.get_security_groups(service,
project_id)
self._drv_lbaas.update_lbaas_sg(service, sgs)
def _is_network_policy_enabled(self):
enabled_handlers = oslo_cfg.CONF.kubernetes.enabled_handlers
svc_sg_driver = oslo_cfg.CONF.kubernetes.service_security_groups_driver
return ('policy' in enabled_handlers and svc_sg_driver == 'policy')

View File

@ -64,6 +64,8 @@ class TestNamespaceHandler(test_base.TestCase):
self._handler._drv_sg.create_namespace_sg)
self._delete_sg = (
self._handler._drv_sg.delete_sg)
self._delete_namespace_sg_rules = (
self._handler._drv_sg.delete_namespace_sg_rules)
self._cleanup_namespace_networks = (
self._handler._drv_subnets.cleanup_namespace_networks)
self._get_net_crd = self._handler._get_net_crd
@ -94,21 +96,24 @@ class TestNamespaceHandler(test_base.TestCase):
}
return crd
@mock.patch.object(drivers.LBaaSDriver, 'get_instance')
@mock.patch.object(drivers.VIFPoolDriver, 'get_instance')
@mock.patch.object(drivers.PodSecurityGroupsDriver, 'get_instance')
@mock.patch.object(drivers.PodSubnetsDriver, 'get_instance')
@mock.patch.object(drivers.NamespaceProjectDriver, 'get_instance')
def test_init(self, m_get_project_driver, m_get_subnets_driver,
m_get_sg_driver, m_get_vif_pool_driver):
m_get_sg_driver, m_get_vif_pool_driver, m_get_lbaas_driver):
project_driver = mock.sentinel.project_driver
subnets_driver = mock.sentinel.subnets_driver
sg_driver = mock.sentinel.sg_driver
vif_pool_driver = mock.Mock(spec=vif_pool.MultiVIFPool)
lbaas_driver = mock.sentinel.lbaas_driver
m_get_project_driver.return_value = project_driver
m_get_subnets_driver.return_value = subnets_driver
m_get_sg_driver.return_value = sg_driver
m_get_vif_pool_driver.return_value = vif_pool_driver
m_get_lbaas_driver.return_value = lbaas_driver
handler = namespace.NamespaceHandler()
@ -278,6 +283,7 @@ class TestNamespaceHandler(test_base.TestCase):
self._get_net_crd_id.return_value = net_crd_id
self._get_net_crd.return_value = net_crd
self._delete_namespace_sg_rules.return_value = []
namespace.NamespaceHandler.on_deleted(self._handler, self._namespace)