Skip to content

Commit

Permalink
Support querying NetworkPolicies applied to a Pod in Agent API/antctl
Browse files Browse the repository at this point in the history
Look up NetworkPolicies from the NetworkPolicyController cache from:
Pod -> AppliedToGroups -> Rules -> NetworkPolicies.
Revise NetworkPolicyController NetworkPolicy lookup funcs.
antctl command to get NetworkPolicies of a Pod:
  antctl get netpol -p pod -n ns.
  • Loading branch information
jianjuns committed Apr 28, 2020
1 parent 1409292 commit 2f061ac
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 51 deletions.
2 changes: 1 addition & 1 deletion pkg/agent/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *agentAPIServer) Run(stopCh <-chan struct{}) error {
func installHandlers(aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier, s *genericapiserver.GenericAPIServer) {
s.Handler.NonGoRestfulMux.HandleFunc("/agentinfo", agentinfo.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/podinterfaces", podinterface.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/networkpolicies", networkpolicy.HandleFunc(npq))
s.Handler.NonGoRestfulMux.HandleFunc("/networkpolicies", networkpolicy.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/appliedtogroups", appliedtogroup.HandleFunc(npq))
s.Handler.NonGoRestfulMux.HandleFunc("/addressgroups", addressgroup.HandleFunc(npq))
s.Handler.NonGoRestfulMux.HandleFunc("/ovsflows", ovsflows.HandleFunc(aq))
Expand Down
42 changes: 25 additions & 17 deletions pkg/agent/apiserver/handlers/networkpolicy/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,48 @@ import (
"encoding/json"
"net/http"

"github.com/vmware-tanzu/antrea/pkg/agent/querier"
networkingv1beta1 "github.com/vmware-tanzu/antrea/pkg/apis/networking/v1beta1"
"github.com/vmware-tanzu/antrea/pkg/querier"
)

// HandleFunc creates a http.HandlerFunc which uses an AgentNetworkPolicyInfoQuerier
// to query network policy rules in current agent.
func HandleFunc(npq querier.AgentNetworkPolicyInfoQuerier) http.HandlerFunc {
func HandleFunc(aq querier.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
ns := r.URL.Query().Get("namespace")
if len(name) > 0 && len(ns) == 0 {
http.Error(w, "an empty namespace may not be set when a resource name is provided", http.StatusBadRequest)
pod := r.URL.Query().Get("pod")

if (name != "" || pod != "") && ns == "" {
http.Error(w, "namespace must be provided", http.StatusBadRequest)
return
}

policies := npq.GetNetworkPolicies()
var resp []networkingv1beta1.NetworkPolicy
for _, p := range policies {
if (len(name) == 0 || name == p.Name) && (len(ns) == 0 || ns == p.Namespace) {
resp = append(resp, p)
var obj interface{}
npq := aq.GetNetworkPolicyInfoQuerier()

if name != "" {
// Query the specified NetworkPolicy.
np := npq.GetNetworkPolicy(name, ns)
if np != nil {
obj = *np
}
} else if pod != "" {
// Query NetworkPolicies applied to the Pod
_, ok := aq.GetInterfaceStore().GetContainerInterface(pod, ns)
if ok {
nps := npq.GetAppliedNetworkPolicies(pod, ns)
obj = networkingv1beta1.NetworkPolicyList{Items: nps}
}
} else {
nps := npq.GetNetworkPolicies(ns)
obj = networkingv1beta1.NetworkPolicyList{Items: nps}
}

if len(name) > 0 && len(resp) == 0 {
if obj == nil {
w.WriteHeader(http.StatusNotFound)
return
}

var obj interface{}
if len(name) > 0 {
obj = resp[0]
} else {
obj = networkingv1beta1.NetworkPolicyList{Items: resp}
}
if err := json.NewEncoder(w).Encode(obj); err != nil {
http.Error(w, "Failed to encode response: "+err.Error(), http.StatusInternalServerError)
}
Expand Down
85 changes: 63 additions & 22 deletions pkg/agent/controller/networkpolicy/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ type ruleCache struct {
podUpdates <-chan v1beta1.PodReference
}

func (c *ruleCache) GetNetworkPolicies() []v1beta1.NetworkPolicy {
var ret []v1beta1.NetworkPolicy
func (c *ruleCache) getNetworkPolicies(namespace string) []v1beta1.NetworkPolicy {
ret := []v1beta1.NetworkPolicy{}
c.policyMapLock.RLock()
defer c.policyMapLock.RUnlock()
for uid := range c.policyMap {
ret = append(ret, *c.buildNetworkPolicy(uid))
for uid, np := range c.policyMap {
if namespace == "" || np.Namespace == namespace {
ret = append(ret, *c.buildNetworkPolicyFromRules(uid))
}
}
return ret
}
Expand All @@ -151,29 +153,68 @@ func (c *ruleCache) getNetworkPolicy(npName, npNamespace string) *v1beta1.Networ
// NetworkPolicy not found.
return nil
}
return c.buildNetworkPolicy(npUID)
return c.buildNetworkPolicyFromRules(npUID)
}

func (c *ruleCache) buildNetworkPolicy(uid string) *v1beta1.NetworkPolicy {
np := v1beta1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid)},
}
func (c *ruleCache) buildNetworkPolicyFromRules(uid string) *v1beta1.NetworkPolicy {
var np *v1beta1.NetworkPolicy
rules, _ := c.rules.ByIndex(policyIndex, uid)
for i, ruleObj := range rules {
rule := ruleObj.(*rule)
if i == 0 {
np.Name = rule.PolicyName
np.Namespace = rule.PolicyNamespace
for _, ruleObj := range rules {
np = addRuleToNetworkPolicy(np, ruleObj.(*rule))
}
return np
}

// addRuleToNetworkPolicy adds a cached rule to the passed NetworkPolicy struct
// and returns it. If np is nil, a new NetworkPolicy struct will be created.
func addRuleToNetworkPolicy(np *v1beta1.NetworkPolicy, rule *rule) *v1beta1.NetworkPolicy {
if np == nil {
np = &v1beta1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{UID: rule.PolicyUID,
Name: rule.PolicyName,
Namespace: rule.PolicyNamespace},
AppliedToGroups: rule.AppliedToGroups,
}
}
np.Rules = append(np.Rules, v1beta1.NetworkPolicyRule{
Direction: rule.Direction,
From: rule.From,
To: rule.To,
Services: rule.Services})
return np

}

func (c *ruleCache) getAppliedNetworkPolicies(pod, namespace string) []v1beta1.NetworkPolicy {
var groups []string
memberPod := &v1beta1.GroupMemberPod{Pod: &v1beta1.PodReference{pod, namespace}}
c.podSetLock.RLock()
for group, podSet := range c.podSetByGroup {
if podSet.Has(memberPod) {
groups = append(groups, group)
}
np.Rules = append(np.Rules, v1beta1.NetworkPolicyRule{
Direction: rule.Direction,
From: rule.From,
To: rule.To,
Services: rule.Services,
})
np.AppliedToGroups = rule.AppliedToGroups
}
return &np
c.podSetLock.RUnlock()

npMap := make(map[string]*v1beta1.NetworkPolicy)
for _, group := range groups {
rules, _ := c.rules.ByIndex(appliedToGroupIndex, group)
for _, ruleObj := range rules {
rule := ruleObj.(*rule)
np, ok := npMap[string(rule.PolicyUID)]
np = addRuleToNetworkPolicy(np, rule)
if !ok {
// First rule for this NetworkPolicy
npMap[string(rule.PolicyUID)] = np
}
}
}

ret := make([]v1beta1.NetworkPolicy, 0, len(npMap))
for _, np := range npMap {
ret = append(ret, *np)
}
return ret
}

func (c *ruleCache) GetAddressGroups() []v1beta1.AddressGroup {
Expand Down
13 changes: 11 additions & 2 deletions pkg/agent/controller/networkpolicy/networkpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,17 @@ func (c *Controller) GetAppliedToGroupNum() int {
return c.ruleCache.GetAppliedToGroupNum()
}

func (c *Controller) GetNetworkPolicies() []v1beta1.NetworkPolicy {
return c.ruleCache.GetNetworkPolicies()
// GetNetworkPolicies returns the requested NetworkPolicies.
// If namespace is provided, only NetworkPolicies in the Namespace are returned.
// If namespace is not provided, NetworkPolicies in all the Namespace are
// returned.
func (c *Controller) GetNetworkPolicies(namespace string) []v1beta1.NetworkPolicy {
return c.ruleCache.getNetworkPolicies(namespace)
}

// GetAppliedToNetworkPolicies returns the NetworkPolicies applied to the Pod.
func (c *Controller) GetAppliedNetworkPolicies(pod, namespace string) []v1beta1.NetworkPolicy {
return c.ruleCache.getAppliedNetworkPolicies(pod, namespace)
}

// GetNetworkPolicy looks up and returns the cached NetworkPolicy.
Expand Down
23 changes: 15 additions & 8 deletions pkg/antctl/antctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,16 @@ var CommandList = &commandList{
{
use: "networkpolicy",
aliases: []string{"networkpolicies", "netpol"},
short: "Print network policies",
long: "Print network policies in ${component}. \"Namespace\" is required if \"Name\" is provided.",
example: ` Get a NetworkPolicy in a specific Namespace
$ antctl get networkpolicy access-nginx -n prod
short: "Print NetworkPolicies",
long: "Print NetworkPolicies in ${component}. \"namespace\" is required if \"name\" is provided.",
example: ` Get a specific NetworkPolicy
$ antctl get networkpolicy np1 -n ns1
Get the list of NetworkPolicies in a Namespace
$ antctl get networkpolicy -n prod
$ antctl get networkpolicy -n ns1
Get the list of NetworkPolicies in all Namespaces
$ antctl get networkpolicy`,
$ antctl get networkpolicy
Get the list of NetworkPolicies applied to a Pod (supported by agent only)
$ antctl get networkpolicy -p pod1 -n ns1`,
commandGroup: get,
controllerEndpoint: &endpoint{
resourceEndpoint: &resourceEndpoint{
Expand All @@ -81,14 +83,19 @@ var CommandList = &commandList{
params: []flagInfo{
{
name: "name",
usage: "Retrieve resource by name",
usage: "Get NetworkPolicy by name. If present, Namespace must be provided.",
arg: true,
},
{
name: "namespace",
usage: "Get networkpolicies from specific Namespace",
usage: "Get Networkpolicies from specific Namespace",
shorthand: "n",
},
{
name: "pod",
usage: "Get NetworkPolicies applied to the Pod. If present, Namespace must be provided.",
shorthand: "p",
},
},
},
addonTransform: networkpolicy.Transform,
Expand Down
3 changes: 2 additions & 1 deletion pkg/querier/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ type NetworkPolicyInfoQuerier interface {
type AgentNetworkPolicyInfoQuerier interface {
NetworkPolicyInfoQuerier
GetControllerConnectionStatus() bool
GetNetworkPolicies() []networkingv1beta1.NetworkPolicy
GetNetworkPolicies(namespace string) []networkingv1beta1.NetworkPolicy
GetAddressGroups() []networkingv1beta1.AddressGroup
GetAppliedToGroups() []networkingv1beta1.AppliedToGroup
GetNetworkPolicy(npName, npNamespace string) *networkingv1beta1.NetworkPolicy
GetAppliedNetworkPolicies(pod, namespace string) []networkingv1beta1.NetworkPolicy
}

type ControllerNetworkPolicyInfoQuerier interface {
Expand Down

0 comments on commit 2f061ac

Please sign in to comment.