Skip to content

Commit

Permalink
Add antrea controller logic
Browse files Browse the repository at this point in the history
Signed-off-by: abhiraut <[email protected]>
  • Loading branch information
abhiraut committed Aug 6, 2021
1 parent 2b85c01 commit 07405b4
Show file tree
Hide file tree
Showing 22 changed files with 1,627 additions and 292 deletions.
2 changes: 2 additions & 0 deletions cmd/antrea-controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func run(o *Options) error {
tfInformer := crdInformerFactory.Crd().V1alpha1().Traceflows()
cgv1a2Informer := crdInformerFactory.Crd().V1alpha2().ClusterGroups()
cgInformer := crdInformerFactory.Crd().V1alpha3().ClusterGroups()
gInformer := crdInformerFactory.Crd().V1alpha3().Groups()
egressInformer := crdInformerFactory.Crd().V1alpha2().Egresses()
externalIPPoolInformer := crdInformerFactory.Crd().V1alpha2().ExternalIPPools()

Expand Down Expand Up @@ -160,6 +161,7 @@ func run(o *Options) error {
anpInformer,
tierInformer,
cgInformer,
gInformer,
addressGroupStore,
appliedToGroupStore,
networkPolicyStore,
Expand Down
16 changes: 16 additions & 0 deletions pkg/apis/controlplane/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,19 @@ func (r *NetworkPolicyReference) ToString() string {
return fmt.Sprintf("%s:%s/%s", r.Type, r.Namespace, r.Name)
}
}

func (r *GroupReference) ToString() string {
if r.Namespace == "" {
return r.Name
}
return fmt.Sprintf("%s/%s", r.Namespace, r.Name)
}

// ToTypedString returns the Group or ClusterGroup namespaced name as a string along with its type.
// Typical usage of typed string will be to use in log messages.
func (r *GroupReference) ToTypedString() string {
if r.Namespace == "" {
return fmt.Sprintf("ClusterGroup: %s", r.Name)
}
return fmt.Sprintf("Group: %s/%s", r.Namespace, r.Name)
}
115 changes: 115 additions & 0 deletions pkg/apis/controlplane/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2021 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package controlplane

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestGroupReferenceToString(t *testing.T) {
tests := []struct {
name string
inGroupRef *GroupReference
out string
}{
{
name: "cg-ref",
inGroupRef: &GroupReference{
Namespace: "",
Name: "cgA",
},
out: "cgA",
},
{
name: "g-ref",
inGroupRef: &GroupReference{
Namespace: "nsA",
Name: "gA",
},
out: "nsA/gA",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualOut := tt.inGroupRef.ToString()
assert.Equal(t, tt.out, actualOut)
})
}
}

func TestGroupReferenceToTypedString(t *testing.T) {
tests := []struct {
name string
inGroupRef *GroupReference
out string
}{
{
name: "cg-ref",
inGroupRef: &GroupReference{
Namespace: "",
Name: "cgA",
},
out: "ClusterGroup: cgA",
},
{
name: "g-ref",
inGroupRef: &GroupReference{
Namespace: "nsA",
Name: "gA",
},
out: "Group: nsA/gA",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualOut := tt.inGroupRef.ToTypedString()
assert.Equal(t, tt.out, actualOut)
})
}
}

func TestNetworkPolicyReferenceToString(t *testing.T) {
tests := []struct {
name string
inNPRef *NetworkPolicyReference
out string
}{
{
name: "acnp-ref",
inNPRef: &NetworkPolicyReference{
Type: AntreaClusterNetworkPolicy,
Namespace: "",
Name: "acnpA",
},
out: "AntreaClusterNetworkPolicy:acnpA",
},
{
name: "anp-ref",
inNPRef: &NetworkPolicyReference{
Type: AntreaNetworkPolicy,
Namespace: "nsA",
Name: "anpA",
},
out: "AntreaNetworkPolicy:nsA/anpA",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualOut := tt.inNPRef.ToString()
assert.Equal(t, tt.out, actualOut)
})
}
}
2 changes: 2 additions & 0 deletions pkg/apis/crd/v1alpha3/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ClusterGroup{},
&ClusterGroupList{},
&Group{},
&GroupList{},
)

metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
Expand Down
3 changes: 0 additions & 3 deletions pkg/apis/crd/v1alpha3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ type ServiceReference struct {
// ClusterGroupReference represent reference to a ClusterGroup.
type ClusterGroupReference string

// GroupReference represent reference to a Group.
type GroupReference string

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type ClusterGroupList struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions)
items := make([]controlplane.GroupReference, 0, len(groups))
for i := range groups {
item := controlplane.GroupReference{
Name: groups[i].Name,
Name: groups[i].SourceReference.Name,
UID: groups[i].UID,
}
items = append(items, item)
Expand Down
21 changes: 15 additions & 6 deletions pkg/apiserver/registry/networkpolicy/groupassociation/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,27 @@ func TestRESTGet(t *testing.T) {
groups := map[string][]antreatypes.Group{
"default/podA": {
{
UID: "groupUID1",
Name: "cg1",
UID: "groupUID1",
SourceReference: &controlplane.GroupReference{
Name: "cg1",
UID: "groupUID1",
},
},
},
"default/podB": {
{
UID: "groupUID2",
Name: "cg2",
UID: "groupUID2",
SourceReference: &controlplane.GroupReference{
Name: "cg2",
UID: "groupUID2",
},
},
{
UID: "groupUID3",
Name: "cg3",
UID: "groupUID3",
SourceReference: &controlplane.GroupReference{
Name: "cg3",
UID: "groupUID3",
},
},
},
}
Expand Down
65 changes: 50 additions & 15 deletions pkg/controller/networkpolicy/antreanetworkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,22 +130,17 @@ func (n *NetworkPolicyController) processAntreaNetworkPolicy(np *crdv1alpha1.Net
// The span calculation and stale appliedToGroup cleanup logic would work seamlessly for both cases.
appliedToGroupNamesSet := sets.String{}
// Create AppliedToGroup for each AppliedTo present in AntreaNetworkPolicy spec.
for _, at := range np.Spec.AppliedTo {
appliedToGroupNamesSet.Insert(n.createAppliedToGroup(
np.Namespace, at.PodSelector, at.NamespaceSelector, at.ExternalEntitySelector))
}

n.processAppliedTo(np.Namespace, np.Spec.AppliedTo, appliedToGroupNamesSet)
rules := make([]controlplane.NetworkPolicyRule, 0, len(np.Spec.Ingress)+len(np.Spec.Egress))
// Compute NetworkPolicyRule for Ingress Rule.
for idx, ingressRule := range np.Spec.Ingress {
// Set default action to ALLOW to allow traffic.
services, namedPortExists := toAntreaServicesForCRD(ingressRule.Ports)
var appliedToGroupNamesForRule []string
// Create AppliedToGroup for each AppliedTo present in the ingress rule.
for _, at := range ingressRule.AppliedTo {
atGroup := n.createAppliedToGroup(np.Namespace, at.PodSelector, at.NamespaceSelector, at.ExternalEntitySelector)
appliedToGroupNamesForRule = append(appliedToGroupNamesForRule, atGroup)
appliedToGroupNamesSet.Insert(atGroup)
}
atGroups := n.processAppliedTo(np.Namespace, ingressRule.AppliedTo, appliedToGroupNamesSet)
appliedToGroupNamesForRule = append(appliedToGroupNamesForRule, atGroups...)
rules = append(rules, controlplane.NetworkPolicyRule{
Direction: controlplane.DirectionIn,
From: *n.toAntreaPeerForCRD(ingressRule.From, np, controlplane.DirectionIn, namedPortExists),
Expand All @@ -162,12 +157,9 @@ func (n *NetworkPolicyController) processAntreaNetworkPolicy(np *crdv1alpha1.Net
// Set default action to ALLOW to allow traffic.
services, namedPortExists := toAntreaServicesForCRD(egressRule.Ports)
var appliedToGroupNamesForRule []string
// Create AppliedToGroup for each AppliedTo present in the ingress rule.
for _, at := range egressRule.AppliedTo {
atGroup := n.createAppliedToGroup(np.Namespace, at.PodSelector, at.NamespaceSelector, at.ExternalEntitySelector)
appliedToGroupNamesForRule = append(appliedToGroupNamesForRule, atGroup)
appliedToGroupNamesSet.Insert(atGroup)
}
// Create AppliedToGroup for each AppliedTo present in the egress rule.
atGroups := n.processAppliedTo(np.Namespace, egressRule.AppliedTo, appliedToGroupNamesSet)
appliedToGroupNamesForRule = append(appliedToGroupNamesForRule, atGroups...)
rules = append(rules, controlplane.NetworkPolicyRule{
Direction: controlplane.DirectionOut,
To: *n.toAntreaPeerForCRD(egressRule.To, np, controlplane.DirectionOut, namedPortExists),
Expand Down Expand Up @@ -198,3 +190,46 @@ func (n *NetworkPolicyController) processAntreaNetworkPolicy(np *crdv1alpha1.Net
}
return internalNetworkPolicy
}

func (n *NetworkPolicyController) processAppliedTo(namespace string, appliedTo []crdv1alpha1.NetworkPolicyPeer, appliedToGroupNamesSet sets.String) []string {
var appliedToGroupNames []string
for _, at := range appliedTo {
var atg string
if at.Group != "" {
atg = n.processAppliedToGroupForG(namespace, at.Group)
} else {
atg = n.createAppliedToGroup(namespace, at.PodSelector, at.NamespaceSelector, at.ExternalEntitySelector)
}
if atg != "" {
appliedToGroupNames = append(appliedToGroupNames, atg)
appliedToGroupNamesSet.Insert(atg)
}
}
return appliedToGroupNames
}

func (n *NetworkPolicyController) processAppliedToGroupForG(namespace, groupName string) string {
// Retrieve Group for corresponding entry in the AppliedToGroup.
g, err := n.gLister.Groups(namespace).Get(groupName)
if err != nil {
// This error should not occur as we validate that a Group must exist before
// referencing it in an ANP.
klog.Errorf("Group %s not found: %v", g, err)
return ""
}
key := internalGroupKeyFunc(g)
// Find the internal Group corresponding to this Group
ig, found, _ := n.internalGroupStore.Get(key)
if !found {
// Internal Group was not found. Once the internal Group is created, the sync
// worker for internal group will re-enqueue the ClusterNetworkPolicy processing
// which will trigger the creation of AddressGroup.
return ""
}
intGrp := ig.(*antreatypes.Group)
if len(intGrp.IPBlocks) > 0 || intGrp.Selector.NamespaceSelector != nil {
klog.V(2).Infof("Group %s with IPBlocks or NamespaceSelector will not be processed as AppliedTo", g)
return ""
}
return n.createAppliedToGroupForInternalGroup(intGrp)
}
74 changes: 74 additions & 0 deletions pkg/controller/networkpolicy/antreanetworkpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package networkpolicy

import (
crdv1alpha3 "antrea.io/antrea/pkg/apis/crd/v1alpha3"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -560,6 +562,78 @@ func TestDeleteANP(t *testing.T) {
assert.False(t, found, "expected internal NetworkPolicy to be deleted")
}

func TestProcessAppliedToGroupsForG(t *testing.T) {
selectorA := metav1.LabelSelector{MatchLabels: map[string]string{"foo1": "bar1"}}
cidr := "10.0.0.0/24"
// gA with selector present in cache
gA := crdv1alpha3.Group{
ObjectMeta: metav1.ObjectMeta{Namespace: "nsA", Name: "gA", UID: "uidA"},
Spec: crdv1alpha3.GroupSpec{
PodSelector: &selectorA,
},
}
// gB with IPBlock present in cache
gB := crdv1alpha3.Group{
ObjectMeta: metav1.ObjectMeta{Namespace: "nsB", Name: "gB", UID: "uidB"},
Spec: crdv1alpha3.GroupSpec{
IPBlocks: []crdv1alpha1.IPBlock{
{
CIDR: cidr,
},
},
},
}
// gC not found in cache
gC := crdv1alpha3.Group{
ObjectMeta: metav1.ObjectMeta{Namespace: "nsC", Name: "gC", UID: "uidC"},
Spec: crdv1alpha3.GroupSpec{
NamespaceSelector: &selectorA,
},
}
_, npc := newController()
npc.addGroup(&gA)
npc.addGroup(&gB)
npc.gStore.Add(&gA)
npc.gStore.Add(&gB)
tests := []struct {
name string
namespace string
inputG string
expectedAG string
}{
{
name: "empty-grp-no-result",
namespace: "nsA",
inputG: "",
expectedAG: "",
},
{
name: "ipblock-grp-no-result",
namespace: "nsB",
inputG: gB.Name,
expectedAG: "",
},
{
name: "selector-grp-missing-no-result",
namespace: "nsC",
inputG: gC.Name,
expectedAG: "",
},
{
name: "selector-grp",
namespace: "nsA",
inputG: gA.Name,
expectedAG: fmt.Sprintf("%s/%s", gA.Namespace, gA.Name),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualAG := npc.processAppliedToGroupForG(tt.namespace, tt.inputG)
assert.Equal(t, tt.expectedAG, actualAG, "appliedToGroup list does not match")
})
}
}

// util functions for testing.
func getANP() *crdv1alpha1.NetworkPolicy {
p10 := float64(10)
Expand Down
Loading

0 comments on commit 07405b4

Please sign in to comment.