Skip to content

Commit 73b8711

Browse files
committed
test: add utility for namespace labels patching and add the test cases for denyNodeFeatureLabels restriction
Signed-off-by: TessaIO <[email protected]>
1 parent 2fbd8a8 commit 73b8711

File tree

3 files changed

+78
-29
lines changed

3 files changed

+78
-29
lines changed

pkg/utils/jsonpatch.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import (
2121
"strings"
2222
)
2323

24+
const (
25+
JSONAddOperation = "add"
26+
JSONRemoveOperation = "remove"
27+
)
28+
2429
// JsonPatch is a json marshaling helper used for patching API objects
2530
type JsonPatch struct {
2631
Op string `json:"op"`

test/e2e/node_feature_discovery_test.go

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"sigs.k8s.io/node-feature-discovery/source/custom"
4848
testutils "sigs.k8s.io/node-feature-discovery/test/e2e/utils"
4949
testds "sigs.k8s.io/node-feature-discovery/test/e2e/utils/daemonset"
50+
"sigs.k8s.io/node-feature-discovery/test/e2e/utils/namespace"
5051
testpod "sigs.k8s.io/node-feature-discovery/test/e2e/utils/pod"
5152
)
5253

@@ -1011,20 +1012,7 @@ resyncPeriod: "1s"
10111012
Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found")
10121013

10131014
// label the namespace in which node feature object is created
1014-
// TODO(TessaIO): add a utility for this.
1015-
patches, err := json.Marshal(
1016-
[]utils.JsonPatch{
1017-
utils.NewJsonPatch(
1018-
"add",
1019-
"/metadata/labels",
1020-
"e2etest",
1021-
"fake",
1022-
),
1023-
},
1024-
)
1025-
Expect(err).NotTo(HaveOccurred())
1026-
1027-
_, err = f.ClientSet.CoreV1().Namespaces().Patch(ctx, f.Namespace.Name, types.JSONPatchType, patches, metav1.PatchOptions{})
1015+
err = namespace.PatchLabels(f.Namespace.Name, "e2etest", "fake", utils.JSONAddOperation, ctx, f)
10281016
Expect(err).NotTo(HaveOccurred())
10291017

10301018
// Apply Node Feature object
@@ -1044,20 +1032,9 @@ resyncPeriod: "1s"
10441032
eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchLabels(expectedLabels, nodes))
10451033

10461034
// remove label the namespace in which node feature object is created
1047-
patches, err = json.Marshal(
1048-
[]utils.JsonPatch{
1049-
utils.NewJsonPatch(
1050-
"remove",
1051-
"/metadata/labels",
1052-
"e2etest",
1053-
"fake",
1054-
),
1055-
},
1056-
)
1035+
err = namespace.PatchLabels(f.Namespace.Name, "e2etest", "fake", utils.JSONRemoveOperation, ctx, f)
10571036
Expect(err).NotTo(HaveOccurred())
10581037

1059-
_, err = f.ClientSet.CoreV1().Namespaces().Patch(ctx, f.Namespace.Name, types.JSONPatchType, patches, metav1.PatchOptions{})
1060-
Expect(err).NotTo(HaveOccurred())
10611038
By("Verifying node labels from NodeFeature object #1 are not created")
10621039
// No labels should be created since the f.Namespace is not in the selected Namespaces
10631040
expectedLabels = map[string]k8sLabels{
@@ -1207,6 +1184,19 @@ restrictions:
12071184
Expect(err).NotTo(HaveOccurred())
12081185
})
12091186
It("No feature labels should be created", func(ctx context.Context) {
1187+
// deploy worker to make sure that labels created by worker are not ignored by denyNodeFeatureLabels restriction
1188+
By("Creating nfd-worker daemonset")
1189+
podSpecOpts := []testpod.SpecOption{
1190+
testpod.SpecWithContainerImage(dockerImage()),
1191+
testpod.SpecWithContainerExtraArgs("-label-sources=fake"),
1192+
}
1193+
workerDS := testds.NFDWorker(podSpecOpts...)
1194+
workerDS, err := f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(ctx, workerDS, metav1.CreateOptions{})
1195+
Expect(err).NotTo(HaveOccurred())
1196+
1197+
By("Waiting for worker daemonset pods to be ready")
1198+
Expect(testpod.WaitForReady(ctx, f.ClientSet, f.Namespace.Name, workerDS.Spec.Template.Labels["name"], 2)).NotTo(HaveOccurred())
1199+
12101200
// deploy node feature object
12111201
nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet)
12121202
Expect(err).NotTo(HaveOccurred())
@@ -1234,7 +1224,7 @@ restrictions:
12341224
"e2e.feature.node.kubernetes.io/restricted-annoation-1": "yes",
12351225
"nfd.node.kubernetes.io/feature-annotations": "e2e.feature.node.kubernetes.io/restricted-annoation-1",
12361226
"nfd.node.kubernetes.io/extended-resources": "e2e.feature.node.kubernetes.io/restricted-er-1",
1237-
"nfd.node.kubernetes.io/feature-labels": "e2e.feature.node.kubernetes.io/restricted-label-1",
1227+
"nfd.node.kubernetes.io/feature-labels": "e2e.feature.node.kubernetes.io/restricted-label-1,fake-fakefeature1,fake-fakefeature2,fake-fakefeature3",
12381228
},
12391229
}
12401230
eventuallyNonControlPlaneNodes(ctx, f.ClientSet).Should(MatchAnnotations(expectedAnnotations, nodes))
@@ -1246,11 +1236,12 @@ restrictions:
12461236
}
12471237
eventuallyNonControlPlaneNodes(ctx, f.ClientSet).WithTimeout(1 * time.Minute).Should(MatchCapacity(expectedCapacity, nodes))
12481238

1249-
// TODO(TessaIO): we need one more test where we deploy nfd-worker that would create
1250-
// a non 3rd-party NF that shouldn't be ignored by this restriction
12511239
By("Verifying node labels from NodeFeature object #6 are not created")
12521240
expectedLabels := map[string]k8sLabels{
12531241
"*": {
1242+
nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature1": "true",
1243+
nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature2": "true",
1244+
nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature3": "true",
12541245
"e2e.feature.node.kubernetes.io/restricted-label-1": "true",
12551246
},
12561247
}

test/e2e/utils/namespace/namespace.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package namespace
18+
19+
import (
20+
"context"
21+
"encoding/json"
22+
"fmt"
23+
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/types"
26+
"k8s.io/kubernetes/test/e2e/framework"
27+
28+
"sigs.k8s.io/node-feature-discovery/pkg/utils"
29+
)
30+
31+
// PatchLabels updates the given label for a specific namespace with a given value
32+
func PatchLabels(name, key, value, operation string, ctx context.Context, f *framework.Framework) error {
33+
if operation != utils.JSONAddOperation && operation != utils.JSONRemoveOperation {
34+
return fmt.Errorf("unknown operation type, known values are %s, %s", utils.JSONAddOperation, utils.JSONRemoveOperation)
35+
}
36+
37+
patches, err := json.Marshal(
38+
[]utils.JsonPatch{
39+
utils.NewJsonPatch(
40+
operation,
41+
"/metadata/labels",
42+
key,
43+
value,
44+
),
45+
},
46+
)
47+
if err != nil {
48+
return err
49+
}
50+
51+
_, err = f.ClientSet.CoreV1().Namespaces().Patch(ctx, name, types.JSONPatchType, patches, metav1.PatchOptions{})
52+
return err
53+
}

0 commit comments

Comments
 (0)