Skip to content

Commit 81e1f58

Browse files
committed
Add e2e tests for storage network policy labels
This commit adds comprehensive e2e tests to verify that storage-related operators and controllers have the required network policy labels and that NetworkPolicy resources exist with correct pod selectors. Changes: - Add namespace constants to helpers.go for reuse across storage tests - Add storage_networkpolicy.go with tests for CSO and CSI operators - Verify required network policy labels on deployments - Validate NetworkPolicy resources in storage namespaces
1 parent 816619b commit 81e1f58

File tree

2 files changed

+318
-0
lines changed

2 files changed

+318
-0
lines changed

test/extended/storage/helpers.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ const (
2121
defaultPollingTime = 2 * time.Second
2222
)
2323

24+
// Storage operator and CSI driver namespace constants
25+
const (
26+
CSONamespace = "openshift-cluster-storage-operator" // Cluster Storage Operator namespace
27+
CSINamespace = "openshift-cluster-csi-drivers" // Default CSI driver operators namespace
28+
ManilaCSINamespace = "openshift-manila-csi-driver" // Manila CSI driver namespace (OpenStack only)
29+
)
30+
2431
// IsCSOHealthy checks whether the Cluster Storage Operator is healthy
2532
func IsCSOHealthy(oc *exutil.CLI) (bool, error) {
2633
// CSO healthyStatus:[degradedStatus:False, progressingStatus:False, availableStatus:True, upgradeableStatus:True]
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
package storage
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
g "github.com/onsi/ginkgo/v2"
9+
o "github.com/onsi/gomega"
10+
exutil "github.com/openshift/origin/test/extended/util"
11+
"k8s.io/apimachinery/pkg/api/errors"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
e2e "k8s.io/kubernetes/test/e2e/framework"
14+
)
15+
16+
type deploymentCheck struct {
17+
Namespace string
18+
Name string
19+
Platform string
20+
RequiredLabels map[string]string
21+
}
22+
23+
type npCheck struct {
24+
Namespace string
25+
Optional bool
26+
Policies map[string]map[string]string
27+
}
28+
29+
var (
30+
npLabelAPI = map[string]string{"openshift.storage.network-policy.api-server": "allow"}
31+
npLabelDNS = map[string]string{"openshift.storage.network-policy.dns": "allow"}
32+
npLabelOperatorMetrics = map[string]string{"openshift.storage.network-policy.operator-metrics": "allow"}
33+
npLabelOperatorMetricsRange = map[string]string{"openshift.storage.network-policy.operator-metrics-range": "allow"}
34+
npLabelMetricsRange = map[string]string{"openshift.storage.network-policy.metrics-range": "allow"}
35+
)
36+
37+
func mergeLabels(maps ...map[string]string) map[string]string {
38+
out := map[string]string{}
39+
for _, m := range maps {
40+
for k, v := range m {
41+
out[k] = v
42+
}
43+
}
44+
return out
45+
}
46+
47+
var (
48+
csoOperatorRequiredLabels = mergeLabels(npLabelAPI, npLabelDNS, npLabelOperatorMetrics)
49+
csoControllerRequiredLabels = mergeLabels(npLabelAPI, npLabelDNS)
50+
csiOperatorRequiredLabels = mergeLabels(npLabelAPI, npLabelDNS, npLabelOperatorMetricsRange)
51+
csiControllerRequiredLabels = mergeLabels(npLabelAPI, npLabelDNS, npLabelMetricsRange)
52+
)
53+
54+
var (
55+
npNameAPI = "allow-egress-to-api-server"
56+
npNameDNS = "allow-to-dns"
57+
npNameOperatorMetrics = "allow-ingress-to-operator-metrics"
58+
npNameMetricsRange = "allow-ingress-to-metrics-range"
59+
npNameOperatorMetricsRange = "allow-ingress-to-operator-metrics-range"
60+
)
61+
62+
var networkPolicyChecks = []npCheck{
63+
{
64+
Namespace: CSONamespace,
65+
Policies: map[string]map[string]string{
66+
npNameAPI: npLabelAPI,
67+
npNameDNS: npLabelDNS,
68+
npNameOperatorMetrics: npLabelOperatorMetrics,
69+
},
70+
},
71+
{
72+
Namespace: CSINamespace,
73+
Policies: map[string]map[string]string{
74+
npNameAPI: npLabelAPI,
75+
npNameDNS: npLabelDNS,
76+
npNameMetricsRange: npLabelMetricsRange,
77+
npNameOperatorMetricsRange: npLabelOperatorMetricsRange,
78+
},
79+
},
80+
{
81+
Namespace: ManilaCSINamespace,
82+
Optional: true,
83+
Policies: map[string]map[string]string{
84+
npNameAPI: npLabelAPI,
85+
npNameDNS: npLabelDNS,
86+
npNameMetricsRange: npLabelMetricsRange,
87+
npNameOperatorMetricsRange: npLabelOperatorMetricsRange,
88+
},
89+
},
90+
}
91+
92+
var _ = g.Describe("[sig-storage][OCPFeature:StorageNetworkPolicy] Storage Network Policy", g.Ordered, g.Label("Conformance"), g.Label("Parallel"), func() {
93+
defer g.GinkgoRecover()
94+
var (
95+
oc = exutil.NewCLI("storage-network-policy")
96+
currentPlatform = e2e.TestContext.Provider
97+
)
98+
99+
g.It("should verify required labels for CSO related Operators", func() {
100+
CSODeploymentsToCheck := []deploymentCheck{
101+
{
102+
Namespace: CSONamespace,
103+
Name: "cluster-storage-operator",
104+
Platform: "all",
105+
RequiredLabels: csoOperatorRequiredLabels,
106+
},
107+
{
108+
Namespace: CSONamespace,
109+
Name: "vsphere-problem-detector-operator",
110+
Platform: "vsphere",
111+
RequiredLabels: csoOperatorRequiredLabels,
112+
},
113+
{
114+
Namespace: CSONamespace,
115+
Name: "csi-snapshot-controller-operator",
116+
Platform: "all",
117+
RequiredLabels: csoOperatorRequiredLabels,
118+
},
119+
{
120+
Namespace: CSONamespace,
121+
Name: "csi-snapshot-controller",
122+
Platform: "all",
123+
RequiredLabels: csoControllerRequiredLabels,
124+
},
125+
}
126+
runDeploymentChecks(oc, CSODeploymentsToCheck, currentPlatform)
127+
})
128+
129+
g.It("should verify required labels for CSI related Operators", func() {
130+
CSIdeploymentsToCheck := []deploymentCheck{
131+
{
132+
Namespace: CSINamespace,
133+
Name: "aws-ebs-csi-driver-operator",
134+
Platform: "aws",
135+
RequiredLabels: csiOperatorRequiredLabels,
136+
},
137+
{
138+
Namespace: CSINamespace,
139+
Name: "aws-ebs-csi-driver-controller",
140+
Platform: "aws",
141+
RequiredLabels: csiControllerRequiredLabels,
142+
},
143+
{
144+
Namespace: CSINamespace,
145+
Name: "aws-efs-csi-driver-operator",
146+
Platform: "aws",
147+
RequiredLabels: csiOperatorRequiredLabels,
148+
},
149+
{
150+
Namespace: CSINamespace,
151+
Name: "azure-disk-csi-driver-operator",
152+
Platform: "azure",
153+
RequiredLabels: csiOperatorRequiredLabels,
154+
},
155+
{
156+
Namespace: CSINamespace,
157+
Name: "azure-disk-csi-driver-controller",
158+
Platform: "azure",
159+
RequiredLabels: csiControllerRequiredLabels,
160+
},
161+
{
162+
Namespace: CSINamespace,
163+
Name: "azure-file-csi-driver-operator",
164+
Platform: "azure",
165+
RequiredLabels: csiOperatorRequiredLabels,
166+
},
167+
{
168+
Namespace: CSINamespace,
169+
Name: "azure-file-csi-driver-controller",
170+
Platform: "azure",
171+
RequiredLabels: csiControllerRequiredLabels,
172+
},
173+
{
174+
Namespace: CSINamespace,
175+
Name: "gcp-pd-csi-driver-operator",
176+
Platform: "gcp",
177+
RequiredLabels: csiOperatorRequiredLabels,
178+
},
179+
{
180+
Namespace: CSINamespace,
181+
Name: "gcp-filestore-csi-driver-operator",
182+
Platform: "gcp",
183+
RequiredLabels: csiOperatorRequiredLabels,
184+
},
185+
{
186+
Namespace: CSINamespace,
187+
Name: "vmware-vsphere-csi-driver-operator",
188+
Platform: "vsphere",
189+
RequiredLabels: csiOperatorRequiredLabels,
190+
},
191+
{
192+
Namespace: CSINamespace,
193+
Name: "vmware-vsphere-csi-driver-controller",
194+
Platform: "vsphere",
195+
RequiredLabels: csiControllerRequiredLabels,
196+
},
197+
{
198+
Namespace: CSINamespace,
199+
Name: "ibm-vpc-block-csi-driver-operator",
200+
Platform: "ibmcloud",
201+
RequiredLabels: csiOperatorRequiredLabels,
202+
},
203+
{
204+
Namespace: CSINamespace,
205+
Name: "ibm-vpc-block-csi-controller",
206+
Platform: "ibmcloud",
207+
RequiredLabels: csiControllerRequiredLabels,
208+
},
209+
{
210+
Namespace: CSINamespace,
211+
Name: "openstack-cinder-csi-driver-operator",
212+
Platform: "openstack",
213+
RequiredLabels: csiOperatorRequiredLabels,
214+
},
215+
{
216+
Namespace: CSINamespace,
217+
Name: "openstack-cinder-csi-driver-controller",
218+
Platform: "openstack",
219+
RequiredLabels: csiControllerRequiredLabels,
220+
},
221+
{
222+
Namespace: CSINamespace,
223+
Name: "manila-csi-driver-operator",
224+
Platform: "openstack",
225+
RequiredLabels: csiOperatorRequiredLabels,
226+
},
227+
{
228+
Namespace: ManilaCSINamespace,
229+
Name: "openstack-manila-csi-controllerplugin",
230+
Platform: "openstack",
231+
RequiredLabels: csiControllerRequiredLabels,
232+
},
233+
{
234+
Namespace: CSINamespace,
235+
Name: "smb-csi-driver-operator",
236+
Platform: "all",
237+
RequiredLabels: csiOperatorRequiredLabels,
238+
},
239+
{
240+
Namespace: CSINamespace,
241+
Name: "smb-csi-driver-controller",
242+
Platform: "all",
243+
RequiredLabels: csiControllerRequiredLabels,
244+
},
245+
}
246+
runDeploymentChecks(oc, CSIdeploymentsToCheck, currentPlatform)
247+
})
248+
249+
g.It("should ensure required NetworkPolicies exist with correct labels", func() {
250+
for _, c := range networkPolicyChecks {
251+
_, err := oc.AdminKubeClient().CoreV1().Namespaces().Get(context.TODO(), c.Namespace, metav1.GetOptions{})
252+
if err != nil {
253+
if c.Optional {
254+
g.By(fmt.Sprintf("Skipping optional namespace %s (not found)", c.Namespace))
255+
continue
256+
}
257+
o.Expect(err).NotTo(o.HaveOccurred(), fmt.Sprintf("namespace %s should exist", c.Namespace))
258+
}
259+
260+
for npName, labels := range c.Policies {
261+
np, err := oc.AdminKubeClient().NetworkingV1().NetworkPolicies(c.Namespace).Get(context.TODO(), npName, metav1.GetOptions{})
262+
o.Expect(err).NotTo(o.HaveOccurred(), fmt.Sprintf("NetworkPolicy %s/%s should exist", c.Namespace, npName))
263+
264+
for key, val := range labels {
265+
gotVal, ok := np.Spec.PodSelector.MatchLabels[key]
266+
o.Expect(ok).To(o.BeTrue(), fmt.Sprintf("NetworkPolicy %s/%s missing label %s", c.Namespace, npName, key))
267+
o.Expect(gotVal).To(o.Equal(val), fmt.Sprintf("NetworkPolicy %s/%s label %s mismatch (got=%s, want=%s)", c.Namespace, npName, key, gotVal, val))
268+
}
269+
}
270+
}
271+
})
272+
})
273+
274+
func runDeploymentChecks(oc *exutil.CLI, deployments []deploymentCheck, currentPlatform string) {
275+
results := []string{}
276+
hasFail := false
277+
for _, dep := range deployments {
278+
if dep.Platform != "" && dep.Platform != currentPlatform && dep.Platform != "all" {
279+
results = append(results, fmt.Sprintf("[SKIP] %s/%s (platform mismatch: %s)", dep.Namespace, dep.Name, dep.Platform))
280+
continue
281+
}
282+
283+
deployment, err := oc.AdminKubeClient().AppsV1().Deployments(dep.Namespace).Get(context.TODO(), dep.Name, metav1.GetOptions{})
284+
if err != nil {
285+
if errors.IsNotFound(err) {
286+
results = append(results, fmt.Sprintf("[SKIP] %s/%s not found", dep.Namespace, dep.Name))
287+
continue
288+
}
289+
g.Fail(fmt.Sprintf("Error fetching deployment %s/%s: %v", dep.Namespace, dep.Name, err))
290+
}
291+
292+
missingLabels := []string{}
293+
for key, val := range dep.RequiredLabels {
294+
if deployment.Spec.Template.Labels[key] != val {
295+
missingLabels = append(missingLabels, fmt.Sprintf("%s=%s", key, val))
296+
}
297+
}
298+
299+
if len(missingLabels) > 0 {
300+
results = append(results, fmt.Sprintf("[FAIL] %s/%s missing labels: %s", dep.Namespace, dep.Name, strings.Join(missingLabels, ", ")))
301+
hasFail = true
302+
} else {
303+
results = append(results, fmt.Sprintf("[PASS] %s/%s", dep.Namespace, dep.Name))
304+
}
305+
}
306+
307+
if hasFail {
308+
summary := strings.Join(results, "\n")
309+
g.Fail(fmt.Sprintf("Some deployments are missing required labels:\n\n%s\n", summary))
310+
}
311+
}

0 commit comments

Comments
 (0)