Skip to content

Commit 62ac60c

Browse files
author
Christopher M. Luciano
committed
netpol: Add CRUD tests for NetworkPolicy API
CRUD operations are the extent of conformance testing that we can add for NetworkPolicy tests since we require a 3rd party plugin like CNI for enforcement. Signed-off-by: Christopher M. Luciano <[email protected]>
1 parent b9d2df8 commit 62ac60c

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

test/e2e/network/network_policy.go

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"net"
24+
"time"
2425

2526
v1 "k8s.io/api/core/v1"
2627
networkingv1 "k8s.io/api/networking/v1"
2728
apierrors "k8s.io/apimachinery/pkg/api/errors"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930
"k8s.io/apimachinery/pkg/types"
3031
"k8s.io/apimachinery/pkg/util/intstr"
32+
"k8s.io/apimachinery/pkg/util/wait"
33+
"k8s.io/apimachinery/pkg/watch"
3134
"k8s.io/kubernetes/test/e2e/framework"
3235
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
3336
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
@@ -2266,3 +2269,179 @@ func cleanupNetworkPolicy(f *framework.Framework, policy *networkingv1.NetworkPo
22662269
framework.Failf("unable to cleanup policy %v: %v", policy.Name, err)
22672270
}
22682271
}
2272+
2273+
var _ = SIGDescribe("NetworkPolicy API", func() {
2274+
f := framework.NewDefaultFramework("networkpolicies")
2275+
/*
2276+
Release: v1.20
2277+
Testname: NetworkPolicies API
2278+
Description:
2279+
- The networking.k8s.io API group MUST exist in the /apis discovery document.
2280+
- The networking.k8s.io/v1 API group/version MUST exist in the /apis/networking.k8s.io discovery document.
2281+
- The NetworkPolicies resources MUST exist in the /apis/networking.k8s.io/v1 discovery document.
2282+
- The NetworkPolicies resource must support create, get, list, watch, update, patch, delete, and deletecollection.
2283+
*/
2284+
2285+
ginkgo.It("should support creating NetworkPolicy API operations", func() {
2286+
// Setup
2287+
ns := f.Namespace.Name
2288+
npVersion := "v1"
2289+
npClient := f.ClientSet.NetworkingV1().NetworkPolicies(ns)
2290+
npTemplate := &networkingv1.NetworkPolicy{
2291+
ObjectMeta: metav1.ObjectMeta{GenerateName: "e2e-example-netpol",
2292+
Labels: map[string]string{
2293+
"special-label": f.UniqueName,
2294+
}},
2295+
Spec: networkingv1.NetworkPolicySpec{
2296+
// Apply this policy to the Server
2297+
PodSelector: metav1.LabelSelector{
2298+
MatchLabels: map[string]string{
2299+
"pod-name": "test-pod",
2300+
},
2301+
},
2302+
// Allow traffic only from client-a in namespace-b
2303+
Ingress: []networkingv1.NetworkPolicyIngressRule{{
2304+
From: []networkingv1.NetworkPolicyPeer{{
2305+
NamespaceSelector: &metav1.LabelSelector{
2306+
MatchLabels: map[string]string{
2307+
"ns-name": "pod-b",
2308+
},
2309+
},
2310+
PodSelector: &metav1.LabelSelector{
2311+
MatchLabels: map[string]string{
2312+
"pod-name": "client-a",
2313+
},
2314+
},
2315+
}},
2316+
}},
2317+
},
2318+
}
2319+
// Discovery
2320+
ginkgo.By("getting /apis")
2321+
{
2322+
discoveryGroups, err := f.ClientSet.Discovery().ServerGroups()
2323+
framework.ExpectNoError(err)
2324+
found := false
2325+
for _, group := range discoveryGroups.Groups {
2326+
if group.Name == networkingv1.GroupName {
2327+
for _, version := range group.Versions {
2328+
if version.Version == npVersion {
2329+
found = true
2330+
break
2331+
}
2332+
}
2333+
}
2334+
}
2335+
framework.ExpectEqual(found, true, fmt.Sprintf("expected networking API group/version, got %#v", discoveryGroups.Groups))
2336+
}
2337+
ginkgo.By("getting /apis/networking.k8s.io")
2338+
{
2339+
group := &metav1.APIGroup{}
2340+
err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/networking.k8s.io").Do(context.TODO()).Into(group)
2341+
framework.ExpectNoError(err)
2342+
found := false
2343+
for _, version := range group.Versions {
2344+
if version.Version == npVersion {
2345+
found = true
2346+
break
2347+
}
2348+
}
2349+
framework.ExpectEqual(found, true, fmt.Sprintf("expected networking API version, got %#v", group.Versions))
2350+
}
2351+
ginkgo.By("getting /apis/networking.k8s.io" + npVersion)
2352+
{
2353+
resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(networkingv1.SchemeGroupVersion.String())
2354+
framework.ExpectNoError(err)
2355+
foundNetPol := false
2356+
for _, resource := range resources.APIResources {
2357+
switch resource.Name {
2358+
case "networkpolicies":
2359+
foundNetPol = true
2360+
}
2361+
}
2362+
framework.ExpectEqual(foundNetPol, true, fmt.Sprintf("expected networkpolicies, got %#v", resources.APIResources))
2363+
}
2364+
// NetPol resource create/read/update/watch verbs
2365+
ginkgo.By("creating")
2366+
_, err := npClient.Create(context.TODO(), npTemplate, metav1.CreateOptions{})
2367+
framework.ExpectNoError(err)
2368+
_, err = npClient.Create(context.TODO(), npTemplate, metav1.CreateOptions{})
2369+
framework.ExpectNoError(err)
2370+
createdNetPol, err := npClient.Create(context.TODO(), npTemplate, metav1.CreateOptions{})
2371+
framework.ExpectNoError(err)
2372+
2373+
ginkgo.By("getting")
2374+
gottenNetPol, err := npClient.Get(context.TODO(), createdNetPol.Name, metav1.GetOptions{})
2375+
framework.ExpectNoError(err)
2376+
framework.ExpectEqual(gottenNetPol.UID, createdNetPol.UID)
2377+
2378+
ginkgo.By("listing")
2379+
nps, err := npClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
2380+
framework.ExpectNoError(err)
2381+
framework.ExpectEqual(len(nps.Items), 3, "filtered list should have 3 items")
2382+
2383+
ginkgo.By("watching")
2384+
framework.Logf("starting watch")
2385+
npWatch, err := npClient.Watch(context.TODO(), metav1.ListOptions{ResourceVersion: nps.ResourceVersion, LabelSelector: "special-label=" + f.UniqueName})
2386+
framework.ExpectNoError(err)
2387+
// Test cluster-wide list and watch
2388+
clusterNPClient := f.ClientSet.NetworkingV1().NetworkPolicies("")
2389+
ginkgo.By("cluster-wide listing")
2390+
clusterNPs, err := clusterNPClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
2391+
framework.ExpectNoError(err)
2392+
framework.ExpectEqual(len(clusterNPs.Items), 3, "filtered list should have 3 items")
2393+
2394+
ginkgo.By("cluster-wide watching")
2395+
framework.Logf("starting watch")
2396+
_, err = clusterNPClient.Watch(context.TODO(), metav1.ListOptions{ResourceVersion: nps.ResourceVersion, LabelSelector: "special-label=" + f.UniqueName})
2397+
framework.ExpectNoError(err)
2398+
2399+
ginkgo.By("patching")
2400+
patchedNetPols, err := npClient.Patch(context.TODO(), createdNetPol.Name, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patched":"true"}}}`), metav1.PatchOptions{})
2401+
framework.ExpectNoError(err)
2402+
framework.ExpectEqual(patchedNetPols.Annotations["patched"], "true", "patched object should have the applied annotation")
2403+
2404+
ginkgo.By("updating")
2405+
npToUpdate := patchedNetPols.DeepCopy()
2406+
npToUpdate.Annotations["updated"] = "true"
2407+
updatedNetPols, err := npClient.Update(context.TODO(), npToUpdate, metav1.UpdateOptions{})
2408+
framework.ExpectNoError(err)
2409+
framework.ExpectEqual(updatedNetPols.Annotations["updated"], "true", "updated object should have the applied annotation")
2410+
2411+
framework.Logf("waiting for watch events with expected annotations")
2412+
for sawAnnotations := false; !sawAnnotations; {
2413+
select {
2414+
case evt, ok := <-npWatch.ResultChan():
2415+
framework.ExpectEqual(ok, true, "watch channel should not close")
2416+
framework.ExpectEqual(evt.Type, watch.Modified)
2417+
watchedNetPol, isNetPol := evt.Object.(*networkingv1.NetworkPolicy)
2418+
framework.ExpectEqual(isNetPol, true, fmt.Sprintf("expected NetworkPolicy, got %T", evt.Object))
2419+
if watchedNetPol.Annotations["patched"] == "true" && watchedNetPol.Annotations["updated"] == "true" {
2420+
framework.Logf("saw patched and updated annotations")
2421+
sawAnnotations = true
2422+
npWatch.Stop()
2423+
} else {
2424+
framework.Logf("missing expected annotations, waiting: %#v", watchedNetPol.Annotations)
2425+
}
2426+
case <-time.After(wait.ForeverTestTimeout):
2427+
framework.Fail("timed out waiting for watch event")
2428+
}
2429+
}
2430+
// NetPol resource delete operations
2431+
ginkgo.By("deleting")
2432+
err = npClient.Delete(context.TODO(), createdNetPol.Name, metav1.DeleteOptions{})
2433+
framework.ExpectNoError(err)
2434+
_, err = npClient.Get(context.TODO(), createdNetPol.Name, metav1.GetOptions{})
2435+
framework.ExpectEqual(apierrors.IsNotFound(err), true, fmt.Sprintf("expected 404, got %#v", err))
2436+
nps, err = npClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
2437+
framework.ExpectNoError(err)
2438+
framework.ExpectEqual(len(nps.Items), 2, "filtered list should have 2 items")
2439+
2440+
ginkgo.By("deleting a collection")
2441+
err = npClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
2442+
framework.ExpectNoError(err)
2443+
nps, err = npClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
2444+
framework.ExpectNoError(err)
2445+
framework.ExpectEqual(len(nps.Items), 0, "filtered list should have 0 items")
2446+
})
2447+
})

0 commit comments

Comments
 (0)