Skip to content

Commit edbb3a3

Browse files
Add NetworkPolicy for DRA pods
DRA pods were the only KMM operand without a NetworkPolicy. Add a deny-all NetworkPolicy (kmm-dra) for them, matching the existing pattern used by worker, build/sign, pull, and device-plugin pods. Also add app.kubernetes.io labels to DRA pod templates so the NetworkPolicy selector can target them.
1 parent f010e15 commit edbb3a3

7 files changed

Lines changed: 200 additions & 20 deletions

File tree

cmd/manager/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func main() {
195195
cmd.FatalError(setupLogger, err, "unable to create controller", "name", controllers.PodNodeLabelReconcilerName)
196196
}
197197

198-
if err = controllers.NewDRAReconciler(client, nodeAPI, scheme).SetupWithManager(mgr); err != nil {
198+
if err = controllers.NewDRAReconciler(client, nodeAPI, networkPolicyAPI, scheme).SetupWithManager(mgr); err != nil {
199199
cmd.FatalError(setupLogger, err, "unable to create controller", "name", controllers.DRAReconcilerName)
200200
}
201201

internal/controllers/dra_reconciler.go

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1"
2525
"github.com/rh-ecosystem-edge/kernel-module-management/internal/constants"
2626
"github.com/rh-ecosystem-edge/kernel-module-management/internal/filter"
27+
"github.com/rh-ecosystem-edge/kernel-module-management/internal/networkpolicy"
2728
"github.com/rh-ecosystem-edge/kernel-module-management/internal/node"
2829
"github.com/rh-ecosystem-edge/kernel-module-management/internal/utils"
2930
appsv1 "k8s.io/api/apps/v1"
@@ -58,9 +59,10 @@ type DRAReconciler struct {
5859
func NewDRAReconciler(
5960
client client.Client,
6061
nodeAPI node.Node,
62+
networkPolicyAPI networkpolicy.NetworkPolicy,
6163
scheme *runtime.Scheme,
6264
) *DRAReconciler {
63-
reconHelperAPI := newDRAReconcilerHelper(client, nodeAPI, scheme)
65+
reconHelperAPI := newDRAReconcilerHelper(client, nodeAPI, networkPolicyAPI, scheme)
6466
return &DRAReconciler{
6567
client: client,
6668
reconHelperAPI: reconHelperAPI,
@@ -101,6 +103,10 @@ func (r *DRAReconciler) Reconcile(ctx context.Context, mod *kmmv1beta1.Module) (
101103
return ctrl.Result{}, r.reconHelperAPI.deleteDRAResources(ctx, mod.Name, mod.Namespace)
102104
}
103105

106+
if err = r.reconHelperAPI.handleDRANetworkPolicy(ctx, mod); err != nil {
107+
return res, fmt.Errorf("failed to handle DRA NetworkPolicy: %v", err)
108+
}
109+
104110
if mod.Spec.DRA == nil {
105111
if err = r.reconHelperAPI.deleteDRAResources(ctx, mod.Name, mod.Namespace); err != nil {
106112
return ctrl.Result{}, err
@@ -138,6 +144,7 @@ func (r *DRAReconciler) Reconcile(ctx context.Context, mod *kmmv1beta1.Module) (
138144
type draReconcilerHelperAPI interface {
139145
getModuleDRADaemonSets(ctx context.Context, name, namespace string) ([]appsv1.DaemonSet, error)
140146
handleDRA(ctx context.Context, mod *kmmv1beta1.Module, existingDRADS []appsv1.DaemonSet) error
147+
handleDRANetworkPolicy(ctx context.Context, mod *kmmv1beta1.Module) error
141148
garbageCollectDRADaemonSets(ctx context.Context, mod *kmmv1beta1.Module, existingDS []appsv1.DaemonSet) error
142149
deleteDRAResources(ctx context.Context, moduleName, moduleNamespace string) error
143150
moduleUpdateDRAStatus(ctx context.Context, mod *kmmv1beta1.Module, existingDRADS []appsv1.DaemonSet) error
@@ -147,20 +154,23 @@ type draReconcilerHelperAPI interface {
147154
}
148155

149156
type draReconcilerHelper struct {
150-
client client.Client
151-
daemonSetHelper draDaemonSetCreator
152-
nodeAPI node.Node
157+
client client.Client
158+
daemonSetHelper draDaemonSetCreator
159+
networkPolicyAPI networkpolicy.NetworkPolicy
160+
nodeAPI node.Node
153161
}
154162

155163
func newDRAReconcilerHelper(client client.Client,
156164
nodeAPI node.Node,
165+
networkPolicyAPI networkpolicy.NetworkPolicy,
157166
scheme *runtime.Scheme,
158167
) draReconcilerHelperAPI {
159168
daemonSetHelper := newDRADaemonSetCreator(scheme)
160169
return &draReconcilerHelper{
161-
client: client,
162-
daemonSetHelper: daemonSetHelper,
163-
nodeAPI: nodeAPI,
170+
client: client,
171+
daemonSetHelper: daemonSetHelper,
172+
networkPolicyAPI: networkPolicyAPI,
173+
nodeAPI: nodeAPI,
164174
}
165175
}
166176

@@ -206,6 +216,23 @@ func (drh *draReconcilerHelper) handleDRA(ctx context.Context, mod *kmmv1beta1.M
206216
return err
207217
}
208218

219+
func (drh *draReconcilerHelper) handleDRANetworkPolicy(ctx context.Context, mod *kmmv1beta1.Module) error {
220+
if mod.Spec.DRA == nil {
221+
return nil
222+
}
223+
224+
logger := log.FromContext(ctx)
225+
logger.Info("Handling DRA NetworkPolicy", "module", mod.Name, "namespace", mod.Namespace)
226+
227+
draPolicy := drh.networkPolicyAPI.DRANetworkPolicy(mod.Namespace)
228+
if err := drh.networkPolicyAPI.CreateOrAddOwnerReference(ctx, draPolicy, mod); err != nil {
229+
return fmt.Errorf("failed to ensure DRA NetworkPolicy %s/%s: %v", draPolicy.Namespace, draPolicy.Name, err)
230+
}
231+
232+
logger.Info("Successfully handled DRA NetworkPolicy")
233+
return nil
234+
}
235+
209236
func (drh *draReconcilerHelper) garbageCollectDRADaemonSets(ctx context.Context, mod *kmmv1beta1.Module, existingDS []appsv1.DaemonSet) error {
210237
if mod.Spec.ModuleLoader == nil {
211238
return nil
@@ -462,11 +489,19 @@ func (dsci *draDaemonSetCreatorImpl) setDRAAsDesired(
462489
overrideLabels(ds.GetLabels(), standardLabels),
463490
)
464491

492+
podTemplateLabels := make(map[string]string, len(standardLabels)+3)
493+
for k, v := range standardLabels {
494+
podTemplateLabels[k] = v
495+
}
496+
podTemplateLabels["app.kubernetes.io/name"] = "kmm"
497+
podTemplateLabels["app.kubernetes.io/component"] = "dra"
498+
podTemplateLabels["app.kubernetes.io/part-of"] = "kmm"
499+
465500
ds.Spec = appsv1.DaemonSetSpec{
466501
Selector: &metav1.LabelSelector{MatchLabels: standardLabels},
467502
Template: v1.PodTemplateSpec{
468503
ObjectMeta: metav1.ObjectMeta{
469-
Labels: standardLabels,
504+
Labels: podTemplateLabels,
470505
Finalizers: []string{constants.NodeLabelerFinalizer},
471506
},
472507
Spec: v1.PodSpec{

internal/controllers/dra_reconciler_test.go

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ import (
2626
kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1"
2727
"github.com/rh-ecosystem-edge/kernel-module-management/internal/client"
2828
"github.com/rh-ecosystem-edge/kernel-module-management/internal/constants"
29+
"github.com/rh-ecosystem-edge/kernel-module-management/internal/networkpolicy"
2930
"github.com/rh-ecosystem-edge/kernel-module-management/internal/node"
3031
"github.com/rh-ecosystem-edge/kernel-module-management/internal/utils"
3132
"go.uber.org/mock/gomock"
3233
appsv1 "k8s.io/api/apps/v1"
3334
v1 "k8s.io/api/core/v1"
35+
networkingv1 "k8s.io/api/networking/v1"
3436
resourcev1 "k8s.io/api/resource/v1"
3537
apierrors "k8s.io/apimachinery/pkg/api/errors"
3638
"k8s.io/apimachinery/pkg/api/resource"
@@ -69,7 +71,7 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
6971

7072
ctx := context.Background()
7173

72-
DescribeTable("check error flows", func(getDSError, getDCError, handleDRAError, gcError, handleDCError bool) {
74+
DescribeTable("check error flows", func(getDSError, getDCError, handleNPError, handleDRAError, gcError, handleDCError bool) {
7375
draDS := []appsv1.DaemonSet{{}}
7476
returnedError := fmt.Errorf("some error")
7577
if getDSError {
@@ -82,6 +84,11 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
8284
goto executeTestFunction
8385
}
8486
mockReconHelper.EXPECT().getModuleDeviceClasses(ctx, mod.Name, mod.Namespace).Return(nil, nil)
87+
if handleNPError {
88+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(returnedError)
89+
goto executeTestFunction
90+
}
91+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(nil)
8592
if handleDRAError {
8693
mockReconHelper.EXPECT().handleDRA(ctx, mod, draDS).Return(returnedError)
8794
goto executeTestFunction
@@ -106,19 +113,21 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
106113
Expect(err).To(HaveOccurred())
107114

108115
},
109-
Entry("getModuleDRADaemonSets failed", true, false, false, false, false),
110-
Entry("getModuleDeviceClasses failed", false, true, false, false, false),
111-
Entry("handleDRA failed", false, false, true, false, false),
112-
Entry("garbageCollectDRADaemonSets failed", false, false, false, true, false),
113-
Entry("handleDeviceClasses failed", false, false, false, false, true),
114-
Entry("moduleUpdateDRAStatus failed", false, false, false, false, false),
116+
Entry("getModuleDRADaemonSets failed", true, false, false, false, false, false),
117+
Entry("getModuleDeviceClasses failed", false, true, false, false, false, false),
118+
Entry("handleDRANetworkPolicy failed", false, false, true, false, false, false),
119+
Entry("handleDRA failed", false, false, false, true, false, false),
120+
Entry("garbageCollectDRADaemonSets failed", false, false, false, false, true, false),
121+
Entry("handleDeviceClasses failed", false, false, false, false, false, true),
122+
Entry("moduleUpdateDRAStatus failed", false, false, false, false, false, false),
115123
)
116124

117125
It("Good flow", func() {
118126
draDS := []appsv1.DaemonSet{{}}
119127
gomock.InOrder(
120128
mockReconHelper.EXPECT().getModuleDRADaemonSets(ctx, mod.Name, mod.Namespace).Return(draDS, nil),
121129
mockReconHelper.EXPECT().getModuleDeviceClasses(ctx, mod.Name, mod.Namespace).Return(nil, nil),
130+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(nil),
122131
mockReconHelper.EXPECT().handleDRA(ctx, mod, draDS).Return(nil),
123132
mockReconHelper.EXPECT().garbageCollectDRADaemonSets(ctx, mod, draDS).Return(nil),
124133
mockReconHelper.EXPECT().handleDeviceClasses(ctx, mod, []resourcev1.DeviceClass(nil)).Return(nil),
@@ -164,6 +173,7 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
164173
gomock.InOrder(
165174
mockReconHelper.EXPECT().getModuleDRADaemonSets(ctx, mod.Name, mod.Namespace).Return(nil, nil),
166175
mockReconHelper.EXPECT().getModuleDeviceClasses(ctx, mod.Name, mod.Namespace).Return(nil, nil),
176+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(nil),
167177
mockReconHelper.EXPECT().deleteDRAResources(ctx, mod.Name, mod.Namespace).Return(nil),
168178
mockReconHelper.EXPECT().clearDRAStatus(ctx, mod).Return(nil),
169179
)
@@ -182,6 +192,7 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
182192
gomock.InOrder(
183193
mockReconHelper.EXPECT().getModuleDRADaemonSets(ctx, mod.Name, mod.Namespace).Return(draDS, nil),
184194
mockReconHelper.EXPECT().getModuleDeviceClasses(ctx, mod.Name, mod.Namespace).Return(existingDCs, nil),
195+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(nil),
185196
mockReconHelper.EXPECT().deleteDRAResources(ctx, mod.Name, mod.Namespace).Return(nil),
186197
mockReconHelper.EXPECT().clearDRAStatus(ctx, mod).Return(nil),
187198
)
@@ -198,6 +209,7 @@ var _ = Describe("DRAReconciler_Reconcile", func() {
198209
gomock.InOrder(
199210
mockReconHelper.EXPECT().getModuleDRADaemonSets(ctx, mod.Name, mod.Namespace).Return(nil, nil),
200211
mockReconHelper.EXPECT().getModuleDeviceClasses(ctx, mod.Name, mod.Namespace).Return(nil, nil),
212+
mockReconHelper.EXPECT().handleDRANetworkPolicy(ctx, mod).Return(nil),
201213
mockReconHelper.EXPECT().deleteDRAResources(ctx, mod.Name, mod.Namespace).Return(nil),
202214
mockReconHelper.EXPECT().clearDRAStatus(ctx, mod).Return(fmt.Errorf("some error")),
203215
)
@@ -314,7 +326,7 @@ var _ = Describe("DRAReconciler_moduleUpdateDRAStatus", func() {
314326
clnt = client.NewMockClient(ctrl)
315327
statusWriter = client.NewMockStatusWriter(ctrl)
316328
mn = node.NewNode(clnt)
317-
drh = newDRAReconcilerHelper(clnt, mn, nil)
329+
drh = newDRAReconcilerHelper(clnt, mn, nil, nil)
318330
})
319331

320332
ctx := context.Background()
@@ -585,11 +597,19 @@ var _ = Describe("DRAReconciler_setDRAAsDesired", func() {
585597
err := dsc.setDRAAsDesired(context.Background(), &ds, &mod)
586598
Expect(err).NotTo(HaveOccurred())
587599

588-
podLabels := map[string]string{
600+
dsLabels := map[string]string{
589601
constants.ModuleNameLabel: draModuleName,
590602
constants.DaemonSetRole: constants.DRARoleLabelValue,
591603
}
592604

605+
podLabels := map[string]string{
606+
constants.ModuleNameLabel: draModuleName,
607+
constants.DaemonSetRole: constants.DRARoleLabelValue,
608+
"app.kubernetes.io/name": "kmm",
609+
"app.kubernetes.io/component": "dra",
610+
"app.kubernetes.io/part-of": "kmm",
611+
}
612+
593613
expectedInitContainer := []v1.Container{
594614
{
595615
Args: args,
@@ -618,7 +638,7 @@ var _ = Describe("DRAReconciler_setDRAAsDesired", func() {
618638
ObjectMeta: metav1.ObjectMeta{
619639
Name: dsName,
620640
Namespace: namespace,
621-
Labels: podLabels,
641+
Labels: dsLabels,
622642
OwnerReferences: []metav1.OwnerReference{
623643
{
624644
APIVersion: mod.APIVersion,
@@ -631,7 +651,7 @@ var _ = Describe("DRAReconciler_setDRAAsDesired", func() {
631651
},
632652
},
633653
Spec: appsv1.DaemonSetSpec{
634-
Selector: &metav1.LabelSelector{MatchLabels: podLabels},
654+
Selector: &metav1.LabelSelector{MatchLabels: dsLabels},
635655
Template: v1.PodTemplateSpec{
636656
ObjectMeta: metav1.ObjectMeta{
637657
Labels: podLabels,
@@ -1239,3 +1259,53 @@ var _ = Describe("DRAReconciler_deleteDRAResources", func() {
12391259
Expect(err.Error()).To(ContainSubstring("DeviceClasses"))
12401260
})
12411261
})
1262+
1263+
var _ = Describe("draReconcilerHelper_handleDRANetworkPolicy", func() {
1264+
var (
1265+
ctrl *gomock.Controller
1266+
mockNP *networkpolicy.MockNetworkPolicy
1267+
drh draReconcilerHelper
1268+
ctx context.Context
1269+
mod *kmmv1beta1.Module
1270+
)
1271+
1272+
BeforeEach(func() {
1273+
ctrl = gomock.NewController(GinkgoT())
1274+
mockNP = networkpolicy.NewMockNetworkPolicy(ctrl)
1275+
ctx = context.Background()
1276+
drh = draReconcilerHelper{
1277+
networkPolicyAPI: mockNP,
1278+
}
1279+
mod = &kmmv1beta1.Module{
1280+
ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: "dra-module"},
1281+
Spec: kmmv1beta1.ModuleSpec{
1282+
DRA: &kmmv1beta1.DRASpec{},
1283+
},
1284+
}
1285+
})
1286+
1287+
It("should return nil when DRA is nil", func() {
1288+
mod.Spec.DRA = nil
1289+
err := drh.handleDRANetworkPolicy(ctx, mod)
1290+
Expect(err).NotTo(HaveOccurred())
1291+
})
1292+
1293+
It("should create the DRA NetworkPolicy", func() {
1294+
policy := &networkingv1.NetworkPolicy{}
1295+
mockNP.EXPECT().DRANetworkPolicy(mod.Namespace).Return(policy)
1296+
mockNP.EXPECT().CreateOrAddOwnerReference(ctx, policy, mod).Return(nil)
1297+
1298+
err := drh.handleDRANetworkPolicy(ctx, mod)
1299+
Expect(err).NotTo(HaveOccurred())
1300+
})
1301+
1302+
It("should return error if CreateOrAddOwnerReference fails", func() {
1303+
policy := &networkingv1.NetworkPolicy{}
1304+
mockNP.EXPECT().DRANetworkPolicy(mod.Namespace).Return(policy)
1305+
mockNP.EXPECT().CreateOrAddOwnerReference(ctx, policy, mod).Return(fmt.Errorf("some error"))
1306+
1307+
err := drh.handleDRANetworkPolicy(ctx, mod)
1308+
Expect(err).To(HaveOccurred())
1309+
Expect(err.Error()).To(ContainSubstring("failed to ensure DRA NetworkPolicy"))
1310+
})
1311+
})

internal/controllers/mock_dra_reconciler.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/networkpolicy/mock_networkpolicy.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/networkpolicy/networkpolicy.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type NetworkPolicy interface {
2222
BuildSignPodsNetworkPolicy(namespace string) *networkingv1.NetworkPolicy
2323
PullPodNetworkPolicy(namespace string) *networkingv1.NetworkPolicy
2424
DevicePluginNetworkPolicy(namespace string) *networkingv1.NetworkPolicy
25+
DRANetworkPolicy(namespace string) *networkingv1.NetworkPolicy
2526
}
2627

2728
type networkPolicy struct {
@@ -41,6 +42,7 @@ const (
4142
buildSignPodsNetworkPolicyName = "kmm-build-and-sign"
4243
pullPodNetworkPolicyName = "kmm-pull"
4344
devicePluginNetworkPolicyName = "kmm-device-plugin"
45+
draNetworkPolicyName = "kmm-dra"
4446
defaultNamespace = "default"
4547
)
4648

@@ -186,3 +188,23 @@ func (np *networkPolicy) DevicePluginNetworkPolicy(namespace string) *networking
186188
},
187189
}
188190
}
191+
192+
func (np *networkPolicy) DRANetworkPolicy(namespace string) *networkingv1.NetworkPolicy {
193+
return &networkingv1.NetworkPolicy{
194+
ObjectMeta: metav1.ObjectMeta{
195+
Name: draNetworkPolicyName,
196+
Namespace: normalizeNamespace(namespace),
197+
},
198+
Spec: networkingv1.NetworkPolicySpec{
199+
PodSelector: metav1.LabelSelector{
200+
MatchLabels: map[string]string{
201+
"app.kubernetes.io/component": "dra",
202+
},
203+
},
204+
PolicyTypes: []networkingv1.PolicyType{
205+
networkingv1.PolicyTypeIngress,
206+
networkingv1.PolicyTypeEgress,
207+
},
208+
},
209+
}
210+
}

0 commit comments

Comments
 (0)