1
16
17 package netpol
18
19 import (
20 "context"
21 "time"
22
23 apierrors "k8s.io/apimachinery/pkg/api/errors"
24 "k8s.io/apimachinery/pkg/types"
25 "k8s.io/apimachinery/pkg/util/intstr"
26 "k8s.io/apimachinery/pkg/util/wait"
27 "k8s.io/apimachinery/pkg/watch"
28 admissionapi "k8s.io/pod-security-admission/api"
29
30 "github.com/onsi/ginkgo/v2"
31 "github.com/onsi/gomega"
32
33 networkingv1 "k8s.io/api/networking/v1"
34 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35 "k8s.io/kubernetes/test/e2e/framework"
36 "k8s.io/kubernetes/test/e2e/network/common"
37 )
38
39 var _ = common.SIGDescribe("Netpol API", func() {
40 f := framework.NewDefaultFramework("netpol")
41 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
42
51
52 ginkgo.It("should support creating NetworkPolicy API operations", func(ctx context.Context) {
53
54 ns := f.Namespace.Name
55 npVersion := "v1"
56 npClient := f.ClientSet.NetworkingV1().NetworkPolicies(ns)
57
58 namespaceSelector := &metav1.LabelSelector{
59 MatchLabels: map[string]string{
60 "ns-name": "pod-b",
61 },
62 }
63 podSelector := &metav1.LabelSelector{
64 MatchLabels: map[string]string{
65 "pod-name": "client-a",
66 },
67 }
68 ingressRule := networkingv1.NetworkPolicyIngressRule{}
69 ingressRule.From = append(ingressRule.From, networkingv1.NetworkPolicyPeer{PodSelector: podSelector, NamespaceSelector: namespaceSelector})
70 npTemplate := GenNetworkPolicy(SetGenerateName("e2e-example-netpol"),
71 SetObjectMetaLabel(map[string]string{"special-label": f.UniqueName}),
72 SetSpecPodSelectorMatchLabels(map[string]string{"pod-name": "test-pod"}),
73 SetSpecIngressRules(ingressRule))
74
75
76 ginkgo.By("getting /apis")
77 {
78 discoveryGroups, err := f.ClientSet.Discovery().ServerGroups()
79 framework.ExpectNoError(err)
80 found := false
81 for _, group := range discoveryGroups.Groups {
82 if group.Name == networkingv1.GroupName {
83 for _, version := range group.Versions {
84 if version.Version == npVersion {
85 found = true
86 break
87 }
88 }
89 }
90 }
91 if !found {
92 framework.Failf("expected networking API group/version, got %#v", discoveryGroups.Groups)
93 }
94 }
95 ginkgo.By("getting /apis/networking.k8s.io")
96 {
97 group := &metav1.APIGroup{}
98 err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/networking.k8s.io").Do(ctx).Into(group)
99 framework.ExpectNoError(err)
100 found := false
101 for _, version := range group.Versions {
102 if version.Version == npVersion {
103 found = true
104 break
105 }
106 }
107 if !found {
108 framework.Failf("expected networking API version, got %#v", group.Versions)
109 }
110 }
111 ginkgo.By("getting /apis/networking.k8s.io" + npVersion)
112 {
113 resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(networkingv1.SchemeGroupVersion.String())
114 framework.ExpectNoError(err)
115 foundNetPol := false
116 for _, resource := range resources.APIResources {
117 switch resource.Name {
118 case "networkpolicies":
119 foundNetPol = true
120 }
121 }
122 if !foundNetPol {
123 framework.Failf("expected networkpolicies, got %#v", resources.APIResources)
124 }
125 }
126
127 ginkgo.By("creating")
128 _, err := npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
129 framework.ExpectNoError(err)
130 _, err = npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
131 framework.ExpectNoError(err)
132 createdNetPol, err := npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
133 framework.ExpectNoError(err)
134
135 ginkgo.By("getting")
136 gottenNetPol, err := npClient.Get(ctx, createdNetPol.Name, metav1.GetOptions{})
137 framework.ExpectNoError(err)
138 gomega.Expect(gottenNetPol.UID).To(gomega.Equal(createdNetPol.UID))
139
140 ginkgo.By("listing")
141 nps, err := npClient.List(ctx, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
142 framework.ExpectNoError(err)
143 gomega.Expect(nps.Items).To(gomega.HaveLen(3), "filtered list should have 3 items")
144
145 ginkgo.By("watching")
146 framework.Logf("starting watch")
147 npWatch, err := npClient.Watch(ctx, metav1.ListOptions{ResourceVersion: nps.ResourceVersion, LabelSelector: "special-label=" + f.UniqueName})
148 framework.ExpectNoError(err)
149
150 clusterNPClient := f.ClientSet.NetworkingV1().NetworkPolicies("")
151 ginkgo.By("cluster-wide listing")
152 clusterNPs, err := clusterNPClient.List(ctx, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
153 framework.ExpectNoError(err)
154 gomega.Expect(clusterNPs.Items).To(gomega.HaveLen(3), "filtered list should have 3 items")
155
156 ginkgo.By("cluster-wide watching")
157 framework.Logf("starting watch")
158 _, err = clusterNPClient.Watch(ctx, metav1.ListOptions{ResourceVersion: nps.ResourceVersion, LabelSelector: "special-label=" + f.UniqueName})
159 framework.ExpectNoError(err)
160
161 ginkgo.By("patching")
162 patchedNetPols, err := npClient.Patch(ctx, createdNetPol.Name, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patched":"true"}}}`), metav1.PatchOptions{})
163 framework.ExpectNoError(err)
164 gomega.Expect(patchedNetPols.Annotations).To(gomega.HaveKeyWithValue("patched", "true"), "patched object should have the applied annotation")
165
166 ginkgo.By("updating")
167 npToUpdate := patchedNetPols.DeepCopy()
168 npToUpdate.Annotations["updated"] = "true"
169 updatedNetPols, err := npClient.Update(ctx, npToUpdate, metav1.UpdateOptions{})
170 framework.ExpectNoError(err)
171 gomega.Expect(updatedNetPols.Annotations).To(gomega.HaveKeyWithValue("updated", "true"), "updated object should have the applied annotation")
172
173 framework.Logf("waiting for watch events with expected annotations")
174 for sawAnnotations := false; !sawAnnotations; {
175 select {
176 case evt, ok := <-npWatch.ResultChan():
177 if !ok {
178 framework.Fail("watch channel should not close")
179 }
180 gomega.Expect(evt.Type).To(gomega.Equal(watch.Modified))
181 watchedNetPol, isNetPol := evt.Object.(*networkingv1.NetworkPolicy)
182 if !isNetPol {
183 framework.Failf("expected NetworkPolicy, got %T", evt.Object)
184 }
185 if watchedNetPol.Annotations["patched"] == "true" && watchedNetPol.Annotations["updated"] == "true" {
186 framework.Logf("saw patched and updated annotations")
187 sawAnnotations = true
188 npWatch.Stop()
189 } else {
190 framework.Logf("missing expected annotations, waiting: %#v", watchedNetPol.Annotations)
191 }
192 case <-time.After(wait.ForeverTestTimeout):
193 framework.Fail("timed out waiting for watch event")
194 }
195 }
196
197 ginkgo.By("deleting")
198 err = npClient.Delete(ctx, createdNetPol.Name, metav1.DeleteOptions{})
199 framework.ExpectNoError(err)
200 _, err = npClient.Get(ctx, createdNetPol.Name, metav1.GetOptions{})
201 if !apierrors.IsNotFound(err) {
202 framework.Failf("expected 404, got %#v", err)
203 }
204 nps, err = npClient.List(ctx, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
205 framework.ExpectNoError(err)
206 gomega.Expect(nps.Items).To(gomega.HaveLen(2), "filtered list should have 2 items")
207
208 ginkgo.By("deleting a collection")
209 err = npClient.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
210 framework.ExpectNoError(err)
211 nps, err = npClient.List(ctx, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
212 framework.ExpectNoError(err)
213 gomega.Expect(nps.Items).To(gomega.BeEmpty(), "filtered list should have 0 items")
214 })
215
216
224 ginkgo.It("should support creating NetworkPolicy API with endport field", func(ctx context.Context) {
225 ns := f.Namespace.Name
226 npClient := f.ClientSet.NetworkingV1().NetworkPolicies(ns)
227
228 ginkgo.By("EndPort field cannot be defined if the Port field is not defined.")
229 var endport int32 = 20000
230 egressRule := networkingv1.NetworkPolicyEgressRule{}
231 egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{EndPort: &endport})
232 npTemplate := GenNetworkPolicy(SetGenerateName("e2e-example-netpol-endport-validate"),
233 SetObjectMetaLabel(map[string]string{"special-label": f.UniqueName}),
234 SetSpecPodSelectorMatchLabels(map[string]string{"pod-name": "test-pod"}),
235 SetSpecEgressRules(egressRule))
236 _, err := npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
237 gomega.Expect(err).To(gomega.HaveOccurred(), "request template:%v", npTemplate)
238
239 ginkgo.By("EndPort field cannot be defined if the Port field is defined as a named (string) port.")
240 egressRule = networkingv1.NetworkPolicyEgressRule{}
241 egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.String, StrVal: "serve-80"}, EndPort: &endport})
242 npTemplate.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{egressRule}
243 _, err = npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
244 gomega.Expect(err).To(gomega.HaveOccurred(), "request template:%v", npTemplate)
245
246 ginkgo.By("EndPort field must be equal or greater than port.")
247 ginkgo.By("When EndPort field is smaller than port, it will failed")
248 egressRule = networkingv1.NetworkPolicyEgressRule{}
249 egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 30000}, EndPort: &endport})
250 npTemplate.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{egressRule}
251 _, err = npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
252 gomega.Expect(err).To(gomega.HaveOccurred(), "request template:%v", npTemplate)
253
254 ginkgo.By("EndPort field is equal with port.")
255 egressRule.Ports[0].Port = &intstr.IntOrString{Type: intstr.Int, IntVal: 20000}
256 npTemplate.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{egressRule}
257 _, err = npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
258 framework.ExpectNoError(err, "request template:%v", npTemplate)
259
260 ginkgo.By("EndPort field is greater than port.")
261 egressRule = networkingv1.NetworkPolicyEgressRule{}
262 egressRule.Ports = append(egressRule.Ports, networkingv1.NetworkPolicyPort{Port: &intstr.IntOrString{Type: intstr.Int, IntVal: 10000}, EndPort: &endport})
263 npTemplate.Spec.Egress = []networkingv1.NetworkPolicyEgressRule{egressRule}
264 _, err = npClient.Create(ctx, npTemplate, metav1.CreateOptions{})
265 framework.ExpectNoError(err, "request template:%v", npTemplate)
266
267 ginkgo.By("deleting all test collection")
268 err = npClient.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
269 framework.ExpectNoError(err)
270 nps, err := npClient.List(ctx, metav1.ListOptions{LabelSelector: "special-label=" + f.UniqueName})
271 framework.ExpectNoError(err)
272 gomega.Expect(nps.Items).To(gomega.BeEmpty(), "filtered list should be 0 items")
273 })
274 })
275
View as plain text