diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index 10695ecc8f8..e1ef4d37bc4 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index 600d1ac7dae..7e4d1447690 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index d5a3fc74ea2..5a83c9d3472 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index 69122ca2644..0ea90788f60 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/antrea-kind.yml b/build/yamls/antrea-kind.yml index 1b7ba036a0f..adac09b64ab 100644 --- a/build/yamls/antrea-kind.yml +++ b/build/yamls/antrea-kind.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index 773da37195c..c7aa211f861 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -616,6 +616,30 @@ spec: match: type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -787,6 +811,30 @@ spec: - Self type: string type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1447,6 +1495,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: @@ -1586,6 +1658,30 @@ spec: matchLabels: x-kubernetes-preserve-unknown-fields: true type: object + nodeSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true + type: object podSelector: properties: matchExpressions: diff --git a/build/yamls/base/crds.yml b/build/yamls/base/crds.yml index eb653d73fd5..689cd48b12c 100644 --- a/build/yamls/base/crds.yml +++ b/build/yamls/base/crds.yml @@ -993,6 +993,30 @@ spec: required: - name - namespace + nodeSelector: + type: object + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true name: type: string enableLogging: @@ -1164,6 +1188,30 @@ spec: required: - name - namespace + nodeSelector: + type: object + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true toServices: type: array items: @@ -1418,6 +1466,30 @@ spec: cidr: type: string format: cidr + nodeSelector: + type: object + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true name: type: string enableLogging: @@ -1561,6 +1633,30 @@ spec: format: cidr fqdn: type: string + nodeSelector: + type: object + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + enum: + - In + - NotIn + - Exists + - DoesNotExist + type: string + values: + items: + type: string + pattern: "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" + type: array + type: object + type: array + matchLabels: + x-kubernetes-preserve-unknown-fields: true toServices: type: array items: diff --git a/cmd/antrea-controller/controller.go b/cmd/antrea-controller/controller.go index 60a726591af..121c44b8e01 100644 --- a/cmd/antrea-controller/controller.go +++ b/cmd/antrea-controller/controller.go @@ -145,6 +145,7 @@ func run(o *Options) error { namespaceInformer, serviceInformer, networkPolicyInformer, + nodeInformer, cnpInformer, anpInformer, tierInformer, diff --git a/docs/antrea-network-policy.md b/docs/antrea-network-policy.md index af3a6be54dc..a22827e74fa 100644 --- a/docs/antrea-network-policy.md +++ b/docs/antrea-network-policy.md @@ -35,6 +35,7 @@ - [K8s clusters with version 1.21 and above](#k8s-clusters-with-version-121-and-above) - [K8s clusters with version 1.20 and below](#k8s-clusters-with-version-120-and-below) - [FQDN based filtering](#fqdn-based-filtering) +- [Node Selector](#node-selector) - [toServices instruction](#toservices-instruction) - [ServiceAccount based selection](#serviceaccount-based-selection) - [RBAC](#rbac) @@ -531,7 +532,7 @@ Usage of ClusterGroups along with stand-alone selectors is not allowed. ### Behavior of *to* and *from* selectors -There are six kinds of selectors that can be specified in an ingress `from` +There are seven kinds of selectors that can be specified in an ingress `from` section or egress `to` section: **podSelector**: This selects particular Pods from all Namespaces as "sources", @@ -545,6 +546,10 @@ with `namespaces` field. specifies both namespaceSelector and podSelector selects particular Pods within particular Namespaces. +**nodeSelector**: This selects particular Nodes in cluster. The selected Node's +IPs will set as "sources" if `nodeSelector` set in `ingress` section, or as +"destinations" if set in `egress` section. + **namespaces**: A `namespaces` field allows users to perform advanced matching on Namespace objects which cannot be done via label selectors. Currently, the `namespaces` field has only one matching strategy, `Self`. If set to `Self`, it indicates @@ -1102,6 +1107,35 @@ spec: - fqdn: "svcA.default.svc.cluster.local" ``` +## Node Selector + +NodeSelector selects certain Nodes which match the label selector. It adds Node IPs to egress rules in `to` field +or ingress rules in `from` filed. +The following rule applies to Pods with label `app=antrea-test-app` and will `Drop` egress traffic to +Nodes which have the labels `node-role.kubernetes.io/control-plane`. + +```yaml +apiVersion: crd.antrea.io/v1alpha1 +kind: ClusterNetworkPolicy +metadata: + name: egress-control-plane +spec: + priority: 1 + appliedTo: + - podSelector: + matchLabels: + app: antrea-test-app + egress: + - action: Drop + to: + - nodeSelector: + matchLabels: + node-role.kubernetes.io/control-plane: "" + ports: + - protocol: TCP + port: 6443 +``` + ## toServices instruction A combination of Service name and Service Namespace can be used in `toServices` to refer to a Service. diff --git a/pkg/agent/controller/networkpolicy/networkpolicy_controller.go b/pkg/agent/controller/networkpolicy/networkpolicy_controller.go index 3396f10738e..4789aa60cb5 100644 --- a/pkg/agent/controller/networkpolicy/networkpolicy_controller.go +++ b/pkg/agent/controller/networkpolicy/networkpolicy_controller.go @@ -377,7 +377,7 @@ func (c *Controller) GetNetworkPolicies(npFilter *querier.NetworkPolicyQueryFilt return c.ruleCache.getNetworkPolicies(npFilter) } -// GetAppliedToNetworkPolicies returns the NetworkPolicies applied to the Pod and match the filter. +// GetAppliedNetworkPolicies returns the NetworkPolicies applied to the Pod and match the filter. func (c *Controller) GetAppliedNetworkPolicies(pod, namespace string, npFilter *querier.NetworkPolicyQueryFilter) []v1beta2.NetworkPolicy { return c.ruleCache.getAppliedNetworkPolicies(pod, namespace, npFilter) } diff --git a/pkg/apis/crd/v1alpha1/types.go b/pkg/apis/crd/v1alpha1/types.go index 12cc33f2eb4..2d4dde26054 100644 --- a/pkg/apis/crd/v1alpha1/types.go +++ b/pkg/apis/crd/v1alpha1/types.go @@ -439,6 +439,12 @@ type NetworkPolicyPeer struct { // Cannot be set with any other selector. // +optional ServiceAccount *NamespacedName `json:"serviceAccount,omitempty"` + // Select certain Nodes which match the label selector, + // if no nodeSelector is specified, then no additional Nodes IPs will be added + // in egress/ingress rules. + // A NodeSelector cannot be set in AppliedTo field or set with any other selector. + // +optional + NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty"` } type PeerNamespaces struct { diff --git a/pkg/apis/crd/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/crd/v1alpha1/zz_generated.deepcopy.go index 345650c66db..3b72cc18ac1 100644 --- a/pkg/apis/crd/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/crd/v1alpha1/zz_generated.deepcopy.go @@ -319,6 +319,11 @@ func (in *NetworkPolicyPeer) DeepCopyInto(out *NetworkPolicyPeer) { *out = new(NamespacedName) **out = **in } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/controller/egress/controller.go b/pkg/controller/egress/controller.go index 0cd162ffe08..d5e7a00f37b 100644 --- a/pkg/controller/egress/controller.go +++ b/pkg/controller/egress/controller.go @@ -404,7 +404,7 @@ func (c *EgressController) addEgress(obj interface{}) { } c.egressGroupStore.Create(egressGroup) // Register the group to the grouping interface. - groupSelector := antreatypes.NewGroupSelector("", egress.Spec.AppliedTo.PodSelector, egress.Spec.AppliedTo.NamespaceSelector, nil) + groupSelector := antreatypes.NewGroupSelector("", egress.Spec.AppliedTo.PodSelector, egress.Spec.AppliedTo.NamespaceSelector, nil, nil) c.groupingInterface.AddGroup(egressGroupType, egress.Name, groupSelector) c.queue.Add(egress.Name) } @@ -417,7 +417,7 @@ func (c *EgressController) updateEgress(old, cur interface{}) { // TODO: Define custom Equal function to be more efficient. if !reflect.DeepEqual(oldEgress.Spec.AppliedTo, curEgress.Spec.AppliedTo) { // Update the group's selector in the grouping interface. - groupSelector := antreatypes.NewGroupSelector("", curEgress.Spec.AppliedTo.PodSelector, curEgress.Spec.AppliedTo.NamespaceSelector, nil) + groupSelector := antreatypes.NewGroupSelector("", curEgress.Spec.AppliedTo.PodSelector, curEgress.Spec.AppliedTo.NamespaceSelector, nil, nil) c.groupingInterface.AddGroup(egressGroupType, curEgress.Name, groupSelector) } if oldEgress.GetGeneration() != curEgress.GetGeneration() { diff --git a/pkg/controller/grouping/group_entity_index_test.go b/pkg/controller/grouping/group_entity_index_test.go index be0515d474e..89342df074e 100644 --- a/pkg/controller/grouping/group_entity_index_test.go +++ b/pkg/controller/grouping/group_entity_index_test.go @@ -47,14 +47,14 @@ var ( nsDefault = newNamespace("default", map[string]string{"company": "default"}) nsOther = newNamespace("other", map[string]string{"company": "other"}) // Fake groups - groupPodFooType1 = &group{groupType: groupType1, groupName: "groupPodFooType1", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil)} - groupPodFooType2 = &group{groupType: groupType2, groupName: "groupPodFooType2", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil)} - groupPodBarType1 = &group{groupType: groupType1, groupName: "groupPodBarType1", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "bar"}}, nil, nil)} - groupEEFooType1 = &group{groupType: groupType1, groupName: "groupEEFooType1", groupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}})} - groupEEFooType2 = &group{groupType: groupType2, groupName: "groupEEFooType2", groupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}})} - groupPodFooAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupPodFooAllNamespaceType1", groupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil)} - groupPodAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupPodAllNamespaceType1", groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil)} - groupEEFooAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupEEFooAllNamespaceType1", groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{}, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}})} + groupPodFooType1 = &group{groupType: groupType1, groupName: "groupPodFooType1", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil)} + groupPodFooType2 = &group{groupType: groupType2, groupName: "groupPodFooType2", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil)} + groupPodBarType1 = &group{groupType: groupType1, groupName: "groupPodBarType1", groupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "bar"}}, nil, nil, nil)} + groupEEFooType1 = &group{groupType: groupType1, groupName: "groupEEFooType1", groupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil)} + groupEEFooType2 = &group{groupType: groupType2, groupName: "groupEEFooType2", groupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil)} + groupPodFooAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupPodFooAllNamespaceType1", groupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil)} + groupPodAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupPodAllNamespaceType1", groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil, nil)} + groupEEFooAllNamespaceType1 = &group{groupType: groupType1, groupName: "groupEEFooAllNamespaceType1", groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{}, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil)} ) type group struct { @@ -124,28 +124,28 @@ func TestGroupEntityIndexGetEntities(t *testing.T) { name: "namespace scoped pod selector", existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil), + inputGroupSelector: types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil), expectedPods: []*v1.Pod{podFoo1, podFoo2}, }, { name: "namespace scoped externalEntity selector", existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}), + inputGroupSelector: types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil), expectedExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2}, }, { name: "cluster scoped pod selector", existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil), + inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil), expectedPods: []*v1.Pod{podFoo1, podFoo2, podFoo1InOtherNamespace}, }, { name: "cluster scoped externalEntity selector", existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}), + inputGroupSelector: types.NewGroupSelector("", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil), expectedExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeFoo1InOtherNamespace}, }, { @@ -153,14 +153,14 @@ func TestGroupEntityIndexGetEntities(t *testing.T) { existingNamespaces: []*v1.Namespace{nsDefault, nsOther}, existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil), + inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil, nil), expectedPods: []*v1.Pod{podFoo1InOtherNamespace}, }, { name: "cluster scoped pod selector with namespaceSelector but no namespaces", existingPods: []*v1.Pod{podFoo1, podFoo2, podBar1, podFoo1InOtherNamespace}, existingExternalEntities: []*v1alpha2.ExternalEntity{eeFoo1, eeFoo2, eeBar1, eeFoo1InOtherNamespace}, - inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil), + inputGroupSelector: types.NewGroupSelector("", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil, nil), expectedPods: []*v1.Pod{}, }, } @@ -289,7 +289,7 @@ func TestGroupEntityIndexUpdateGroup(t *testing.T) { for _, ns := range namespaces { index.AddNamespace(ns) } - index.AddGroup(groupType1, "group1", types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil)) + index.AddGroup(groupType1, "group1", types.NewGroupSelector("default", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil)) actualGroups, _ := index.GetGroupsForPod(podFoo1.Namespace, podFoo1.Name) assert.Equal(t, map[GroupType][]string{groupType1: {"group1"}}, actualGroups) actualGroups, _ = index.GetGroupsForExternalEntity(eeFoo1.Namespace, eeFoo1.Name) @@ -298,7 +298,7 @@ func TestGroupEntityIndexUpdateGroup(t *testing.T) { assert.ElementsMatch(t, []*v1.Pod{podFoo1, podFoo2}, actualPods) assert.ElementsMatch(t, []*v1alpha2.ExternalEntity{}, actualExternalEntities) - index.AddGroup(groupType1, "group1", types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}})) + index.AddGroup(groupType1, "group1", types.NewGroupSelector("default", nil, nil, &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil)) actualGroups, _ = index.GetGroupsForPod(podFoo1.Namespace, podFoo1.Name) assert.Equal(t, map[GroupType][]string{}, actualGroups) actualGroups, _ = index.GetGroupsForExternalEntity(eeFoo1.Namespace, eeFoo1.Name) @@ -502,12 +502,12 @@ func TestGroupEntityIndexEventHandlers(t *testing.T) { existingGroups: []*group{groupPodFooType1, groupPodFooAllNamespaceType1, groupPodAllNamespaceType1, { groupType: groupType1, groupName: "groupCompanyDefault", - groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{MatchLabels: nsDefault.Labels}, nil), + groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{MatchLabels: nsDefault.Labels}, nil, nil), }, { groupType: groupType1, groupName: "groupCompanyOther", - groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil), + groupSelector: types.NewGroupSelector("", nil, &metav1.LabelSelector{MatchLabels: nsOther.Labels}, nil, nil), }}, inputEvent: func(i *GroupEntityIndex) { i.AddNamespace(copyAndMutateNamespace(nsDefault, func(namespace *v1.Namespace) { diff --git a/pkg/controller/networkpolicy/antreanetworkpolicy_test.go b/pkg/controller/networkpolicy/antreanetworkpolicy_test.go index efb4f8e1a35..eb5cc430a81 100644 --- a/pkg/controller/networkpolicy/antreanetworkpolicy_test.go +++ b/pkg/controller/networkpolicy/antreanetworkpolicy_test.go @@ -117,7 +117,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -131,7 +131,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -143,7 +143,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns1", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns1", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -202,7 +202,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns2", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns2", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -216,7 +216,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -228,7 +228,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns2", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns2", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 2, @@ -294,9 +294,9 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorA, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -309,9 +309,9 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { }, { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -324,8 +324,8 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { }, }, AppliedToGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorA, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorB, nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("ns3", &selectorA, nil, nil, nil).NormalizedName), }, AppliedToPerRule: true, }, @@ -376,7 +376,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -389,7 +389,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns4", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns4", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -442,11 +442,69 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns5", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns5", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 0, }, + { + name: "rules-with-nodeSelector", + inputPolicy: &crdv1alpha1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Namespace: "ns6", Name: "npF", UID: "uidF"}, + Spec: crdv1alpha1.NetworkPolicySpec{ + AppliedTo: []crdv1alpha1.NetworkPolicyPeer{ + {PodSelector: &selectorA}, + }, + Priority: p10, + Egress: []crdv1alpha1.Rule{ + { + Ports: []crdv1alpha1.NetworkPolicyPort{ + { + Port: &int81, + }, + }, + To: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorB, + }, + }, + Action: &allowAction, + }, + }, + }, + }, + expectedPolicy: &antreatypes.NetworkPolicy{ + UID: "uidF", + Name: "uidF", + SourceRef: &controlplane.NetworkPolicyReference{ + Type: controlplane.AntreaNetworkPolicy, + Namespace: "ns6", + Name: "npF", + UID: "uidF", + }, + Priority: &p10, + TierPriority: &DefaultTierPriority, + Rules: []controlplane.NetworkPolicyRule{ + { + Direction: controlplane.DirectionOut, + To: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns6", nil, nil, nil, &selectorB).NormalizedName)}, + }, + Services: []controlplane.Service{ + { + Protocol: &protocolTCP, + Port: &int81, + }, + }, + Priority: 0, + Action: &allowAction, + }, + }, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("ns6", &selectorA, nil, nil, nil).NormalizedName)}, + }, + expectedAppliedToGroups: 1, + expectedAddressGroups: 1, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -466,7 +524,7 @@ func TestAddANP(t *testing.T) { int80 := intstr.FromInt(80) selectorAll := metav1.LabelSelector{} matchAllPeerEgress := matchAllPeer - matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil).NormalizedName)} + matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil, nil).NormalizedName)} tests := []struct { name string inputPolicy *crdv1alpha1.NetworkPolicy @@ -518,7 +576,7 @@ func TestAddANP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, &selectorD).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, &selectorD, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -530,7 +588,7 @@ func TestAddANP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -579,7 +637,7 @@ func TestAddANP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -592,7 +650,7 @@ func TestAddANP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -616,7 +674,7 @@ func TestAddANP(t *testing.T) { func TestDeleteANP(t *testing.T) { selectorA := metav1.LabelSelector{MatchLabels: map[string]string{"foo1": "bar1"}} anpObj := getANP() - apgID := getNormalizedUID(antreatypes.NewGroupSelector("test-ns", &selectorA, nil, nil).NormalizedName) + apgID := getNormalizedUID(antreatypes.NewGroupSelector("test-ns", &selectorA, nil, nil, nil).NormalizedName) _, npc := newController() npc.addANP(anpObj) npc.deleteANP(anpObj) diff --git a/pkg/controller/networkpolicy/clustergroup.go b/pkg/controller/networkpolicy/clustergroup.go index 3fe25640ed8..e08facc6092 100644 --- a/pkg/controller/networkpolicy/clustergroup.go +++ b/pkg/controller/networkpolicy/clustergroup.go @@ -142,7 +142,7 @@ func (c *NetworkPolicyController) processClusterGroup(cg *crdv1alpha3.ClusterGro Name: svcSelector.Name, } } else { - groupSelector := antreatypes.NewGroupSelector("", cg.Spec.PodSelector, cg.Spec.NamespaceSelector, cg.Spec.ExternalEntitySelector) + groupSelector := antreatypes.NewGroupSelector("", cg.Spec.PodSelector, cg.Spec.NamespaceSelector, cg.Spec.ExternalEntitySelector, nil) internalGroup.Selector = groupSelector } return &internalGroup @@ -356,7 +356,7 @@ func (c *NetworkPolicyController) serviceToGroupSelector(service *v1.Service) *a } // Convert Service.spec.selector to GroupSelector by setting the Namespace to the Service's Namespace // and podSelector to Service's selector. - groupSelector := antreatypes.NewGroupSelector(service.Namespace, &svcPodSelector, nil, nil) + groupSelector := antreatypes.NewGroupSelector(service.Namespace, &svcPodSelector, nil, nil, nil) return groupSelector } diff --git a/pkg/controller/networkpolicy/clustergroup_test.go b/pkg/controller/networkpolicy/clustergroup_test.go index adfb7532fa8..24c74b3257c 100644 --- a/pkg/controller/networkpolicy/clustergroup_test.go +++ b/pkg/controller/networkpolicy/clustergroup_test.go @@ -55,7 +55,7 @@ func TestProcessClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidA", Name: "cgA", - Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil), + Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil, nil), }, }, { @@ -69,7 +69,7 @@ func TestProcessClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidB", Name: "cgB", - Selector: antreatypes.NewGroupSelector("", &selectorB, nil, nil), + Selector: antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil), }, }, { @@ -84,7 +84,7 @@ func TestProcessClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidC", Name: "cgC", - Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil), + Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil, nil), }, }, { @@ -177,7 +177,7 @@ func TestAddClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidA", Name: "cgA", - Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil), + Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil, nil), }, }, { @@ -191,7 +191,7 @@ func TestAddClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidB", Name: "cgB", - Selector: antreatypes.NewGroupSelector("", &selectorB, nil, nil), + Selector: antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil), }, }, { @@ -206,7 +206,7 @@ func TestAddClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidC", Name: "cgC", - Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil), + Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil, nil), }, }, { @@ -274,7 +274,7 @@ func TestUpdateClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidA", Name: "cgA", - Selector: antreatypes.NewGroupSelector("", nil, &selectorB, nil), + Selector: antreatypes.NewGroupSelector("", nil, &selectorB, nil, nil), }, }, { @@ -288,7 +288,7 @@ func TestUpdateClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidA", Name: "cgA", - Selector: antreatypes.NewGroupSelector("", &selectorC, nil, nil), + Selector: antreatypes.NewGroupSelector("", &selectorC, nil, nil, nil), }, }, { @@ -303,7 +303,7 @@ func TestUpdateClusterGroup(t *testing.T) { expectedGroup: &antreatypes.Group{ UID: "uidA", Name: "cgA", - Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil), + Selector: antreatypes.NewGroupSelector("", &selectorC, &selectorD, nil, nil), }, }, { @@ -482,7 +482,7 @@ func TestFilterInternalGroupsForService(t *testing.T) { Name: "svc1", Namespace: metav1.NamespaceDefault, }, - Selector: antreatypes.NewGroupSelector(metav1.NamespaceDefault, &selectorSpec, nil, nil), + Selector: antreatypes.NewGroupSelector(metav1.NamespaceDefault, &selectorSpec, nil, nil, nil), } grp3 := &antreatypes.Group{ UID: "uid3", @@ -492,7 +492,7 @@ func TestFilterInternalGroupsForService(t *testing.T) { Namespace: "test", }, // Selector is out of sync with latest service spec, but the CG should still be returned. - Selector: antreatypes.NewGroupSelector("test", nil, nil, nil), + Selector: antreatypes.NewGroupSelector("test", nil, nil, nil, nil), } grp4 := &antreatypes.Group{ UID: "uid4", @@ -598,13 +598,13 @@ func TestServiceToGroupSelector(t *testing.T) { "service-default-ns", svc1, grp1, - antreatypes.NewGroupSelector(metav1.NamespaceDefault, &selectorSpec, nil, nil), + antreatypes.NewGroupSelector(metav1.NamespaceDefault, &selectorSpec, nil, nil, nil), }, { "service-match-name-and-namespace", svc2, grp2, - antreatypes.NewGroupSelector("test", &selectorSpec, nil, nil), + antreatypes.NewGroupSelector("test", &selectorSpec, nil, nil, nil), }, { "service-without-selectors", @@ -706,17 +706,17 @@ var groups = []antreatypes.Group{ { UID: "groupUID0", Name: "group0", - Selector: antreatypes.NewGroupSelector("test-ns", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil), + Selector: antreatypes.NewGroupSelector("test-ns", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "foo"}}, nil, nil, nil), }, { UID: "groupUID1", Name: "group1", - Selector: antreatypes.NewGroupSelector("test-ns", nil, nil, nil), + Selector: antreatypes.NewGroupSelector("test-ns", nil, nil, nil, nil), }, { UID: "groupUID2", Name: "group2", - Selector: antreatypes.NewGroupSelector("test-ns", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "other"}}, nil, nil), + Selector: antreatypes.NewGroupSelector("test-ns", &metav1.LabelSelector{MatchLabels: map[string]string{"app": "other"}}, nil, nil, nil), }, { UID: "groupUID3", @@ -915,7 +915,7 @@ func TestSyncInternalGroup(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, } actualInternalNetworkPolicy1, exists, _ := npc.internalNetworkPolicyStore.Get(internalNetworkPolicyKeyFunc(cnp1)) require.True(t, exists) @@ -939,7 +939,7 @@ func TestSyncInternalGroup(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil, nil).NormalizedName)}, } actualInternalNetworkPolicy2, exists, _ := npc.internalNetworkPolicyStore.Get(internalNetworkPolicyKeyFunc(cnp2)) require.True(t, exists) @@ -948,7 +948,7 @@ func TestSyncInternalGroup(t *testing.T) { expectedInternalGroup := &antreatypes.Group{ UID: cgUID, Name: cgName, - Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil), + Selector: antreatypes.NewGroupSelector("", nil, &selectorA, nil, nil), MembersComputed: corev1.ConditionTrue, } actualInternalGroup, exists, _ := npc.internalGroupStore.Get(internalGroupKeyFunc(cg)) diff --git a/pkg/controller/networkpolicy/clusternetworkpolicy.go b/pkg/controller/networkpolicy/clusternetworkpolicy.go index c20a18d116c..f837cdf6ab6 100644 --- a/pkg/controller/networkpolicy/clusternetworkpolicy.go +++ b/pkg/controller/networkpolicy/clusternetworkpolicy.go @@ -15,6 +15,8 @@ package networkpolicy import ( + "reflect" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -27,6 +29,7 @@ import ( "antrea.io/antrea/pkg/controller/grouping" "antrea.io/antrea/pkg/controller/networkpolicy/store" antreatypes "antrea.io/antrea/pkg/controller/types" + "antrea.io/antrea/pkg/util/k8s" utilsets "antrea.io/antrea/pkg/util/sets" ) @@ -255,6 +258,86 @@ func (n *NetworkPolicyController) deleteNamespace(old interface{}) { } } +func (c *NetworkPolicyController) filterAGsFromNodeLabels(node *v1.Node) sets.String { + ags := sets.NewString() + addressGroupObjs, _ := c.addressGroupStore.GetByIndex(store.IsNodeAddressGroupIndex, store.IsNodeAddressGroupIndex) + for _, addressGroupObj := range addressGroupObjs { + addressGroup := addressGroupObj.(*antreatypes.AddressGroup) + nodeSelector := addressGroup.Selector.NodeSelector + if nodeSelector.Matches(labels.Set(node.GetLabels())) { + ags.Insert(addressGroup.Name) + } + } + return ags +} + +func (c *NetworkPolicyController) addNode(obj interface{}) { + node := obj.(*v1.Node) + affectedAGs := c.filterAGsFromNodeLabels(node) + for _, key := range affectedAGs.List() { + c.enqueueAddressGroup(key) + } + klog.V(2).InfoS("Processed Node CREATE event", "nodeName", node.Name, "affectedAGs", affectedAGs.Len()) +} + +func (c *NetworkPolicyController) deleteNode(obj interface{}) { + node, ok := obj.(*v1.Node) + if !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + klog.ErrorS(nil, "Processed Node DELETE event error", "obj", obj) + return + } + node, ok = tombstone.Obj.(*v1.Node) + if !ok { + klog.ErrorS(nil, "Processed Node DELETE event error", "obj", tombstone.Obj) + return + } + } + // enqueue affected address group + affectedAGs := c.filterAGsFromNodeLabels(node) + for _, key := range affectedAGs.List() { + c.enqueueAddressGroup(key) + } + klog.V(2).InfoS("Processed Node DELETE event", "nodeName", node.Name, "affectedAGs", affectedAGs.Len()) +} + +func nodeIPChanged(oldNode, newNode *v1.Node) (bool, error) { + oldIPs, err := k8s.GetNodeAddrs(oldNode) + if err != nil { + return false, err + } + newIPs, err := k8s.GetNodeAddrs(newNode) + if err != nil { + return false, err + } + return reflect.DeepEqual(newIPs, oldIPs), nil +} + +func (c *NetworkPolicyController) updateNode(oldObj, newObj interface{}) { + node := newObj.(*v1.Node) + oldNode := oldObj.(*v1.Node) + ipChanged, err := nodeIPChanged(oldNode, node) + if err != nil { + klog.ErrorS(err, "Processed Node UPDATE error", "nodeName", node.Name) + return + } + if reflect.DeepEqual(node.GetLabels(), oldNode.GetLabels()) && !ipChanged { + klog.V(2).InfoS("Processed Node UPDATE event, labels not changed", "nodeName", node.Name) + return + } + oldMatches, newMatches := c.filterAGsFromNodeLabels(oldNode), c.filterAGsFromNodeLabels(node) + if oldMatches.Equal(newMatches) && !ipChanged { + klog.V(2).InfoS("Processed Node UPDATE event, affectedAGs not changed", "nodeName", node.Name) + return + } + affectedAGs := oldMatches.Union(newMatches) + for _, key := range affectedAGs.List() { + c.enqueueAddressGroup(key) + } + klog.V(2).InfoS("Processed Node UPDATE event", "nodeName", node.Name, "affectedAGs", affectedAGs.Len()) +} + // processClusterNetworkPolicy creates an internal NetworkPolicy instance // corresponding to the crdv1alpha1.ClusterNetworkPolicy object. This method // does not commit the internal NetworkPolicy in store, instead returns an diff --git a/pkg/controller/networkpolicy/clusternetworkpolicy_test.go b/pkg/controller/networkpolicy/clusternetworkpolicy_test.go index 1dbf8009d87..2a5b025dc40 100644 --- a/pkg/controller/networkpolicy/clusternetworkpolicy_test.go +++ b/pkg/controller/networkpolicy/clusternetworkpolicy_test.go @@ -153,7 +153,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -167,7 +167,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -179,7 +179,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -237,7 +237,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -251,7 +251,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -263,7 +263,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 2, @@ -322,7 +322,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -336,7 +336,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -348,7 +348,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 2, @@ -395,7 +395,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -408,7 +408,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -474,9 +474,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -489,9 +489,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -504,8 +504,8 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, }, AppliedToGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName), }, AppliedToPerRule: true, }, @@ -593,7 +593,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -661,7 +661,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Direction: controlplane.DirectionIn, AppliedToGroups: []string{cgA.Name}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -676,7 +676,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Direction: controlplane.DirectionOut, AppliedToGroups: []string{cgA.Name}, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -750,9 +750,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -765,9 +765,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -780,9 +780,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorA, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorA, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -795,9 +795,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, }, AppliedToGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", nil, &metav1.LabelSelector{}, nil, nil).NormalizedName), }, AppliedToPerRule: true, PerNamespaceSelectors: []labels.Selector{labels.Everything()}, @@ -870,9 +870,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -885,9 +885,9 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, { Direction: controlplane.DirectionIn, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName)}, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -900,8 +900,8 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { }, }, AppliedToGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsB", nil, nil, nil, nil).NormalizedName), }, AppliedToPerRule: true, PerNamespaceSelectors: []labels.Selector{labelSelectorA, labelSelectorB}, @@ -956,7 +956,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &dropAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 0, @@ -1013,7 +1013,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { Action: &dropAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 0, @@ -1058,13 +1058,13 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, }, Priority: 0, Action: &dropAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -1109,14 +1109,14 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, Priority: 0, Action: &dropAction, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, AppliedToPerRule: true, }, expectedAppliedToGroups: 1, @@ -1172,24 +1172,24 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, nil, nil, nil).NormalizedName)}, }, Priority: 0, Action: &dropAction, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, }, { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorB, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorB, nil, nil).NormalizedName)}, }, Priority: 1, Action: &allowAction, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName)}, }, }, AppliedToGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorD, nil, nil, nil).NormalizedName), }, AppliedToPerRule: true, PerNamespaceSelectors: []labels.Selector{}, @@ -1197,6 +1197,63 @@ func TestProcessClusterNetworkPolicy(t *testing.T) { expectedAppliedToGroups: 1, expectedAddressGroups: 2, }, + { + name: "rule-with-node-selector", + inputPolicy: &crdv1alpha1.ClusterNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "cnpL", UID: "uidL"}, + Spec: crdv1alpha1.ClusterNetworkPolicySpec{ + AppliedTo: []crdv1alpha1.NetworkPolicyPeer{ + {PodSelector: &selectorA}, + }, + Priority: p10, + Egress: []crdv1alpha1.Rule{ + { + Ports: []crdv1alpha1.NetworkPolicyPort{ + { + Port: &int81, + }, + }, + To: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorB, + }, + }, + Action: &dropAction, + }, + }, + }, + }, + expectedPolicy: &antreatypes.NetworkPolicy{ + UID: "uidL", + Name: "uidL", + SourceRef: &controlplane.NetworkPolicyReference{ + Type: controlplane.AntreaClusterNetworkPolicy, + Name: "cnpL", + UID: "uidL", + }, + Priority: &p10, + TierPriority: &DefaultTierPriority, + Rules: []controlplane.NetworkPolicyRule{ + { + Direction: controlplane.DirectionOut, + To: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, nil, nil, &selectorB).NormalizedName)}, + }, + Services: []controlplane.Service{ + { + Protocol: &protocolTCP, + Port: &int81, + }, + }, + Priority: 0, + Action: &dropAction, + }, + }, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, + }, + expectedAppliedToGroups: 1, + expectedAddressGroups: 1, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1247,7 +1304,7 @@ func TestAddCNP(t *testing.T) { selectorC := metav1.LabelSelector{MatchLabels: map[string]string{"foo3": "bar3"}} selectorAll := metav1.LabelSelector{} matchAllPeerEgress := matchAllPeer - matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil).NormalizedName)} + matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil, nil).NormalizedName)} tests := []struct { name string inputPolicy *crdv1alpha1.ClusterNetworkPolicy @@ -1297,7 +1354,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1309,7 +1366,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -1355,7 +1412,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1367,7 +1424,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -1414,7 +1471,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1426,7 +1483,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -1473,7 +1530,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1485,7 +1542,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -1547,7 +1604,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1561,7 +1618,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1573,7 +1630,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -1631,7 +1688,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1645,7 +1702,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1657,7 +1714,7 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 2, @@ -1704,7 +1761,7 @@ func TestAddCNP(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -1717,11 +1774,97 @@ func TestAddCNP(t *testing.T) { Action: &allowAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, }, + { + name: "rules-with-node-selector", + inputPolicy: &crdv1alpha1.ClusterNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "cnpI", UID: "uidI"}, + Spec: crdv1alpha1.ClusterNetworkPolicySpec{ + AppliedTo: []crdv1alpha1.NetworkPolicyPeer{ + {PodSelector: &selectorA}, + }, + Priority: p10, + Ingress: []crdv1alpha1.Rule{ + { + Ports: []crdv1alpha1.NetworkPolicyPort{ + { + Port: &int80, + }, + }, + From: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorB, + }, + }, + Action: &allowAction, + }, + }, + Egress: []crdv1alpha1.Rule{ + { + Ports: []crdv1alpha1.NetworkPolicyPort{ + { + Port: &int81, + }, + }, + To: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorA, + }, + }, + Action: &allowAction, + }, + }, + }, + }, + expPolicy: &antreatypes.NetworkPolicy{ + UID: "uidI", + Name: "uidI", + SourceRef: &controlplane.NetworkPolicyReference{ + Type: controlplane.AntreaClusterNetworkPolicy, + Name: "cnpI", + UID: "uidI", + }, + Priority: &p10, + TierPriority: &DefaultTierPriority, + Rules: []controlplane.NetworkPolicyRule{ + { + Direction: controlplane.DirectionIn, + From: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, nil, nil, &selectorB).NormalizedName)}, + }, + Services: []controlplane.Service{ + { + Protocol: &protocolTCP, + Port: &int80, + }, + }, + Priority: 0, + Action: &allowAction, + }, + { + Direction: controlplane.DirectionOut, + To: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, nil, nil, &selectorA).NormalizedName)}, + }, + Services: []controlplane.Service{ + { + Protocol: &protocolTCP, + Port: &int81, + }, + }, + Priority: 0, + Action: &allowAction, + }, + }, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName)}, + }, + expAppliedToGroups: 1, + expAddressGroups: 2, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1741,15 +1884,15 @@ func TestAddCNP(t *testing.T) { for _, tt := range tests { npc.addCNP(tt.inputPolicy) } - assert.Equal(t, 7, npc.GetNetworkPolicyNum(), "number of NetworkPolicies do not match") - assert.Equal(t, 3, npc.GetAddressGroupNum(), "number of AddressGroups do not match") + assert.Equal(t, 8, npc.GetNetworkPolicyNum(), "number of NetworkPolicies do not match") + assert.Equal(t, 5, npc.GetAddressGroupNum(), "number of AddressGroups do not match") assert.Equal(t, 1, npc.GetAppliedToGroupNum(), "number of AppliedToGroups do not match") } func TestDeleteCNP(t *testing.T) { selectorA := metav1.LabelSelector{MatchLabels: map[string]string{"foo1": "bar1"}} cnpObj := getCNP() - apgID := getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil).NormalizedName) + apgID := getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, nil, nil, nil).NormalizedName) _, npc := newController() npc.addCNP(cnpObj) npc.deleteCNP(cnpObj) diff --git a/pkg/controller/networkpolicy/crd_utils.go b/pkg/controller/networkpolicy/crd_utils.go index 6abf8c41a88..b77a241a236 100644 --- a/pkg/controller/networkpolicy/crd_utils.go +++ b/pkg/controller/networkpolicy/crd_utils.go @@ -87,7 +87,7 @@ func (n *NetworkPolicyController) toAntreaPeerForCRD(peers []v1alpha1.NetworkPol if dir == controlplane.DirectionIn || !namedPortExists { return &matchAllPeer } - allPodsGroupUID := n.createAddressGroup("", matchAllPodsPeerCrd.PodSelector, matchAllPodsPeerCrd.NamespaceSelector, nil) + allPodsGroupUID := n.createAddressGroup("", matchAllPodsPeerCrd.PodSelector, matchAllPodsPeerCrd.NamespaceSelector, nil, nil) podsPeer := matchAllPeer podsPeer.AddressGroups = append(addressGroups, allPodsGroupUID) return &podsPeer @@ -115,10 +115,14 @@ func (n *NetworkPolicyController) toAntreaPeerForCRD(peers []v1alpha1.NetworkPol } else if peer.FQDN != "" { fqdns = append(fqdns, peer.FQDN) } else if peer.ServiceAccount != nil { - normalizedUID := n.createAddressGroup(peer.ServiceAccount.Namespace, serviceAccountNameToPodSelector(peer.ServiceAccount.Name), nil, nil) + normalizedUID := n.createAddressGroup(peer.ServiceAccount.Namespace, serviceAccountNameToPodSelector(peer.ServiceAccount.Name), nil, nil, nil) + addressGroups = append(addressGroups, normalizedUID) + } else if peer.NodeSelector != nil { + normalizedUID := n.createAddressGroup(np.GetNamespace(), peer.PodSelector, peer.NamespaceSelector, + peer.ExternalEntitySelector, peer.NodeSelector) addressGroups = append(addressGroups, normalizedUID) } else { - normalizedUID := n.createAddressGroup(np.GetNamespace(), peer.PodSelector, peer.NamespaceSelector, peer.ExternalEntitySelector) + normalizedUID := n.createAddressGroup(np.GetNamespace(), peer.PodSelector, peer.NamespaceSelector, peer.ExternalEntitySelector, nil) addressGroups = append(addressGroups, normalizedUID) } } @@ -131,7 +135,7 @@ func (n *NetworkPolicyController) toAntreaPeerForCRD(peers []v1alpha1.NetworkPol func (n *NetworkPolicyController) toNamespacedPeerForCRD(peers []v1alpha1.NetworkPolicyPeer, namespace string) *controlplane.NetworkPolicyPeer { var addressGroups []string for _, peer := range peers { - normalizedUID := n.createAddressGroup(namespace, peer.PodSelector, nil, peer.ExternalEntitySelector) + normalizedUID := n.createAddressGroup(namespace, peer.PodSelector, nil, peer.ExternalEntitySelector, nil) addressGroups = append(addressGroups, normalizedUID) } return &controlplane.NetworkPolicyPeer{AddressGroups: addressGroups} diff --git a/pkg/controller/networkpolicy/crd_utils_test.go b/pkg/controller/networkpolicy/crd_utils_test.go index a4aab9bb46d..82ba1abceab 100644 --- a/pkg/controller/networkpolicy/crd_utils_test.go +++ b/pkg/controller/networkpolicy/crd_utils_test.go @@ -151,7 +151,7 @@ func TestToAntreaPeerForCRD(t *testing.T) { selectorC := metav1.LabelSelector{MatchLabels: map[string]string{"foo3": "bar3"}} selectorAll := metav1.LabelSelector{} matchAllPodsPeer := matchAllPeer - matchAllPodsPeer.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil).NormalizedName)} + matchAllPodsPeer.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil, nil).NormalizedName)} // cgA with selector present in cache cgA := crdv1alpha3.ClusterGroup{ ObjectMeta: metav1.ObjectMeta{Name: "cgA", UID: "uidA"}, @@ -180,8 +180,8 @@ func TestToAntreaPeerForCRD(t *testing.T) { }, outPeer: controlplane.NetworkPolicyPeer{ AddressGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, &selectorB, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, &selectorB, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil, nil).NormalizedName), }, }, direction: controlplane.DirectionIn, @@ -199,8 +199,8 @@ func TestToAntreaPeerForCRD(t *testing.T) { }, outPeer: controlplane.NetworkPolicyPeer{ AddressGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, &selectorB, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorA, &selectorB, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("", &selectorC, nil, nil, nil).NormalizedName), }, }, direction: controlplane.DirectionOut, @@ -280,6 +280,34 @@ func TestToAntreaPeerForCRD(t *testing.T) { }, direction: controlplane.DirectionOut, }, + { + name: "node-selector-peer-ingress", + inPeers: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorA, + }, + }, + outPeer: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{ + getNormalizedUID(antreatypes.NewGroupSelector("", nil, nil, nil, &selectorA).NormalizedName), + }, + }, + direction: controlplane.DirectionIn, + }, + { + name: "node-selector-peer-egress", + inPeers: []crdv1alpha1.NetworkPolicyPeer{ + { + NodeSelector: &selectorA, + }, + }, + outPeer: controlplane.NetworkPolicyPeer{ + AddressGroups: []string{ + getNormalizedUID(antreatypes.NewGroupSelector("", nil, nil, nil, &selectorA).NormalizedName), + }, + }, + direction: controlplane.DirectionOut, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/controller/networkpolicy/networkpolicy_controller.go b/pkg/controller/networkpolicy/networkpolicy_controller.go index 7c5da125c82..0eb8af670d0 100644 --- a/pkg/controller/networkpolicy/networkpolicy_controller.go +++ b/pkg/controller/networkpolicy/networkpolicy_controller.go @@ -30,6 +30,7 @@ import ( v1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" @@ -173,6 +174,13 @@ type NetworkPolicyController struct { // once. cgListerSynced cache.InformerSynced + nodeInformer coreinformers.NodeInformer + // nodeLister is able to list/get Nodes and is populated by the shared informer passed to + // NewNetworkPolicyController. + nodeLister corelisters.NodeLister + // nodeListerSynced is a function which returns true if the Node shared informer has been synced at least once. + nodeListerSynced cache.InformerSynced + // addressGroupStore is the storage where the populated Address Groups are stored. addressGroupStore storage.Interface // appliedToGroupStore is the storage where the populated AppliedTo Groups are stored. @@ -289,6 +297,7 @@ func NewNetworkPolicyController(kubeClient clientset.Interface, namespaceInformer coreinformers.NamespaceInformer, serviceInformer coreinformers.ServiceInformer, networkPolicyInformer networkinginformers.NetworkPolicyInformer, + nodeInformer coreinformers.NodeInformer, cnpInformer secinformers.ClusterNetworkPolicyInformer, anpInformer secinformers.NetworkPolicyInformer, tierInformer secinformers.TierInformer, @@ -334,6 +343,9 @@ func NewNetworkPolicyController(kubeClient clientset.Interface, n.serviceInformer = serviceInformer n.serviceLister = serviceInformer.Lister() n.serviceListerSynced = serviceInformer.Informer().HasSynced + n.nodeInformer = nodeInformer + n.nodeLister = nodeInformer.Lister() + n.nodeListerSynced = nodeInformer.Informer().HasSynced n.cnpInformer = cnpInformer n.cnpLister = cnpInformer.Lister() n.cnpListerSynced = cnpInformer.Informer().HasSynced @@ -363,6 +375,15 @@ func NewNetworkPolicyController(kubeClient clientset.Interface, }, resyncPeriod, ) + // Add handlers for Node events. + nodeInformer.Informer().AddEventHandlerWithResyncPeriod( + cache.ResourceEventHandlerFuncs{ + AddFunc: n.addNode, + UpdateFunc: n.updateNode, + DeleteFunc: n.deleteNode, + }, + resyncPeriod, + ) tierInformer.Informer().AddIndexers(tierIndexers) cnpInformer.Informer().AddIndexers(cnpIndexers) cnpInformer.Informer().AddEventHandlerWithResyncPeriod( @@ -434,7 +455,7 @@ func getNormalizedUID(name string) string { // createAppliedToGroup creates an AppliedToGroup object in store if it is not created already. func (n *NetworkPolicyController) createAppliedToGroup(npNsName string, pSel, nSel, eSel *metav1.LabelSelector) string { - groupSelector := antreatypes.NewGroupSelector(npNsName, pSel, nSel, eSel) + groupSelector := antreatypes.NewGroupSelector(npNsName, pSel, nSel, eSel, nil) appliedToGroupUID := getNormalizedUID(groupSelector.NormalizedName) // Get or create a AppliedToGroup for the generated UID. // Ignoring returned error (here and elsewhere in this file) as with the @@ -460,8 +481,8 @@ func (n *NetworkPolicyController) createAppliedToGroup(npNsName string, pSel, nS // NetworkPolicyPeer object in NetworkPolicyRule. This function simply // creates the object without actually populating the PodAddresses as the // affected GroupMembers are calculated during sync process. -func (n *NetworkPolicyController) createAddressGroup(namespace string, podSelector, nsSelector, eeSelector *metav1.LabelSelector) string { - groupSelector := antreatypes.NewGroupSelector(namespace, podSelector, nsSelector, eeSelector) +func (n *NetworkPolicyController) createAddressGroup(namespace string, podSelector, nsSelector, eeSelector, nodeSelector *metav1.LabelSelector) string { + groupSelector := antreatypes.NewGroupSelector(namespace, podSelector, nsSelector, eeSelector, nodeSelector) normalizedUID := getNormalizedUID(groupSelector.NormalizedName) // Get or create an AddressGroup for the generated UID. _, found, _ := n.addressGroupStore.Get(normalizedUID) @@ -621,7 +642,7 @@ func (n *NetworkPolicyController) toAntreaPeer(peers []networkingv1.NetworkPolic if dir == controlplane.DirectionIn || !namedPortExists { return &matchAllPeer } - allPodsGroupUID := n.createAddressGroup(np.Namespace, matchAllPodsPeer.PodSelector, matchAllPodsPeer.NamespaceSelector, nil) + allPodsGroupUID := n.createAddressGroup(np.Namespace, matchAllPodsPeer.PodSelector, matchAllPodsPeer.NamespaceSelector, nil, nil) podsPeer := matchAllPeer podsPeer.AddressGroups = append(addressGroups, allPodsGroupUID) return &podsPeer @@ -638,7 +659,7 @@ func (n *NetworkPolicyController) toAntreaPeer(peers []networkingv1.NetworkPolic } ipBlocks = append(ipBlocks, *ipBlock) } else { - normalizedUID := n.createAddressGroup(np.Namespace, peer.PodSelector, peer.NamespaceSelector, nil) + normalizedUID := n.createAddressGroup(np.Namespace, peer.PodSelector, peer.NamespaceSelector, nil, nil) addressGroups = append(addressGroups, normalizedUID) } } @@ -1043,6 +1064,11 @@ func (n *NetworkPolicyController) syncAddressGroup(key string) error { utilsets.MergeString(addrGroupNodeNames, internalNP.SpanMeta.NodeNames) } memberSet := n.getAddressGroupMemberSet(addressGroup) + if addressGroup.Selector.NodeSelector != nil { + ms, _ := n.addNodeSelectorMemberSet(addressGroup.Selector.NodeSelector) + memberSet = memberSet.Union(ms) + // TODO: AddressGroup shouldn't contain PodIP and NodeIP at the same time to avoid complexity. + } updatedAddressGroup := &antreatypes.AddressGroup{ Name: addressGroup.Name, UID: addressGroup.UID, @@ -1055,6 +1081,18 @@ func (n *NetworkPolicyController) syncAddressGroup(key string) error { return nil } +func (c *NetworkPolicyController) addNodeSelectorMemberSet(selector labels.Selector) (controlplane.GroupMemberSet, sets.String) { + groupMemberSet := controlplane.GroupMemberSet{} + nodes, _ := c.nodeLister.List(selector) + nList := sets.String{} + for _, node := range nodes { + groupMemberSet.Insert(nodeToGroupMember(node)) + nList.Insert(node.Name) + } + klog.V(2).InfoS("Select node", "nList", nList, "groupMemberSet", groupMemberSet, "selector", selector) + return groupMemberSet, nList +} + // getAddressGroupMemberSet knows how to construct a GroupMemberSet that contains // all the entities selected by an AddressGroup. func (n *NetworkPolicyController) getAddressGroupMemberSet(g *antreatypes.AddressGroup) controlplane.GroupMemberSet { @@ -1137,6 +1175,21 @@ func podToGroupMember(pod *v1.Pod, includeIP bool) *controlplane.GroupMember { return memberPod } +func nodeToGroupMember(node *v1.Node) *controlplane.GroupMember { + member := &controlplane.GroupMember{} + nodeIPs, err := k8s.GetNodeAddrs(node) + if err != nil { + return nil + } + if nodeIPs.IPv4 != nil { + member.IPs = append(member.IPs, ipStrToIPAddress(nodeIPs.IPv4.String())) + } + if nodeIPs.IPv6 != nil { + member.IPs = append(member.IPs, ipStrToIPAddress(nodeIPs.IPv6.String())) + } + return member +} + func externalEntityToGroupMember(ee *v1alpha2.ExternalEntity) *controlplane.GroupMember { memberEntity := &controlplane.GroupMember{} namedPorts := make([]controlplane.NamedPort, len(ee.Spec.Ports)) diff --git a/pkg/controller/networkpolicy/networkpolicy_controller_test.go b/pkg/controller/networkpolicy/networkpolicy_controller_test.go index d2a431f1aff..29b0f1b757d 100644 --- a/pkg/controller/networkpolicy/networkpolicy_controller_test.go +++ b/pkg/controller/networkpolicy/networkpolicy_controller_test.go @@ -16,6 +16,7 @@ package networkpolicy import ( "bytes" + "context" "fmt" "net" "reflect" @@ -30,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" k8stesting "k8s.io/client-go/testing" @@ -106,6 +108,7 @@ func newController(objects ...runtime.Object) (*fake.Clientset, *networkPolicyCo informerFactory.Core().V1().Namespaces(), informerFactory.Core().V1().Services(), informerFactory.Networking().V1().NetworkPolicies(), + informerFactory.Core().V1().Nodes(), crdInformerFactory.Crd().V1alpha1().ClusterNetworkPolicies(), crdInformerFactory.Crd().V1alpha1().NetworkPolicies(), crdInformerFactory.Crd().V1alpha1().Tiers(), @@ -230,7 +233,7 @@ func TestAddNetworkPolicy(t *testing.T) { selectorC := metav1.LabelSelector{MatchLabels: map[string]string{"foo3": "bar3"}} selectorAll := metav1.LabelSelector{} matchAllPeerEgress := matchAllPeer - matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil).NormalizedName)} + matchAllPeerEgress.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil, nil).NormalizedName)} tests := []struct { name string inputPolicy *networkingv1.NetworkPolicy @@ -264,7 +267,7 @@ func TestAddNetworkPolicy(t *testing.T) { Priority: defaultRulePriority, Action: &defaultAction, }}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 0, @@ -295,7 +298,7 @@ func TestAddNetworkPolicy(t *testing.T) { Priority: defaultRulePriority, Action: &defaultAction, }}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 0, @@ -340,7 +343,7 @@ func TestAddNetworkPolicy(t *testing.T) { Priority: defaultRulePriority, Action: &defaultAction, }}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -366,7 +369,7 @@ func TestAddNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ denyAllIngressRule, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 0, @@ -392,7 +395,7 @@ func TestAddNetworkPolicy(t *testing.T) { Rules: []controlplane.NetworkPolicyRule{ denyAllEgressRule, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 0, @@ -448,7 +451,7 @@ func TestAddNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -462,7 +465,7 @@ func TestAddNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -474,7 +477,7 @@ func TestAddNetworkPolicy(t *testing.T) { Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -526,7 +529,7 @@ func TestAddNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -540,7 +543,7 @@ func TestAddNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -552,7 +555,7 @@ func TestAddNetworkPolicy(t *testing.T) { Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 2, @@ -594,7 +597,7 @@ func TestAddNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -607,7 +610,7 @@ func TestAddNetworkPolicy(t *testing.T) { Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -639,7 +642,7 @@ func TestDeleteNetworkPolicy(t *testing.T) { ns := npObj.ObjectMeta.Namespace pSelector := npObj.Spec.PodSelector pLabelSelector, _ := metav1.LabelSelectorAsSelector(&pSelector) - apgID := getNormalizedUID(antreatypes.GenerateNormalizedName(ns, pLabelSelector, nil, nil)) + apgID := getNormalizedUID(antreatypes.GenerateNormalizedName(ns, pLabelSelector, nil, nil, nil)) _, npc := newController() npc.addNetworkPolicy(npObj) npc.deleteNetworkPolicy(npObj) @@ -728,7 +731,7 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, @@ -736,13 +739,13 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 2, @@ -778,13 +781,13 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -820,13 +823,13 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 1, @@ -849,7 +852,7 @@ func TestUpdateNetworkPolicy(t *testing.T) { UID: "uidA", }, Rules: []controlplane.NetworkPolicyRule{}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 0, @@ -901,7 +904,7 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, @@ -909,7 +912,7 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorA, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorA, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, @@ -917,13 +920,13 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 3, @@ -968,7 +971,7 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, @@ -976,13 +979,13 @@ func TestUpdateNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, Priority: defaultRulePriority, Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expAppliedToGroups: 1, expAddressGroups: 2, @@ -1439,9 +1442,9 @@ func TestAddPod(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { npc.groupingInterface.AddPod(tt.addedPod) - appGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorSpec, nil, nil).NormalizedName) - inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorIn, nil, nil).NormalizedName) - outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorOut, nil, nil).NormalizedName) + appGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorSpec, nil, nil, nil).NormalizedName) + inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorIn, nil, nil, nil).NormalizedName) + outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorOut, nil, nil, nil).NormalizedName) npc.syncAppliedToGroup(appGroupID) npc.syncAddressGroup(inGroupID) npc.syncAddressGroup(outGroupID) @@ -1483,7 +1486,7 @@ func TestDeletePod(t *testing.T) { inPSelector := metav1.LabelSelector{ MatchLabels: ruleLabels, } - matchAppGID := getNormalizedUID(antreatypes.GenerateNormalizedName(ns, mLabelSelector, nil, nil)) + matchAppGID := getNormalizedUID(antreatypes.GenerateNormalizedName(ns, mLabelSelector, nil, nil, nil)) ingressRules := []networkingv1.NetworkPolicyIngressRule{ { From: []networkingv1.NetworkPolicyPeer{ @@ -1686,8 +1689,8 @@ func TestAddNamespace(t *testing.T) { p2 := getPod("p2", "nsA", "nodeA", "2.2.3.4", false) npc.groupingInterface.AddPod(p1) npc.groupingInterface.AddPod(p2) - inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorIn, nil).NormalizedName) - outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorOut, nil).NormalizedName) + inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorIn, nil, nil).NormalizedName) + outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorOut, nil, nil).NormalizedName) npc.syncAddressGroup(inGroupID) npc.syncAddressGroup(outGroupID) npc.syncInternalGroup(groupKey) @@ -1843,8 +1846,8 @@ func TestDeleteNamespace(t *testing.T) { npc.groupingInterface.AddPod(p1) npc.groupingInterface.AddPod(p2) npc.groupingInterface.DeleteNamespace(tt.deletedNamespace) - inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorIn, nil).NormalizedName) - outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorOut, nil).NormalizedName) + inGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorIn, nil, nil).NormalizedName) + outGroupID := getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorOut, nil, nil).NormalizedName) npc.syncAddressGroup(inGroupID) npc.syncAddressGroup(outGroupID) npc.syncInternalGroup(groupKey) @@ -2085,7 +2088,7 @@ func TestToGroupSelector(t *testing.T) { Namespace: "nsName", NamespaceSelector: nil, PodSelector: pLabelSelector, - NormalizedName: antreatypes.GenerateNormalizedName("nsName", pLabelSelector, nil, nil), + NormalizedName: antreatypes.GenerateNormalizedName("nsName", pLabelSelector, nil, nil, nil), }, }, { @@ -2097,7 +2100,7 @@ func TestToGroupSelector(t *testing.T) { Namespace: "", NamespaceSelector: nLabelSelector, PodSelector: nil, - NormalizedName: antreatypes.GenerateNormalizedName("", nil, nLabelSelector, nil), + NormalizedName: antreatypes.GenerateNormalizedName("", nil, nLabelSelector, nil, nil), }, }, { @@ -2109,7 +2112,7 @@ func TestToGroupSelector(t *testing.T) { Namespace: "nsName", NamespaceSelector: nil, PodSelector: pLabelSelector, - NormalizedName: antreatypes.GenerateNormalizedName("nsName", pLabelSelector, nil, nil), + NormalizedName: antreatypes.GenerateNormalizedName("nsName", pLabelSelector, nil, nil, nil), }, }, { @@ -2121,13 +2124,13 @@ func TestToGroupSelector(t *testing.T) { Namespace: "", NamespaceSelector: nLabelSelector, PodSelector: pLabelSelector, - NormalizedName: antreatypes.GenerateNormalizedName("", pLabelSelector, nLabelSelector, nil), + NormalizedName: antreatypes.GenerateNormalizedName("", pLabelSelector, nLabelSelector, nil, nil), }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - group := antreatypes.NewGroupSelector(tt.namespace, tt.podSelector, tt.nsSelector, nil) + group := antreatypes.NewGroupSelector(tt.namespace, tt.podSelector, tt.nsSelector, nil, nil) if group.Namespace != tt.expGroupSelector.Namespace { t.Errorf("Group Namespace incorrectly set. Expected %s, got: %s", tt.expGroupSelector.Namespace, group.Namespace) } @@ -2207,7 +2210,7 @@ func TestGenerateNormalizedName(t *testing.T) { }, } for _, table := range tables { - name := antreatypes.GenerateNormalizedName(table.namespace, table.pSelector, table.nSelector, nil) + name := antreatypes.GenerateNormalizedName(table.namespace, table.pSelector, table.nSelector, nil, nil) if table.expName != name { t.Errorf("Unexpected normalized name. Expected %s, got %s", table.expName, name) } @@ -2345,7 +2348,7 @@ func TestToAntreaPeer(t *testing.T) { selectorC := metav1.LabelSelector{MatchLabels: map[string]string{"foo3": "bar3"}} selectorAll := metav1.LabelSelector{} matchAllPodsPeer := matchAllPeer - matchAllPodsPeer.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil).NormalizedName)} + matchAllPodsPeer.AddressGroups = []string{getNormalizedUID(antreatypes.NewGroupSelector("", nil, &selectorAll, nil, nil).NormalizedName)} tests := []struct { name string inPeers []networkingv1.NetworkPolicyPeer @@ -2366,8 +2369,8 @@ func TestToAntreaPeer(t *testing.T) { }, outPeer: controlplane.NetworkPolicyPeer{ AddressGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, &selectorB, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorC, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, &selectorB, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorC, nil, nil, nil).NormalizedName), }, }, direction: controlplane.DirectionIn, @@ -2385,8 +2388,8 @@ func TestToAntreaPeer(t *testing.T) { }, outPeer: controlplane.NetworkPolicyPeer{ AddressGroups: []string{ - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, &selectorB, nil).NormalizedName), - getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorC, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, &selectorB, nil, nil).NormalizedName), + getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorC, nil, nil, nil).NormalizedName), }, }, direction: controlplane.DirectionOut, @@ -2533,7 +2536,7 @@ func TestProcessNetworkPolicy(t *testing.T) { Priority: defaultRulePriority, Action: &defaultAction, }}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 0, @@ -2557,7 +2560,7 @@ func TestProcessNetworkPolicy(t *testing.T) { UID: "uidA", }, Rules: []controlplane.NetworkPolicyRule{denyAllEgressRule}, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &metav1.LabelSelector{}, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 0, @@ -2613,7 +2616,7 @@ func TestProcessNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -2627,7 +2630,7 @@ func TestProcessNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionOut, To: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -2639,7 +2642,7 @@ func TestProcessNetworkPolicy(t *testing.T) { Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 1, @@ -2691,7 +2694,7 @@ func TestProcessNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorB, nil, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -2705,7 +2708,7 @@ func TestProcessNetworkPolicy(t *testing.T) { { Direction: controlplane.DirectionIn, From: controlplane.NetworkPolicyPeer{ - AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, &selectorC, nil).NormalizedName)}, + AddressGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", nil, &selectorC, nil, nil).NormalizedName)}, }, Services: []controlplane.Service{ { @@ -2717,7 +2720,7 @@ func TestProcessNetworkPolicy(t *testing.T) { Action: &defaultAction, }, }, - AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil).NormalizedName)}, + AppliedToGroups: []string{getNormalizedUID(antreatypes.NewGroupSelector("nsA", &selectorA, nil, nil, nil).NormalizedName)}, }, expectedAppliedToGroups: 1, expectedAddressGroups: 2, @@ -3271,6 +3274,58 @@ func TestGetAddressGroupMemberSet(t *testing.T) { } } +func TestAddNodeSelector(t *testing.T) { + stopCh := make(chan struct{}) + defer close(stopCh) + _, c := newController() + c.informerFactory.Start(stopCh) + c.crdInformerFactory.Start(stopCh) + go c.groupingController.Run(stopCh) + go c.groupingInterface.Run(stopCh) + c.informerFactory.WaitForCacheSync(stopCh) + c.crdInformerFactory.WaitForCacheSync(stopCh) + cache.WaitForCacheSync(stopCh, c.groupingInterfaceSynced) + + nodeSelectorA := metav1.LabelSelector{MatchLabels: map[string]string{"env": "pro"}} + nodeSelectorB := metav1.LabelSelector{MatchLabels: map[string]string{"env": "test"}} + + fakeNode1 := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "fakeNode0"}, + Status: corev1.NodeStatus{Addresses: []corev1.NodeAddress{{Type: corev1.NodeInternalIP, Address: "1.1.1.1"}}}, + } + fakeNode2 := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "fakeNode1"}, + Status: corev1.NodeStatus{Addresses: []corev1.NodeAddress{{Type: corev1.NodeInternalIP, Address: "1.1.1.2"}}}, + } + createNode := func(node *corev1.Node) error { + _, err := c.kubeClient.CoreV1().Nodes().Create(context.TODO(), node, metav1.CreateOptions{}) + if err != nil { + return err + } + assert.NoError(t, wait.Poll(time.Millisecond*100, time.Second, func() (done bool, err error) { + newNode, err := c.nodeLister.Get(node.Name) + return reflect.DeepEqual(node, newNode), err + })) + return nil + } + fakeNode1.Labels = nodeSelectorA.MatchLabels + fakeNode2.Labels = nodeSelectorB.MatchLabels + assert.NoError(t, createNode(fakeNode1)) + assert.NoError(t, createNode(fakeNode2)) + + agID := c.createAddressGroup("", nil, nil, nil, &nodeSelectorA) + + assert.NoError(t, c.syncAddressGroup(agID)) + addrGroupObj, _, err := c.addressGroupStore.Get(agID) + assert.NoError(t, err) + addrGroup := addrGroupObj.(*antreatypes.AddressGroup) + groupMembers := addrGroup.GroupMembers + memberNode1 := &controlplane.GroupMember{IPs: []controlplane.IPAddress{ipStrToIPAddress("1.1.1.1")}} + memberNode2 := &controlplane.GroupMember{IPs: []controlplane.IPAddress{ipStrToIPAddress("1.1.1.2")}} + assert.True(t, groupMembers.Has(memberNode1)) + assert.False(t, groupMembers.Has(memberNode2)) +} + func getK8sNetworkPolicyObj() *networkingv1.NetworkPolicy { ns := metav1.NamespaceDefault npName := "testing-1" diff --git a/pkg/controller/networkpolicy/store/addressgroup.go b/pkg/controller/networkpolicy/store/addressgroup.go index edac6b8d6ba..bb7924f931e 100644 --- a/pkg/controller/networkpolicy/store/addressgroup.go +++ b/pkg/controller/networkpolicy/store/addressgroup.go @@ -28,6 +28,8 @@ import ( "antrea.io/antrea/pkg/controller/types" ) +const IsNodeAddressGroupIndex = "isNodeSelector" + // addressGroupEvent implements storage.InternalEvent. type addressGroupEvent struct { // The current version of the stored AddressGroup. @@ -161,6 +163,13 @@ func NewAddressGroupStore() storage.Interface { // ag.Selector.Namespace == "" means it's a cluster scoped group, we index it as it is. return []string{ag.Selector.Namespace}, nil }, + IsNodeAddressGroupIndex: func(obj interface{}) ([]string, error) { + ag, ok := obj.(*types.AddressGroup) + if !ok || ag.Selector.NodeSelector == nil { + return []string{}, nil + } + return []string{IsNodeAddressGroupIndex}, nil + }, } return ram.NewStore(AddressGroupKeyFunc, indexers, genAddressGroupEvent, keyAndSpanSelectFunc, func() runtime.Object { return new(controlplane.AddressGroup) }) } diff --git a/pkg/controller/networkpolicy/validate.go b/pkg/controller/networkpolicy/validate.go index 2188bf7d8a8..1b74687b43b 100644 --- a/pkg/controller/networkpolicy/validate.go +++ b/pkg/controller/networkpolicy/validate.go @@ -515,7 +515,10 @@ func (v *antreaPolicyValidator) validatePeers(ingress, egress []crdv1alpha1.Rule if peer.ServiceAccount != nil && peerFieldsNum > 1 { return "serviceAccount cannot be set with other peers in rules", false } - if reason, allowed := checkSelectorsLabels(peer.PodSelector, peer.NamespaceSelector, peer.ExternalEntitySelector); !allowed { + if peer.NodeSelector != nil && peerFieldsNum > 1 { + return "nodeSelector cannot be set with other peers in rules", false + } + if reason, allowed := checkSelectorsLabels(peer.PodSelector, peer.NamespaceSelector, peer.ExternalEntitySelector, peer.NodeSelector); !allowed { return reason, allowed } } diff --git a/pkg/controller/types/group.go b/pkg/controller/types/group.go index 7bf89974ae9..544b8e2bd7e 100644 --- a/pkg/controller/types/group.go +++ b/pkg/controller/types/group.go @@ -49,27 +49,36 @@ type GroupSelector struct { // If Namespace and NamespaceSelector both are unset, it selects the ExternalEntities in all the Namespaces. // TODO: Add validation in API to not allow externalEntitySelector and podSelector in the same group. ExternalEntitySelector labels.Selector + + // This is a label selector which selects certain Node IPs. Within a group NodeSelector cannot be set concurrently with + // other selectors: Namespace/NamespaceSelector/PodSelector/ExternalEntitySelector. + NodeSelector labels.Selector } -func NewGroupSelector(namespace string, podSelector, nsSelector, extEntitySelector *metav1.LabelSelector) *GroupSelector { +// NewGroupSelector converts the podSelector, namespaceSelector, externalEntitySelector and nodeSelector +// and NetworkPolicy Namespace to a networkpolicy.GroupSelector object. +func NewGroupSelector(namespace string, podSelector, nsSelector, extEntitySelector, nodeSelector *metav1.LabelSelector) *GroupSelector { groupSelector := GroupSelector{} if podSelector != nil { - pSelector, _ := metav1.LabelSelectorAsSelector(podSelector) - groupSelector.PodSelector = pSelector + groupSelector.PodSelector, _ = metav1.LabelSelectorAsSelector(podSelector) } if extEntitySelector != nil { - eSelector, _ := metav1.LabelSelectorAsSelector(extEntitySelector) - groupSelector.ExternalEntitySelector = eSelector + groupSelector.ExternalEntitySelector, _ = metav1.LabelSelectorAsSelector(extEntitySelector) } if nsSelector == nil { // No namespaceSelector indicates that the pods must be selected within // the NetworkPolicy's Namespace. groupSelector.Namespace = namespace } else { - nSelector, _ := metav1.LabelSelectorAsSelector(nsSelector) - groupSelector.NamespaceSelector = nSelector + groupSelector.NamespaceSelector, _ = metav1.LabelSelectorAsSelector(nsSelector) + } + + if nodeSelector != nil { + groupSelector.NodeSelector, _ = metav1.LabelSelectorAsSelector(nodeSelector) } - name := GenerateNormalizedName(groupSelector.Namespace, groupSelector.PodSelector, groupSelector.NamespaceSelector, groupSelector.ExternalEntitySelector) + + name := GenerateNormalizedName(groupSelector.Namespace, groupSelector.PodSelector, + groupSelector.NamespaceSelector, groupSelector.ExternalEntitySelector, groupSelector.NodeSelector) groupSelector.NormalizedName = name return &groupSelector } @@ -78,7 +87,7 @@ func NewGroupSelector(namespace string, podSelector, nsSelector, extEntitySelect // the following format: "namespace=NamespaceName And podSelector=normalizedPodSelector". // Note: Namespace and nsSelector may or may not be set depending on the // selector. However, they cannot be set simultaneously. -func GenerateNormalizedName(namespace string, podSelector, nsSelector, eeSelector labels.Selector) string { +func GenerateNormalizedName(namespace string, podSelector, nsSelector, eeSelector labels.Selector, nodeSelector labels.Selector) string { normalizedName := []string{} if nsSelector != nil { normalizedName = append(normalizedName, fmt.Sprintf("namespaceSelector=%s", nsSelector.String())) @@ -91,6 +100,9 @@ func GenerateNormalizedName(namespace string, podSelector, nsSelector, eeSelecto if eeSelector != nil { normalizedName = append(normalizedName, fmt.Sprintf("eeSelector=%s", eeSelector.String())) } + if nodeSelector != nil { + normalizedName = append(normalizedName, fmt.Sprintf("nodeSelector=%s", nodeSelector.String())) + } sort.Strings(normalizedName) return strings.Join(normalizedName, " And ") } diff --git a/test/e2e/antreapolicy_test.go b/test/e2e/antreapolicy_test.go index 52dec43a4f9..20728301b16 100644 --- a/test/e2e/antreapolicy_test.go +++ b/test/e2e/antreapolicy_test.go @@ -44,13 +44,13 @@ import ( // common for all tests. var ( - allPods []Pod - podsByNamespace map[string][]Pod - k8sUtils *KubernetesUtils - allTestList []*TestCase - pods, namespaces []string - podIPs map[string][]string - p80, p81, p8080, p8081, p8082, p8085 int32 + allPods []Pod + podsByNamespace map[string][]Pod + k8sUtils *KubernetesUtils + allTestList []*TestCase + pods, namespaces []string + podIPs map[string][]string + p80, p81, p8080, p8081, p8082, p8085, p6443 int32 ) const ( @@ -2227,7 +2227,7 @@ func testACNPNamespaceIsolation(t *testing.T) { builder2 = builder2.SetName("test-acnp-ns-isolation-applied-to-per-rule"). SetTier("baseline"). SetPriority(1.0) - //SetAppliedToGroup([]ACNPAppliedToSpec{{NSSelector: map[string]string{"ns": "x"}}}) + // SetAppliedToGroup([]ACNPAppliedToSpec{{NSSelector: map[string]string{"ns": "x"}}}) builder2.AddEgress(v1.ProtocolTCP, nil, nil, nil, nil, nil, nil, nil, nil, true, []ACNPAppliedToSpec{{NSSelector: map[string]string{"ns": "x"}}}, crdv1alpha1.RuleActionAllow, "", "", nil) builder2.AddEgress(v1.ProtocolTCP, nil, nil, nil, nil, nil, map[string]string{}, nil, nil, @@ -2616,6 +2616,49 @@ func testServiceAccountSelector(t *testing.T, data *TestData) { time.Sleep(networkPolicyDelay) } +func testACNPNodeSelector(t *testing.T) { + builder := &ClusterNetworkPolicySpecBuilder{} + builder = builder.SetName("test-acnp-drop-egress-control-plane"). + SetPriority(1.0) + nodeSelector := metav1.LabelSelector{MatchLabels: map[string]string{"kubernetes.io/hostname": controlPlaneNodeName()}} + builder.AddNodeSelectorRule(&nodeSelector, v1.ProtocolTCP, &p6443, "egress-control-plane-drop", + []ACNPAppliedToSpec{{NSSelector: map[string]string{"ns": "x"}, PodSelector: map[string]string{"pod": "a"}}}, + crdv1alpha1.RuleActionDrop) + + testcases := []podToAddrTestStep{ + { + "x/a", + controlPlaneNodeIPv4(), + 6443, + Dropped, + }, + { + "x/b", + controlPlaneNodeIPv4(), + 6443, + Connected, + }, + } + _, err := k8sUtils.CreateOrUpdateACNP(builder.Get()) + failOnError(err, t) + time.Sleep(networkPolicyDelay) + for _, tc := range testcases { + log.Tracef("Probing: %s -> %s", tc.clientPod.PodName(), tc.destAddr) + connectivity, err := k8sUtils.ProbeAddr(tc.clientPod.Namespace(), "pod", tc.clientPod.PodName(), tc.destAddr, tc.destPort, v1.ProtocolTCP) + if err != nil { + t.Errorf("failure -- could not complete probe: %v", err) + } + if connectivity != tc.expectedConnectivity { + t.Errorf("failure -- wrong results for probe: Source %s/%s --> Dest %s:%d connectivity: %v, expected: %v", + tc.clientPod.Namespace(), tc.clientPod.PodName(), tc.destAddr, tc.destPort, connectivity, tc.expectedConnectivity) + } + } + // cleanup test resources + failOnError(k8sUtils.DeleteACNP(builder.Name), t) + failOnError(waitForResourceDelete("", builder.Name, resourceACNP, timeout), t) + time.Sleep(networkPolicyDelay) +} + // executeTests runs all the tests in testList and prints results func executeTests(t *testing.T, testList []*TestCase) { executeTestsWithData(t, testList, nil) @@ -2946,6 +2989,7 @@ func TestAntreaPolicy(t *testing.T) { t.Run("Case=FQDNPolicyInCluster", func(t *testing.T) { testFQDNPolicyInClusterService(t) }) t.Run("Case=ACNPToServices", func(t *testing.T) { testToServices(t) }) t.Run("Case=ACNPServiceAccountSelector", func(t *testing.T) { testServiceAccountSelector(t, data) }) + t.Run("Case=ACNPNodeSelector", func(t *testing.T) { testACNPNodeSelector(t) }) }) // print results for reachability tests printResults() diff --git a/test/e2e/utils/cnpspecbuilder.go b/test/e2e/utils/cnpspecbuilder.go index 1f92f7ba929..9ab4350a8c2 100644 --- a/test/e2e/utils/cnpspecbuilder.go +++ b/test/e2e/utils/cnpspecbuilder.go @@ -218,6 +218,27 @@ func (b *ClusterNetworkPolicySpecBuilder) AddEgress(protoc v1.Protocol, return b } +func (b *ClusterNetworkPolicySpecBuilder) AddNodeSelectorRule(nodeSelector *metav1.LabelSelector, protoc v1.Protocol, port *int32, name string, + ruleAppliedToSpecs []ACNPAppliedToSpec, action crdv1alpha1.RuleAction) *ClusterNetworkPolicySpecBuilder { + var appliedTos []crdv1alpha1.NetworkPolicyPeer + for _, at := range ruleAppliedToSpecs { + appliedTos = append(appliedTos, b.GetAppliedToPeer(at.PodSelector, at.NSSelector, at.PodSelectorMatchExp, at.NSSelectorMatchExp, at.Group)) + } + policyPeer := []crdv1alpha1.NetworkPolicyPeer{{NodeSelector: nodeSelector}} + + newRule := crdv1alpha1.Rule{ + To: policyPeer, + Ports: []crdv1alpha1.NetworkPolicyPort{ + {Protocol: &protoc, Port: &intstr.IntOrString{IntVal: *port}}, + }, + Action: &action, + Name: name, + AppliedTo: appliedTos, + } + b.Spec.Egress = append(b.Spec.Egress, newRule) + return b +} + func (b *ClusterNetworkPolicySpecBuilder) AddFQDNRule(fqdn string, protoc v1.Protocol, port *int32, portName *string, endPort *int32, name string, ruleAppliedToSpecs []ACNPAppliedToSpec, action crdv1alpha1.RuleAction) *ClusterNetworkPolicySpecBuilder {