Update CRD when NP has namespaceSelectors
When a namespace is created, deleted or updated and its labels matches the namespaceSelector of a NP, the CRD and the respective sg must be updated. Partially Implements: blueprint k8s-network-policies Change-Id: I515de28647f5f06248555733c27dd4f5a56149ec
This commit is contained in:
parent
7480cc36f8
commit
9deb322962
|
@ -37,6 +37,7 @@ K8S_POD_STATUS_PENDING = 'Pending'
|
|||
K8S_ANNOTATION_PREFIX = 'openstack.org/kuryr'
|
||||
K8S_ANNOTATION_VIF = K8S_ANNOTATION_PREFIX + '-vif'
|
||||
K8S_ANNOTATION_LABEL = K8S_ANNOTATION_PREFIX + '-pod-label'
|
||||
K8S_ANNOTATION_NAMESPACE_LABEL = K8S_ANNOTATION_PREFIX + '-namespace-label'
|
||||
K8S_ANNOTATION_LBAAS_SPEC = K8S_ANNOTATION_PREFIX + '-lbaas-spec'
|
||||
K8S_ANNOTATION_LBAAS_STATE = K8S_ANNOTATION_PREFIX + '-lbaas-state'
|
||||
K8S_ANNOTATION_NET_CRD = K8S_ANNOTATION_PREFIX + '-net-crd'
|
||||
|
|
|
@ -268,6 +268,27 @@ class PodSecurityGroupsDriver(DriverBase):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_namespace_sg_rules(self, namespace):
|
||||
"""Delete security group rule associated to a namespace.
|
||||
|
||||
:param namespace: dict containing K8S Namespace object
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_namespace_sg_rules(self, namespace):
|
||||
"""Create security group rule associated to a namespace.
|
||||
|
||||
:param namespace: dict containing K8S Namespace object
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def update_namespace_sg_rules(self, namespace):
|
||||
"""Update security group rule associated to a namespace.
|
||||
|
||||
:param namespace: dict containing K8S Namespace object
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ServiceSecurityGroupsDriver(DriverBase):
|
||||
|
|
|
@ -59,6 +59,18 @@ class DefaultPodSecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
|||
LOG.debug("Security group driver does not update SG rules for "
|
||||
"the pods.")
|
||||
|
||||
def delete_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not delete SG rules for "
|
||||
"namespace.")
|
||||
|
||||
def create_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not create SG rules for "
|
||||
"namespace.")
|
||||
|
||||
def update_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not update SG rules for "
|
||||
"namespace.")
|
||||
|
||||
|
||||
class DefaultServiceSecurityGroupsDriver(base.ServiceSecurityGroupsDriver):
|
||||
"""Provides security groups for Service based on a configuration option."""
|
||||
|
|
|
@ -21,6 +21,7 @@ from kuryr_kubernetes import clients
|
|||
from kuryr_kubernetes import config
|
||||
from kuryr_kubernetes import constants
|
||||
from kuryr_kubernetes.controller.drivers import base
|
||||
from kuryr_kubernetes.controller.drivers import utils
|
||||
from kuryr_kubernetes import exceptions
|
||||
|
||||
from neutronclient.common import exceptions as n_exc
|
||||
|
@ -67,6 +68,73 @@ def _get_net_crd(namespace):
|
|||
return net_crd
|
||||
|
||||
|
||||
def _create_sg_rule(sg_id, direction, cidr, port=None, namespace=None):
|
||||
if port:
|
||||
sg_rule = utils.create_security_group_rule_body(
|
||||
sg_id, direction, port.get('port'),
|
||||
protocol=port.get('protocol'), cidr=cidr, namespace=namespace)
|
||||
else:
|
||||
sg_rule = utils.create_security_group_rule_body(
|
||||
sg_id, direction, port_range_min=1,
|
||||
port_range_max=65535, cidr=cidr, namespace=namespace)
|
||||
|
||||
sgr_id = utils.create_security_group_rule(sg_rule)
|
||||
|
||||
sg_rule['security_group_rule']['id'] = sgr_id
|
||||
return sg_rule
|
||||
|
||||
|
||||
def _parse_rules(direction, crd, namespace):
|
||||
policy = crd['spec']['networkpolicy_spec']
|
||||
sg_id = crd['spec']['securityGroupId']
|
||||
|
||||
ns_labels = namespace['metadata'].get('labels')
|
||||
ns_name = namespace['metadata'].get('name')
|
||||
ns_cidr = utils.get_namespace_subnet_cidr(namespace)
|
||||
|
||||
rule_direction = 'from'
|
||||
crd_rules = crd['spec'].get('ingressSgRules')
|
||||
if direction == 'egress':
|
||||
rule_direction = 'to'
|
||||
crd_rules = crd['spec'].get('egressSgRules')
|
||||
|
||||
matched = False
|
||||
rule_list = policy.get(direction, None)
|
||||
for rule_block in rule_list:
|
||||
for rule in rule_block.get(rule_direction, []):
|
||||
pod_selector = rule.get('podSelector')
|
||||
ns_selector = rule.get('namespaceSelector')
|
||||
if (ns_selector and ns_labels and
|
||||
utils.match_selector(ns_selector, ns_labels)):
|
||||
if pod_selector:
|
||||
pods = utils.get_pods(pod_selector, ns_name)
|
||||
for pod in pods.get('items'):
|
||||
pod_ip = utils.get_pod_ip(pod)
|
||||
if 'ports' in rule_block:
|
||||
for port in rule_block['ports']:
|
||||
matched = True
|
||||
crd_rules.append(_create_sg_rule(
|
||||
sg_id, direction, pod_ip, port=port,
|
||||
namespace=ns_name))
|
||||
else:
|
||||
matched = True
|
||||
crd_rules.append(_create_sg_rule(
|
||||
sg_id, direction, pod_ip,
|
||||
namespace=ns_name))
|
||||
else:
|
||||
if 'ports' in rule_block:
|
||||
for port in rule_block['ports']:
|
||||
matched = True
|
||||
crd_rules.append(_create_sg_rule(
|
||||
sg_id, direction, ns_cidr,
|
||||
port=port, namespace=ns_name))
|
||||
else:
|
||||
matched = True
|
||||
crd_rules.append(_create_sg_rule(
|
||||
sg_id, direction, ns_cidr, namespace=ns_name))
|
||||
return matched, crd_rules
|
||||
|
||||
|
||||
class NamespacePodSecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
||||
"""Provides security groups for Pod based on a configuration option."""
|
||||
|
||||
|
@ -131,6 +199,68 @@ class NamespacePodSecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
|||
LOG.exception("Error deleting security group %s.", sg_id)
|
||||
raise
|
||||
|
||||
def delete_namespace_sg_rules(self, namespace):
|
||||
ns_name = namespace['metadata']['name']
|
||||
LOG.debug("Deleting sg rule for namespace: %s",
|
||||
ns_name)
|
||||
|
||||
knp_crds = utils.get_kuryrnetpolicy_crds()
|
||||
for crd in knp_crds.get('items'):
|
||||
crd_selector = crd['spec'].get('podSelector')
|
||||
ingress_rule_list = crd['spec'].get('ingressSgRules')
|
||||
egress_rule_list = crd['spec'].get('egressSgRules')
|
||||
i_rules = []
|
||||
e_rules = []
|
||||
|
||||
matched = False
|
||||
for i_rule in ingress_rule_list:
|
||||
LOG.debug("Parsing ingress rule: %r", i_rule)
|
||||
rule_namespace = i_rule.get('namespace', None)
|
||||
|
||||
if rule_namespace and rule_namespace == ns_name:
|
||||
matched = True
|
||||
utils.delete_security_group_rule(
|
||||
i_rule['security_group_rule']['id'])
|
||||
else:
|
||||
i_rules.append(i_rule)
|
||||
|
||||
for e_rule in egress_rule_list:
|
||||
LOG.debug("Parsing egress rule: %r", e_rule)
|
||||
rule_namespace = e_rule.get('namespace', None)
|
||||
|
||||
if rule_namespace and rule_namespace == ns_name:
|
||||
matched = True
|
||||
utils.delete_security_group_rule(
|
||||
e_rule['security_group_rule']['id'])
|
||||
else:
|
||||
e_rules.append(e_rule)
|
||||
|
||||
if matched:
|
||||
utils.patch_kuryr_crd(crd, i_rules, e_rules, crd_selector)
|
||||
|
||||
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)
|
||||
namespace = kubernetes.get(
|
||||
'{}/namespaces/{}'.format(constants.K8S_API_BASE, ns_name))
|
||||
knp_crds = utils.get_kuryrnetpolicy_crds()
|
||||
for crd in knp_crds.get('items'):
|
||||
crd_selector = crd['spec'].get('podSelector')
|
||||
|
||||
i_matched, i_rules = _parse_rules('ingress', crd, namespace)
|
||||
e_matched, e_rules = _parse_rules('egress', crd, namespace)
|
||||
|
||||
if i_matched or e_matched:
|
||||
utils.patch_kuryr_crd(crd, i_rules,
|
||||
e_rules, crd_selector)
|
||||
|
||||
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)
|
||||
|
||||
def create_sg_rules(self, pod):
|
||||
LOG.debug("Security group driver does not create SG rules for "
|
||||
"the pods.")
|
||||
|
|
|
@ -203,40 +203,27 @@ class NetworkPolicyDriver(base.NetworkPolicyDriver):
|
|||
matching_pods = driver_utils.get_pods(pod_selector, namespace)
|
||||
for pod in matching_pods.get('items'):
|
||||
if pod['status']['podIP']:
|
||||
ips.append(pod['status']['podIP'])
|
||||
pod_ip = pod['status']['podIP']
|
||||
ns = pod['metadata']['namespace']
|
||||
ips.append({'cidr': pod_ip, 'namespace': ns})
|
||||
return ips
|
||||
|
||||
def _get_namespace_subnet_cidr(self, namespace):
|
||||
try:
|
||||
ns_annotations = namespace['metadata']['annotations']
|
||||
ns_name = ns_annotations[constants.K8S_ANNOTATION_NET_CRD]
|
||||
except KeyError:
|
||||
LOG.exception('Namespace handler must be enabled to support '
|
||||
'Network Policies with namespaceSelector')
|
||||
raise exceptions.ResourceNotReady(namespace)
|
||||
try:
|
||||
net_crd = self.kubernetes.get('{}/kuryrnets/{}'.format(
|
||||
constants.K8S_API_CRD, ns_name))
|
||||
except exceptions.K8sClientException:
|
||||
LOG.exception("Kubernetes Client Exception.")
|
||||
raise
|
||||
return net_crd['spec']['subnetCIDR']
|
||||
|
||||
def _get_namespaces_cidr(self, namespace_selector, namespace=None):
|
||||
cidrs = []
|
||||
if not namespace_selector and namespace:
|
||||
ns = self.kubernetes.get(
|
||||
'{}/namespaces/{}'.format(constants.K8S_API_BASE, namespace))
|
||||
ns_cidr = self._get_namespace_subnet_cidr(ns)
|
||||
cidrs.append(ns_cidr)
|
||||
ns_cidr = driver_utils.get_namespace_subnet_cidr(ns)
|
||||
cidrs.append({'cidr': ns_cidr, 'namespace': namespace})
|
||||
else:
|
||||
matching_namespaces = driver_utils.get_namespaces(
|
||||
namespace_selector)
|
||||
for ns in matching_namespaces.get('items'):
|
||||
# NOTE(ltomasbo): This requires the namespace handler to be
|
||||
# also enabled
|
||||
ns_cidr = self._get_namespace_subnet_cidr(ns)
|
||||
cidrs.append(ns_cidr)
|
||||
ns_cidr = driver_utils.get_namespace_subnet_cidr(ns)
|
||||
ns_name = ns['metadata']['name']
|
||||
cidrs.append({'cidr': ns_cidr, 'namespace': ns_name})
|
||||
return cidrs
|
||||
|
||||
def _parse_selectors(self, rule_block, rule_direction, policy_namespace):
|
||||
|
@ -315,7 +302,8 @@ class NetworkPolicyDriver(base.NetworkPolicyDriver):
|
|||
driver_utils.create_security_group_rule_body(
|
||||
sg_id, direction, port.get('port'),
|
||||
protocol=port.get('protocol'),
|
||||
cidr=cidr))
|
||||
cidr=cidr.get('cidr'),
|
||||
namespace=cidr.get('namespace')))
|
||||
sg_rule_body_list.append(rule)
|
||||
if allow_all:
|
||||
rule = (
|
||||
|
@ -334,7 +322,8 @@ class NetworkPolicyDriver(base.NetworkPolicyDriver):
|
|||
sg_id, direction,
|
||||
port_range_min=1,
|
||||
port_range_max=65535,
|
||||
cidr=cidr)
|
||||
cidr=cidr.get('cidr'),
|
||||
namespace=cidr.get('namespace'))
|
||||
sg_rule_body_list.append(rule)
|
||||
if allow_all:
|
||||
rule = driver_utils.create_security_group_rule_body(
|
||||
|
|
|
@ -26,81 +26,6 @@ from oslo_log import log as logging
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
OPERATORS_WITH_VALUES = [constants.K8S_OPERATOR_IN,
|
||||
constants.K8S_OPERATOR_NOT_IN]
|
||||
|
||||
|
||||
def _get_kuryrnetpolicy_crds(namespace=None):
|
||||
kubernetes = clients.get_kubernetes_client()
|
||||
|
||||
try:
|
||||
if namespace:
|
||||
knp_path = '{}/{}/kuryrnetpolicies'.format(
|
||||
constants.K8S_API_CRD_NAMESPACES, namespace)
|
||||
else:
|
||||
knp_path = constants.K8S_API_CRD_KURYRNETPOLICIES
|
||||
LOG.debug("K8s API Query %s", knp_path)
|
||||
knps = kubernetes.get(knp_path)
|
||||
LOG.debug("Return Kuryr Network Policies with label %s", knps)
|
||||
except exceptions.K8sResourceNotFound:
|
||||
LOG.exception("KuryrNetPolicy CRD not found")
|
||||
raise
|
||||
except exceptions.K8sClientException:
|
||||
LOG.exception("Kubernetes Client Exception")
|
||||
raise
|
||||
return knps
|
||||
|
||||
|
||||
def _match_expressions(expressions, labels):
|
||||
for exp in expressions:
|
||||
exp_op = exp['operator'].lower()
|
||||
if labels:
|
||||
if exp_op in OPERATORS_WITH_VALUES:
|
||||
exp_values = exp['values']
|
||||
label_value = labels.get(str(exp['key']), None)
|
||||
if exp_op == constants.K8S_OPERATOR_IN:
|
||||
if label_value is None or label_value not in exp_values:
|
||||
return False
|
||||
elif exp_op == constants.K8S_OPERATOR_NOT_IN:
|
||||
if label_value in exp_values:
|
||||
return False
|
||||
else:
|
||||
if exp_op == constants.K8S_OPERATOR_EXISTS:
|
||||
exists = labels.get(str(exp['key']), None)
|
||||
if exists is None:
|
||||
return False
|
||||
elif exp_op == constants.K8S_OPERATOR_DOES_NOT_EXIST:
|
||||
exists = labels.get(str(exp['key']), None)
|
||||
if exists is not None:
|
||||
return False
|
||||
else:
|
||||
if exp_op in (constants.K8S_OPERATOR_IN,
|
||||
constants.K8S_OPERATOR_EXISTS):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _match_labels(crd_labels, labels):
|
||||
for crd_key, crd_value in crd_labels.items():
|
||||
label_value = labels.get(crd_key, None)
|
||||
if not label_value or crd_value != label_value:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _match_selector(selector, labels):
|
||||
crd_labels = selector.get('matchLabels', None)
|
||||
crd_expressions = selector.get('matchExpressions', None)
|
||||
|
||||
match_exp = match_lb = True
|
||||
if crd_expressions:
|
||||
match_exp = _match_expressions(crd_expressions,
|
||||
labels)
|
||||
if crd_labels and labels:
|
||||
match_lb = _match_labels(crd_labels, labels)
|
||||
return match_exp and match_lb
|
||||
|
||||
|
||||
def _get_namespace_labels(namespace):
|
||||
kubernetes = clients.get_kubernetes_client()
|
||||
|
||||
|
@ -119,15 +44,15 @@ def _get_namespace_labels(namespace):
|
|||
return namespaces['metadata'].get('labels')
|
||||
|
||||
|
||||
def _create_sg_rules(crd, pod, namespace_selector, pod_selector,
|
||||
rule_block, crd_rules, direction,
|
||||
matched):
|
||||
def _create_sg_rules(crd, pod, pod_selector, rule_block, crd_rules,
|
||||
direction, matched, namespace=None):
|
||||
pod_labels = pod['metadata'].get('labels')
|
||||
|
||||
# NOTE (maysams) No need to differentiate between podSelector
|
||||
# with empty value or with '{}', as they have same result in here.
|
||||
if (pod_selector and
|
||||
_match_selector(pod_selector, pod_labels)):
|
||||
driver_utils.match_selector(pod_selector, pod_labels)):
|
||||
|
||||
matched = True
|
||||
pod_ip = driver_utils.get_pod_ip(pod)
|
||||
sg_id = crd['spec']['securityGroupId']
|
||||
|
@ -135,7 +60,8 @@ def _create_sg_rules(crd, pod, namespace_selector, pod_selector,
|
|||
for port in rule_block['ports']:
|
||||
sg_rule = driver_utils.create_security_group_rule_body(
|
||||
sg_id, direction, port.get('port'),
|
||||
protocol=port.get('protocol'), cidr=pod_ip)
|
||||
protocol=port.get('protocol'), cidr=pod_ip,
|
||||
namespace=namespace)
|
||||
sgr_id = driver_utils.create_security_group_rule(sg_rule)
|
||||
sg_rule['security_group_rule']['id'] = sgr_id
|
||||
crd_rules.append(sg_rule)
|
||||
|
@ -144,7 +70,8 @@ def _create_sg_rules(crd, pod, namespace_selector, pod_selector,
|
|||
sg_id, direction,
|
||||
port_range_min=1,
|
||||
port_range_max=65535,
|
||||
cidr=pod_ip)
|
||||
cidr=pod_ip,
|
||||
namespace=namespace)
|
||||
sgr_id = driver_utils.create_security_group_rule(sg_rule)
|
||||
sg_rule['security_group_rule']['id'] = sgr_id
|
||||
crd_rules.append(sg_rule)
|
||||
|
@ -171,23 +98,22 @@ def _parse_rules(direction, crd, pod):
|
|||
namespace_selector = rule.get('namespaceSelector')
|
||||
pod_selector = rule.get('podSelector')
|
||||
if namespace_selector == {}:
|
||||
if _create_sg_rules(crd, pod, namespace_selector,
|
||||
pod_selector, rule_block, crd_rules,
|
||||
direction, matched):
|
||||
if _create_sg_rules(crd, pod, pod_selector, rule_block,
|
||||
crd_rules, direction, matched):
|
||||
matched = True
|
||||
elif namespace_selector:
|
||||
if (pod_namespace_labels and
|
||||
_match_selector(namespace_selector,
|
||||
pod_namespace_labels)):
|
||||
if _create_sg_rules(crd, pod, namespace_selector,
|
||||
pod_selector, rule_block, crd_rules,
|
||||
direction, matched):
|
||||
driver_utils.match_selector(namespace_selector,
|
||||
pod_namespace_labels)):
|
||||
if _create_sg_rules(crd, pod, pod_selector, rule_block,
|
||||
crd_rules, direction, matched,
|
||||
pod_namespace):
|
||||
matched = True
|
||||
else:
|
||||
if pod_namespace == policy_namespace:
|
||||
if _create_sg_rules(crd, pod, namespace_selector,
|
||||
pod_selector, rule_block, crd_rules,
|
||||
direction, matched):
|
||||
if _create_sg_rules(crd, pod, pod_selector, rule_block,
|
||||
crd_rules, direction, matched,
|
||||
pod_namespace):
|
||||
matched = True
|
||||
return matched, crd_rules
|
||||
|
||||
|
@ -198,11 +124,12 @@ def _get_pod_sgs(pod, project_id):
|
|||
pod_labels = pod['metadata'].get('labels')
|
||||
pod_namespace = pod['metadata']['namespace']
|
||||
|
||||
knp_crds = _get_kuryrnetpolicy_crds(namespace=pod_namespace)
|
||||
knp_crds = driver_utils.get_kuryrnetpolicy_crds(
|
||||
namespace=pod_namespace)
|
||||
for crd in knp_crds.get('items'):
|
||||
pod_selector = crd['spec'].get('podSelector')
|
||||
if pod_selector:
|
||||
if _match_selector(pod_selector, pod_labels):
|
||||
if driver_utils.match_selector(pod_selector, pod_labels):
|
||||
LOG.debug("Appending %s",
|
||||
str(crd['spec']['securityGroupId']))
|
||||
sg_list.append(str(crd['spec']['securityGroupId']))
|
||||
|
@ -229,7 +156,7 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
|||
|
||||
def create_sg_rules(self, pod):
|
||||
LOG.debug("Creating sg rule for pod: %s", pod['metadata']['name'])
|
||||
knp_crds = _get_kuryrnetpolicy_crds()
|
||||
knp_crds = driver_utils.get_kuryrnetpolicy_crds()
|
||||
for crd in knp_crds.get('items'):
|
||||
crd_selector = crd['spec'].get('podSelector')
|
||||
|
||||
|
@ -244,7 +171,7 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
|||
LOG.debug("Deleting sg rule for pod: %s", pod['metadata']['name'])
|
||||
pod_ip = driver_utils.get_pod_ip(pod)
|
||||
|
||||
knp_crds = _get_kuryrnetpolicy_crds()
|
||||
knp_crds = driver_utils.get_kuryrnetpolicy_crds()
|
||||
for crd in knp_crds.get('items'):
|
||||
crd_selector = crd['spec'].get('podSelector')
|
||||
ingress_rule_list = crd['spec'].get('ingressSgRules')
|
||||
|
@ -293,6 +220,18 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
|||
LOG.debug("Security group driver does not implement deleting "
|
||||
"SGs.")
|
||||
|
||||
def delete_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not delete SG rules for "
|
||||
"namespace.")
|
||||
|
||||
def create_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not create SG rules for "
|
||||
"namespace.")
|
||||
|
||||
def update_namespace_sg_rules(self, namespace):
|
||||
LOG.debug("Security group driver does not update SG rules for "
|
||||
"namespace.")
|
||||
|
||||
|
||||
class NetworkPolicyServiceSecurityGroupsDriver(
|
||||
base.ServiceSecurityGroupsDriver):
|
||||
|
|
|
@ -238,7 +238,7 @@ def patch_kuryr_crd(crd, i_rules, e_rules, pod_selector, np_spec=None):
|
|||
def create_security_group_rule_body(
|
||||
security_group_id, direction, port_range_min,
|
||||
port_range_max=None, protocol=None, ethertype='IPv4', cidr=None,
|
||||
description="Kuryr-Kubernetes NetPolicy SG rule"):
|
||||
description="Kuryr-Kubernetes NetPolicy SG rule", namespace=None):
|
||||
if not port_range_min:
|
||||
port_range_min = 1
|
||||
port_range_max = 65535
|
||||
|
@ -260,6 +260,8 @@ def create_security_group_rule_body(
|
|||
if cidr:
|
||||
security_group_rule_body[u'security_group_rule'][
|
||||
u'remote_ip_prefix'] = cidr
|
||||
if namespace:
|
||||
security_group_rule_body['namespace'] = namespace
|
||||
LOG.debug("Creating sg rule body %s", security_group_rule_body)
|
||||
return security_group_rule_body
|
||||
|
||||
|
@ -280,11 +282,100 @@ def get_pod_ip(pod):
|
|||
return first_subnet_ip
|
||||
|
||||
|
||||
def get_pod_annotated_labels(pod):
|
||||
def get_annotated_labels(resource, annotation_labels):
|
||||
try:
|
||||
annotations = pod['metadata']['annotations']
|
||||
pod_labels_annotation = annotations[constants.K8S_ANNOTATION_LABEL]
|
||||
annotations = resource['metadata']['annotations']
|
||||
labels_annotation = annotations[annotation_labels]
|
||||
except KeyError:
|
||||
return None
|
||||
pod_labels = jsonutils.loads(pod_labels_annotation)
|
||||
return pod_labels
|
||||
labels = jsonutils.loads(labels_annotation)
|
||||
return labels
|
||||
|
||||
|
||||
def get_kuryrnetpolicy_crds(namespace=None):
|
||||
kubernetes = clients.get_kubernetes_client()
|
||||
|
||||
try:
|
||||
if namespace:
|
||||
knp_path = '{}/{}/kuryrnetpolicies'.format(
|
||||
constants.K8S_API_CRD_NAMESPACES, namespace)
|
||||
else:
|
||||
knp_path = constants.K8S_API_CRD_KURYRNETPOLICIES
|
||||
LOG.debug("K8s API Query %s", knp_path)
|
||||
knps = kubernetes.get(knp_path)
|
||||
LOG.debug("Return Kuryr Network Policies with label %s", knps)
|
||||
except k_exc.K8sResourceNotFound:
|
||||
LOG.exception("KuryrNetPolicy CRD not found")
|
||||
raise
|
||||
except k_exc.K8sClientException:
|
||||
LOG.exception("Kubernetes Client Exception")
|
||||
raise
|
||||
return knps
|
||||
|
||||
|
||||
def match_expressions(expressions, labels):
|
||||
for exp in expressions:
|
||||
exp_op = exp['operator'].lower()
|
||||
if labels:
|
||||
if exp_op in OPERATORS_WITH_VALUES:
|
||||
exp_values = exp['values']
|
||||
label_value = labels.get(str(exp['key']), None)
|
||||
if exp_op == constants.K8S_OPERATOR_IN:
|
||||
if label_value is None or label_value not in exp_values:
|
||||
return False
|
||||
elif exp_op == constants.K8S_OPERATOR_NOT_IN:
|
||||
if label_value in exp_values:
|
||||
return False
|
||||
else:
|
||||
if exp_op == constants.K8S_OPERATOR_EXISTS:
|
||||
exists = labels.get(str(exp['key']), None)
|
||||
if exists is None:
|
||||
return False
|
||||
elif exp_op == constants.K8S_OPERATOR_DOES_NOT_EXIST:
|
||||
exists = labels.get(str(exp['key']), None)
|
||||
if exists is not None:
|
||||
return False
|
||||
else:
|
||||
if exp_op in (constants.K8S_OPERATOR_IN,
|
||||
constants.K8S_OPERATOR_EXISTS):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def match_labels(crd_labels, labels):
|
||||
for crd_key, crd_value in crd_labels.items():
|
||||
label_value = labels.get(crd_key, None)
|
||||
if not label_value or crd_value != label_value:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def match_selector(selector, labels):
|
||||
crd_labels = selector.get('matchLabels', None)
|
||||
crd_expressions = selector.get('matchExpressions', None)
|
||||
|
||||
match_exp = match_lb = True
|
||||
if crd_expressions:
|
||||
match_exp = match_expressions(crd_expressions,
|
||||
labels)
|
||||
if crd_labels and labels:
|
||||
match_lb = match_labels(crd_labels, labels)
|
||||
return match_exp and match_lb
|
||||
|
||||
|
||||
def get_namespace_subnet_cidr(namespace):
|
||||
kubernetes = clients.get_kubernetes_client()
|
||||
try:
|
||||
ns_annotations = namespace['metadata']['annotations']
|
||||
ns_name = ns_annotations[constants.K8S_ANNOTATION_NET_CRD]
|
||||
except KeyError:
|
||||
LOG.exception('Namespace handler must be enabled to support '
|
||||
'Network Policies with namespaceSelector')
|
||||
raise k_exc.ResourceNotReady(namespace)
|
||||
try:
|
||||
net_crd = kubernetes.get('{}/kuryrnets/{}'.format(
|
||||
constants.K8S_API_CRD, ns_name))
|
||||
except k_exc.K8sClientException:
|
||||
LOG.exception("Kubernetes Client Exception.")
|
||||
raise
|
||||
return net_crd['spec']['subnetCIDR']
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
from oslo_cache import core as cache
|
||||
from oslo_config import cfg as oslo_cfg
|
||||
from oslo_log import log as logging
|
||||
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 import exceptions
|
||||
from kuryr_kubernetes.handlers import k8s_base
|
||||
from kuryr_kubernetes import utils
|
||||
|
@ -57,6 +59,17 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
|
|||
self._drv_vif_pool.set_vif_driver()
|
||||
|
||||
def on_present(self, namespace):
|
||||
current_namespace_labels = namespace['metadata'].get('labels')
|
||||
previous_namespace_labels = drivers_utils.get_annotated_labels(
|
||||
namespace, constants.K8S_ANNOTATION_NAMESPACE_LABEL)
|
||||
LOG.debug("Got previous namespace labels from annotation: %r",
|
||||
previous_namespace_labels)
|
||||
|
||||
if (previous_namespace_labels and
|
||||
current_namespace_labels != previous_namespace_labels):
|
||||
self._drv_sg.update_namespace_sg_rules(namespace)
|
||||
self._set_namespace_labels(namespace, current_namespace_labels)
|
||||
|
||||
ns_name = namespace['metadata']['name']
|
||||
project_id = self._drv_project.get_project(namespace)
|
||||
net_crd_id = self._get_net_crd_id(namespace)
|
||||
|
@ -85,6 +98,8 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
|
|||
try:
|
||||
net_crd = self._add_kuryrnet_crd(ns_name, net_crd_spec)
|
||||
self._set_net_crd(namespace, net_crd)
|
||||
self._drv_sg.create_namespace_sg_rules(namespace)
|
||||
self._set_namespace_labels(namespace, current_namespace_labels)
|
||||
except exceptions.K8sClientException:
|
||||
LOG.exception("Kuryrnet CRD could not be added. Rolling back "
|
||||
"network resources created for the namespace.")
|
||||
|
@ -108,8 +123,8 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
|
|||
else:
|
||||
LOG.debug("There is no security group associated with the "
|
||||
"namespace to be deleted")
|
||||
|
||||
self._del_kuryrnet_crd(net_crd_id)
|
||||
self._drv_sg.delete_namespace_sg_rules(namespace)
|
||||
|
||||
def is_ready(self, quota):
|
||||
if not utils.has_kuryr_crd(constants.K8S_API_CRD_KURYRNETS):
|
||||
|
@ -191,3 +206,16 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
|
|||
LOG.exception("Kubernetes Client Exception deleting kuryrnet "
|
||||
"CRD.")
|
||||
raise
|
||||
|
||||
def _set_namespace_labels(self, namespace, labels):
|
||||
if not labels:
|
||||
LOG.debug("Removing Label annotation: %r", labels)
|
||||
annotation = None
|
||||
else:
|
||||
annotation = jsonutils.dumps(labels, sort_keys=True)
|
||||
LOG.debug("Setting Labels annotation: %r", annotation)
|
||||
|
||||
k8s = clients.get_kubernetes_client()
|
||||
k8s.annotate(namespace['metadata']['selfLink'],
|
||||
{constants.K8S_ANNOTATION_NAMESPACE_LABEL: annotation},
|
||||
resource_version=namespace['metadata']['resourceVersion'])
|
||||
|
|
|
@ -61,6 +61,131 @@ def get_namespace_obj():
|
|||
}
|
||||
|
||||
|
||||
def get_no_match_crd_namespace_obj():
|
||||
return {
|
||||
"kind": "Namespace",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"openstack.org/kuryr-namespace-label": '{"name": "dev"}',
|
||||
"openstack.org/kuryr-net-crd": "ns-dev"
|
||||
},
|
||||
"labels": {"name": "prod"},
|
||||
"name": "prod",
|
||||
"selfLink": "/api/v1/namespaces/dev"}}
|
||||
|
||||
|
||||
def get_match_crd_namespace_obj():
|
||||
return {
|
||||
"kind": "Namespace",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"openstack.org/kuryr-namespace-label": '{"name": "dev"}',
|
||||
"openstack.org/kuryr-net-crd": "ns-dev"
|
||||
},
|
||||
"labels": {
|
||||
"name": "dev"
|
||||
},
|
||||
"name": "dev",
|
||||
"selfLink": "/api/v1/namespaces/dev"}}
|
||||
|
||||
|
||||
def get_match_crd_pod_obj():
|
||||
return {
|
||||
'kind': 'Pod',
|
||||
'metadata': {
|
||||
'name': mock.sentinel.pod_name,
|
||||
'namespace': 'dev',
|
||||
'labels': {
|
||||
'tier': 'backend'},
|
||||
'annotations': {
|
||||
'openstack.org/kuryr-pod-label': '{"tier": "backend"}'}},
|
||||
'status': {'podIP': mock.sentinel.podIP}}
|
||||
|
||||
|
||||
def get_sg_rule():
|
||||
pod_ip = get_match_crd_pod_obj()['status'].get('podIP')
|
||||
return {
|
||||
"namespace": 'dev',
|
||||
"security_group_rule": {
|
||||
"description": "Kuryr-Kubernetes NetPolicy SG rule",
|
||||
"direction": "ingress",
|
||||
"ethertype": "IPv4",
|
||||
"id": 'f15ff50a-e8a4-4872-81bf-a04cbb8cb388',
|
||||
"port_range_max": 6379,
|
||||
"port_range_min": 6379,
|
||||
"protocol": "tcp",
|
||||
"remote_ip_prefix": pod_ip,
|
||||
"security_group_id": '36923e76-026c-422b-8dfd-7292e7c88228'}}
|
||||
|
||||
|
||||
def get_matched_crd_obj():
|
||||
return {
|
||||
"kind": "KuryrNetPolicy",
|
||||
"metadata": {"name": "np-test-network-policy",
|
||||
"namespace": "default"},
|
||||
"spec": {
|
||||
"egressSgRules": [],
|
||||
"ingressSgRules": [get_sg_rule()],
|
||||
"networkpolicy_spec": {
|
||||
"ingress": [
|
||||
{"from": [
|
||||
{"namespaceSelector": {
|
||||
"matchLabels": {"name": "dev"}}}],
|
||||
"ports": [
|
||||
{"port": 6379,
|
||||
"protocol": "TCP"}]}],
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"policyTypes": ["Ingress"]},
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"securityGroupId": '36923e76-026c-422b-8dfd-7292e7c88228'}}
|
||||
|
||||
|
||||
def get_crd_obj_no_match():
|
||||
return {
|
||||
"kind": "KuryrNetPolicy",
|
||||
"metadata": {"name": "np-test-network-policy",
|
||||
"namespace": "default"},
|
||||
"spec": {
|
||||
"egressSgRules": [],
|
||||
"ingressSgRules": [],
|
||||
"networkpolicy_spec": {
|
||||
"ingress": [
|
||||
{"from": [
|
||||
{"namespaceSelector": {
|
||||
"matchLabels": {"name": "dev"}}}],
|
||||
"ports": [
|
||||
{"port": 6379,
|
||||
"protocol": "TCP"}]}],
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"policyTypes": ["Ingress"]},
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"securityGroupId": '36923e76-026c-422b-8dfd-7292e7c88228'}}
|
||||
|
||||
|
||||
def get_crd_obj_with_all_selectors():
|
||||
return {
|
||||
"kind": "KuryrNetPolicy",
|
||||
"metadata": {"name": "np-test-network-policy",
|
||||
"namespace": "default"},
|
||||
"spec": {
|
||||
"egressSgRules": [],
|
||||
"ingressSgRules": [],
|
||||
"networkpolicy_spec": {
|
||||
"ingress": [
|
||||
{"from": [
|
||||
{"namespaceSelector": {
|
||||
"matchLabels": {"name": "dev"}},
|
||||
"podSelector": {
|
||||
"matchLabels": {"tier": "backend"}}}],
|
||||
"ports": [
|
||||
{"port": 6379,
|
||||
"protocol": "TCP"}]}],
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"policyTypes": ["Ingress"]},
|
||||
"podSelector": {"matchLabels": {"app": "demo"}},
|
||||
"securityGroupId": '36923e76-026c-422b-8dfd-7292e7c88228'}}
|
||||
|
||||
|
||||
class TestNamespacePodSecurityGroupsDriver(test_base.TestCase):
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
||||
|
@ -165,3 +290,143 @@ class TestNamespacePodSecurityGroupsDriver(test_base.TestCase):
|
|||
|
||||
cls.delete_sg(m_driver, sg_id)
|
||||
neutron.delete_security_group.assert_called_once_with(sg_id)
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'patch_kuryr_crd')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'delete_security_group_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_delete_namespace_sg_rule(self, m_get_knp_crd, m_delete_sg_rule,
|
||||
m_patch_kuryr_crd):
|
||||
cls = namespace_security_groups.NamespacePodSecurityGroupsDriver
|
||||
m_driver = mock.MagicMock(spec=cls)
|
||||
i_rule = get_matched_crd_obj()['spec']['ingressSgRules'][0]
|
||||
sg_rule_id = i_rule.get('security_group_rule')['id']
|
||||
|
||||
m_get_knp_crd.return_value = {"items": [get_matched_crd_obj()]}
|
||||
|
||||
cls.delete_namespace_sg_rules(m_driver, get_match_crd_namespace_obj())
|
||||
|
||||
m_get_knp_crd.assert_called_once()
|
||||
m_delete_sg_rule.assert_called_once_with(sg_rule_id)
|
||||
m_patch_kuryr_crd.assert_called_once()
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'patch_kuryr_crd')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'delete_security_group_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_delete_namespace_sg_rule_no_match(self, m_get_knp_crd,
|
||||
m_delete_sg_rule,
|
||||
m_patch_kuryr_crd):
|
||||
cls = namespace_security_groups.NamespacePodSecurityGroupsDriver
|
||||
m_driver = mock.MagicMock(spec=cls)
|
||||
|
||||
m_get_knp_crd.return_value = {"items": [get_matched_crd_obj()]}
|
||||
|
||||
cls.delete_namespace_sg_rules(m_driver,
|
||||
get_no_match_crd_namespace_obj())
|
||||
|
||||
m_get_knp_crd.assert_called_once()
|
||||
m_delete_sg_rule.assert_not_called()
|
||||
m_patch_kuryr_crd.assert_not_called()
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
||||
'namespace_security_groups._create_sg_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_selector')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_namespace_subnet_cidr')
|
||||
def test__parse_rules(self, m_get_ns_subnet_cidr, m_match_selector,
|
||||
m_create_sg_rule):
|
||||
crd = get_crd_obj_no_match()
|
||||
policy = crd['spec']['networkpolicy_spec']
|
||||
i_rule = policy.get('ingress')[0]
|
||||
ns_selector = i_rule['from'][0].get('namespaceSelector')
|
||||
ns = get_match_crd_namespace_obj()
|
||||
|
||||
m_get_ns_subnet_cidr.return_value = '10.0.2.0/26'
|
||||
m_match_selector.return_value = True
|
||||
m_create_sg_rule.return_value = get_sg_rule()
|
||||
|
||||
matched, rules = namespace_security_groups._parse_rules('ingress',
|
||||
crd, ns)
|
||||
|
||||
m_get_ns_subnet_cidr.assert_called_once_with(ns)
|
||||
m_match_selector.assert_called_once_with(ns_selector,
|
||||
ns['metadata']['labels'])
|
||||
m_create_sg_rule.assert_called_once()
|
||||
|
||||
self.assertEqual(matched, True)
|
||||
self.assertEqual(rules, [get_sg_rule()])
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
||||
'namespace_security_groups._create_sg_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_selector')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_namespace_subnet_cidr')
|
||||
def test__parse_rules_no_match(self, m_get_ns_subnet_cidr,
|
||||
m_match_selector, m_create_sg_rule):
|
||||
crd = get_crd_obj_no_match()
|
||||
policy = crd['spec']['networkpolicy_spec']
|
||||
i_rule = policy.get('ingress')[0]
|
||||
ns_selector = i_rule['from'][0].get('namespaceSelector')
|
||||
ns = get_no_match_crd_namespace_obj()
|
||||
|
||||
m_get_ns_subnet_cidr.return_value = '10.0.2.0/26'
|
||||
m_match_selector.return_value = False
|
||||
|
||||
matched, rules = namespace_security_groups._parse_rules('ingress',
|
||||
crd, ns)
|
||||
|
||||
m_get_ns_subnet_cidr.assert_called_once_with(ns)
|
||||
m_match_selector.assert_called_once_with(ns_selector,
|
||||
ns['metadata']['labels'])
|
||||
m_create_sg_rule.assert_not_called()
|
||||
|
||||
self.assertEqual(matched, False)
|
||||
self.assertEqual(rules, [])
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
||||
'namespace_security_groups._create_sg_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_pod_ip')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_pods')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_selector')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_namespace_subnet_cidr')
|
||||
def test__parse_rules_all_selectors(self, m_get_ns_subnet_cidr,
|
||||
m_match_selector, m_get_pods,
|
||||
m_get_pod_ip, m_create_sg_rule):
|
||||
crd = get_crd_obj_with_all_selectors()
|
||||
policy = crd['spec']['networkpolicy_spec']
|
||||
i_rule = policy.get('ingress')[0]
|
||||
ns_selector = i_rule['from'][0].get('namespaceSelector')
|
||||
pod_selector = i_rule['from'][0].get('podSelector')
|
||||
ns = get_match_crd_namespace_obj()
|
||||
pod = get_match_crd_pod_obj()
|
||||
|
||||
m_get_ns_subnet_cidr.return_value = '10.0.2.0/26'
|
||||
m_match_selector.return_value = True
|
||||
m_get_pods.return_value = {"items": [pod]}
|
||||
m_get_pod_ip.return_value = pod['status']['podIP']
|
||||
m_create_sg_rule.return_value = get_sg_rule()
|
||||
|
||||
matched, rules = namespace_security_groups._parse_rules('ingress',
|
||||
crd, ns)
|
||||
|
||||
m_get_ns_subnet_cidr.assert_called_once_with(ns)
|
||||
m_match_selector.assert_called_once_with(ns_selector,
|
||||
ns['metadata']['labels'])
|
||||
m_get_pods.assert_called_once_with(pod_selector,
|
||||
ns['metadata']['name'])
|
||||
m_get_pod_ip.assert_called_once_with(pod)
|
||||
m_create_sg_rule.assert_called_once()
|
||||
|
||||
self.assertEqual(matched, True)
|
||||
self.assertEqual(rules, [get_sg_rule()])
|
||||
|
|
|
@ -302,7 +302,7 @@ class TestNetworkPolicyDriver(test_base.TestCase):
|
|||
self.kubernetes.get.side_effect = [{'items': [pod]}, net_crd]
|
||||
|
||||
resp = self._driver._get_namespaces_cidr(namespace_selector)
|
||||
self.assertEqual([subnet_cidr], resp)
|
||||
self.assertEqual(subnet_cidr, resp[0].get('cidr'))
|
||||
self.kubernetes.get.assert_called()
|
||||
|
||||
def test_get_namespaces_cidr_no_matches(self):
|
||||
|
@ -330,7 +330,7 @@ class TestNetworkPolicyDriver(test_base.TestCase):
|
|||
def test_parse_network_policy_rules_with_rules(self, m_create,
|
||||
m_get_ns_cidr):
|
||||
subnet_cidr = '10.10.0.0/24'
|
||||
m_get_ns_cidr.return_value = [subnet_cidr]
|
||||
m_get_ns_cidr.return_value = [{'cidr': subnet_cidr, 'namespace': ''}]
|
||||
self._driver.parse_network_policy_rules(self._policy, self._sg_id)
|
||||
m_create.assert_called()
|
||||
m_get_ns_cidr.assert_called()
|
||||
|
@ -374,7 +374,7 @@ class TestNetworkPolicyDriver(test_base.TestCase):
|
|||
def test_parse_network_policy_rules_with_no_ports(self, m_create,
|
||||
m_get_ns_cidr):
|
||||
subnet_cidr = '10.10.0.0/24'
|
||||
m_get_ns_cidr.return_value = [subnet_cidr]
|
||||
m_get_ns_cidr.return_value = [{'cidr': subnet_cidr, 'namespace': ''}]
|
||||
policy = self._policy.copy()
|
||||
selectors = {'namespaceSelector': {
|
||||
'matchLabels': {
|
||||
|
@ -389,9 +389,11 @@ class TestNetworkPolicyDriver(test_base.TestCase):
|
|||
self._driver.parse_network_policy_rules(policy, self._sg_id)
|
||||
m_get_ns_cidr.assert_called()
|
||||
calls = [mock.call(self._sg_id, 'ingress', port_range_min=1,
|
||||
port_range_max=65535, cidr=subnet_cidr),
|
||||
port_range_max=65535, cidr=subnet_cidr,
|
||||
namespace=''),
|
||||
mock.call(self._sg_id, 'egress', port_range_min=1,
|
||||
port_range_max=65535, cidr=subnet_cidr)]
|
||||
port_range_max=65535, cidr=subnet_cidr,
|
||||
namespace='')]
|
||||
m_create.assert_has_calls(calls)
|
||||
|
||||
def test_knps_on_namespace(self):
|
||||
|
|
|
@ -258,8 +258,8 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
'create_security_group_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'create_security_group_rule_body')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_selector', return_value=True)
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_selector', return_value=True)
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_pod_ip')
|
||||
def test__create_sg_rules(self, m_get_pod_ip,
|
||||
m_match_selector,
|
||||
|
@ -277,16 +277,15 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
policy = crd['spec']['networkpolicy_spec']
|
||||
rule_list = policy.get('ingress', None)
|
||||
crd_rules = crd['spec'].get('ingressSgRules')
|
||||
pod_ns = pod['metadata']['namespace']
|
||||
|
||||
for rule_block in rule_list:
|
||||
for rule in rule_block.get('from', []):
|
||||
namespace_selector = rule.get('namespaceSelector')
|
||||
pod_selector = rule.get('podSelector')
|
||||
matched = network_policy_security_groups._create_sg_rules(
|
||||
crd, pod, namespace_selector, pod_selector, rule_block,
|
||||
crd_rules, 'ingress', matched)
|
||||
new_sg_rule['namespaceSelector'] = namespace_selector
|
||||
new_sg_rule['podSelector'] = pod_selector
|
||||
crd, pod, pod_selector, rule_block,
|
||||
crd_rules, 'ingress', matched, pod_ns)
|
||||
new_sg_rule['namespace'] = pod_ns
|
||||
new_sg_rule['security_group_rule']['id'] = sgr_id
|
||||
m_match_selector.assert_called_once_with(
|
||||
pod_selector, pod['metadata']['labels'])
|
||||
|
@ -296,8 +295,8 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
self.assertEqual([new_sg_rule], crd_rules)
|
||||
self.assertEqual(matched, True)
|
||||
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_selector', return_value=False)
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_selector', return_value=False)
|
||||
def test__create_sg_rules_no_match(self, m_match_selector):
|
||||
crd = self._crd_without_rules
|
||||
pod = self._pod2
|
||||
|
@ -308,17 +307,16 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
|
||||
for rule_block in rule_list:
|
||||
for rule in rule_block.get('from', []):
|
||||
namespace_selector = rule.get('namespaceSelector')
|
||||
pod_selector = rule.get('podSelector')
|
||||
matched = network_policy_security_groups._create_sg_rules(
|
||||
crd, pod, namespace_selector, pod_selector, rule_block,
|
||||
crd_rules, 'ingress', False)
|
||||
crd, pod, pod_selector, rule_block,
|
||||
crd_rules, 'ingress', False, self._namespace)
|
||||
self.assertEqual(matched, False)
|
||||
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'patch_kuryr_crd')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'delete_security_group_rule')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_pod_ip')
|
||||
|
@ -347,8 +345,8 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
crd, i_rules, e_rules, crd['spec'].get('podSelector'))
|
||||
|
||||
@mock.patch('kuryr_kubernetes.config.CONF')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_get_sgs_for_pod_without_label(self, m_get_crds, m_cfg):
|
||||
m_get_crds.return_value = self._crds
|
||||
sg_list = [str(mock.sentinel.sg_id)]
|
||||
|
@ -360,12 +358,12 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
m_get_crds.assert_called_once_with(namespace=self._namespace)
|
||||
self.assertEqual(sg_list, sgs)
|
||||
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_expressions')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_labels')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_expressions')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_labels')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_get_sgs_for_pod_with_label(self, m_get_crds, m_match_labels,
|
||||
m_match_expressions):
|
||||
m_get_crds.return_value = self._crds
|
||||
|
@ -382,12 +380,12 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
self.assertEqual(resp, [str(self._sg_id)])
|
||||
|
||||
@mock.patch('kuryr_kubernetes.config.CONF')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_expressions')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_labels')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_expressions')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_labels')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_get_sgs_for_pod_with_label_no_match(self, m_get_crds,
|
||||
m_match_labels,
|
||||
m_match_expressions, m_cfg):
|
||||
|
@ -407,8 +405,8 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
self._crd['spec']['podSelector']['matchLabels'], pod_labels)
|
||||
self.assertEqual(sg_list, sgs)
|
||||
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_get_sgs_no_crds(self, m_get_crds):
|
||||
m_get_crds.return_value = self._empty_crds
|
||||
cfg.CONF.set_override('pod_security_groups', [],
|
||||
|
@ -419,12 +417,12 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
|||
self._project_id)
|
||||
m_get_crds.assert_called_with(namespace=self._namespace)
|
||||
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_expressions')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_match_labels')
|
||||
@mock.patch.object(network_policy_security_groups,
|
||||
'_get_kuryrnetpolicy_crds')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_expressions')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'match_labels')
|
||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||
'get_kuryrnetpolicy_crds')
|
||||
def test_get_sgs_multiple_crds(self, m_get_crds, m_match_labels,
|
||||
m_match_expressions):
|
||||
m_match_expressions.return_value = True
|
||||
|
|
Loading…
Reference in New Issue