Skip to content

Commit 83561f6

Browse files
committed
Generalize common functions to support other program types
Also, rename application-common.go to common.go. Signed-off-by: Andre Fredette <[email protected]>
1 parent d68ab2a commit 83561f6

File tree

5 files changed

+159
-315
lines changed

5 files changed

+159
-315
lines changed

bundle/manifests/bpfman-operator.clusterserviceversion.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ metadata:
562562
capabilities: Basic Install
563563
categories: OpenShift Optional
564564
containerImage: quay.io/bpfman/bpfman-operator:latest
565-
createdAt: "2025-01-22T17:15:06Z"
565+
createdAt: "2025-01-22T23:05:42Z"
566566
features.operators.openshift.io/cnf: "false"
567567
features.operators.openshift.io/cni: "false"
568568
features.operators.openshift.io/csi: "true"

controllers/app-agent/application-program.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/bpfman/bpfman-operator/internal"
2727

2828
v1 "k8s.io/api/core/v1"
29+
"k8s.io/apimachinery/pkg/api/meta"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/apimachinery/pkg/types"
3132
ctrl "sigs.k8s.io/controller-runtime"
@@ -53,8 +54,12 @@ type BpfApplicationReconciler struct {
5354
ourNode *v1.Node
5455
}
5556

56-
func (r *BpfApplicationReconciler) getRecType() string {
57-
return internal.ApplicationString
57+
// func (r *BpfApplicationReconciler) getRecType() string {
58+
// return internal.ApplicationString
59+
// }
60+
61+
func (r *BpfApplicationReconciler) getAppNodeName() string {
62+
return r.currentAppNode.Name
5863
}
5964

6065
func (r *BpfApplicationReconciler) getNode() *v1.Node {
@@ -69,6 +74,20 @@ func (r *BpfApplicationReconciler) GetStatus() *bpfmaniov1alpha1.BpfAppStatus {
6974
return &r.currentAppNode.Status
7075
}
7176

77+
func (r *BpfApplicationReconciler) isBeingDeleted() bool {
78+
return !r.currentApp.GetDeletionTimestamp().IsZero()
79+
}
80+
81+
func (r *BpfApplicationReconciler) updateBpfAppStatus(ctx context.Context, condition metav1.Condition) error {
82+
r.currentAppNode.Status.Conditions = nil
83+
meta.SetStatusCondition(&r.currentAppNode.Status.Conditions, condition)
84+
return r.Status().Update(ctx, r.currentAppNode)
85+
}
86+
87+
func (r *BpfApplicationReconciler) updateLoadStatus(newCondition bpfmaniov1alpha1.BpfProgramConditionType) {
88+
r.currentAppNode.Spec.AppLoadStatus = newCondition
89+
}
90+
7291
// SetupWithManager sets up the controller with the Manager.
7392
// The Bpfman-Agent should reconcile whenever a BpfApplication object is updated,
7493
// load the programs to the node via bpfman, and then create a bpfProgram object

controllers/app-agent/application-program_test.go

Lines changed: 28 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package appagent
22

33
import (
44
"context"
5+
"reflect"
56
"testing"
67

78
bpfmaniov1alpha1 "github.com/bpfman/bpfman-operator/apis/v1alpha1"
@@ -154,10 +155,7 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
154155

155156
// ANF-TODO: Check more fields?
156157

157-
//////////////////////////////////////////////////////////
158-
// Do another reconcile and make sure there are no changes
159-
//////////////////////////////////////////////////////////
160-
158+
// Do a second reconcile and check that Status was updated
161159
r.Logger.Info("Second reconcile")
162160
res, err = r.Reconcile(ctx, req)
163161
require.NoError(t, err)
@@ -179,12 +177,31 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
179177
require.Equal(t, 1, len(bpfAppNode2.Status.Conditions))
180178
require.Equal(t, string(bpfmaniov1alpha1.ProgramReconcileSuccess), bpfAppNode2.Status.Conditions[0].Type)
181179

182-
// ANF-TODO: This needs to be checked after the 3rd reconcile
183-
// // Check that the bpfAppNode was not updated
184-
// require.True(t, reflect.DeepEqual(bpfAppNode, bpfAppNode2))
180+
// Do a 3rd reconcile and make sure it doesn't change
181+
r.Logger.Info("Third reconcile")
182+
res, err = r.Reconcile(ctx, req)
183+
require.NoError(t, err)
184+
185+
// Require no requeue
186+
require.False(t, res.Requeue)
187+
188+
r.Logger.Info("Third reconcile", "res:", res, "err:", err)
189+
190+
// Check the BpfProgram Object was created successfully
191+
bpfAppNode3, bpfAppNodeNew, err := r.getBpfAppNode(ctx, false)
192+
require.NoError(t, err)
193+
194+
// Make sure we got bpfAppNode from the api server and didn't create a new
195+
// one.
196+
require.Equal(t, false, bpfAppNodeNew)
197+
198+
// Check that the bpfAppNode was not updated
199+
require.True(t, reflect.DeepEqual(bpfAppNode2, bpfAppNode3))
185200

186201
currentProgram := programMap[xdpBpfFunctionName]
187202

203+
attachPoint := bpfAppNode.Spec.Programs[xdpBpfFunctionName].XDP.AttachPoints[0]
204+
188205
xdpReconciler := &XdpProgramReconciler{
189206
ReconcilerCommon: rc,
190207
appCommon: bpfmaniov1alpha1.BpfAppCommon{
@@ -195,190 +212,12 @@ func TestBpfApplicationControllerCreate(t *testing.T) {
195212
},
196213
currentProgram: &currentProgram,
197214
currentProgramNode: &bpfmaniov1alpha1.BpfApplicationProgramNode{},
198-
ourNode: fakeNode,
215+
currentAttachPoint: &attachPoint,
199216
}
200217

201-
attachPoint := bpfAppNode.Spec.Programs[xdpBpfFunctionName].XDP.AttachPoints[0]
202-
203-
loadRequest, err := xdpReconciler.getLoadRequest(xdpBpfFunctionName, &attachPoint, nil)
218+
loadRequest, err := xdpReconciler.getLoadRequest(nil)
204219
require.NoError(t, err)
205220

206-
r.Logger.Info("LoadRequest", "loadRequest:", loadRequest)
207-
// {"loadRequest:": "bytecode:{file:\"/tmp/hello.o\"} name:\"XdpTest\"
208-
// program_type:6 attach:{xdp_attach_info:{priority:50 iface:\"eth0\"
209-
// proceed_on:2 proceed_on:31 netns:\"/host/proc/0/ns/net\"}}
210-
// metadata:{key:\"bpfman.io/ProgramName\" value:\"BpfApplication\"}
211-
// metadata:{key:\"bpfman.io/uuid\"
212-
// value:\"1b464e84-c7b3-4dbf-beab-6de3447673c2\"}"}
213-
214-
// rfentry := &FentryProgramReconciler{ClusterProgramReconciler: rc, ourNode: fakeNode}
215-
// err = r.getBpfProgram(ctx, rfentry, name, fentryAppProgramId, fentryAttachPoint, fentryBpfProg)
216-
// require.NoError(t, err)
217-
218-
// require.NotEmpty(t, fentryBpfProg)
219-
// // Finalizer is written
220-
// require.Equal(t, internal.BpfApplicationControllerFinalizer, fentryBpfProg.Finalizers[0])
221-
// // owningConfig Label was correctly set
222-
// require.Equal(t, name, fentryBpfProg.Labels[internal.BpfProgramOwner])
223-
// // node Label was correctly set
224-
// require.Equal(t, fakeNode.Name, fentryBpfProg.Labels[internal.K8sHostLabel])
225-
// // fentry function Annotation was correctly set
226-
// require.Equal(t, fentryFunctionName, fentryBpfProg.Annotations[internal.FentryProgramFunction])
227-
// // Type is set
228-
// require.Equal(t, r.getRecType(), fentryBpfProg.Spec.Type)
229-
// // Require no requeue
230-
// require.False(t, res.Requeue)
231-
232-
// // Update UID of bpfProgram with Fake UID since the fake API server won't
233-
// fentryBpfProg.UID = types.UID(fentryFakeUID)
234-
// err = cl.Update(ctx, fentryBpfProg)
235-
// require.NoError(t, err)
236-
237-
// // Second reconcile should create the bpfman Load Request and update the
238-
// // BpfProgram object's maps field and id annotation.
239-
// res, err = r.Reconcile(ctx, req)
240-
// if err != nil {
241-
// t.Fatalf("reconcile: (%v)", err)
242-
// }
243-
244-
// // Require no requeue
245-
// require.False(t, res.Requeue)
246-
247-
// // do Fentry Program
248-
// expectedLoadReq := &gobpfman.LoadRequest{
249-
// Bytecode: &gobpfman.BytecodeLocation{
250-
// Location: &gobpfman.BytecodeLocation_File{File: bytecodePath},
251-
// },
252-
// Name: bpfFentryFunctionName,
253-
// ProgramType: *internal.Tracing.Uint32(),
254-
// Metadata: map[string]string{internal.UuidMetadataKey: string(fentryBpfProg.UID), internal.ProgramNameKey: name},
255-
// MapOwnerId: nil,
256-
// Attach: &gobpfman.AttachInfo{
257-
// Info: &gobpfman.AttachInfo_FentryAttachInfo{
258-
// FentryAttachInfo: &gobpfman.FentryAttachInfo{
259-
// FnName: fentryFunctionName,
260-
// },
261-
// },
262-
// },
263-
// }
264-
265-
// // Check that the bpfProgram's programs was correctly updated
266-
// err = r.getBpfProgram(ctx, rfentry, name, fentryAppProgramId, fentryAttachPoint, fentryBpfProg)
267-
// require.NoError(t, err)
268-
269-
// // prog ID should already have been set
270-
// id, err := GetID(fentryBpfProg)
271-
// require.NoError(t, err)
272-
273-
// // Check the bpfLoadRequest was correctly Built
274-
// if !cmp.Equal(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform()) {
275-
// cmp.Diff(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform())
276-
// t.Logf("Diff %v", cmp.Diff(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform()))
277-
// t.Fatal("Built bpfman LoadRequest does not match expected")
278-
// }
279-
280-
// // Third reconcile should set the status to loaded
281-
// res, err = r.Reconcile(ctx, req)
282-
// if err != nil {
283-
// t.Fatalf("reconcile: (%v)", err)
284-
// }
285-
286-
// // Require no requeue
287-
// require.False(t, res.Requeue)
288-
289-
// // Check that the bpfProgram's status was correctly updated
290-
// err = r.getBpfProgram(ctx, rfentry, name, fentryAppProgramId, fentryAttachPoint, fentryBpfProg)
291-
// require.NoError(t, err)
292-
293-
// require.Equal(t, string(bpfmaniov1alpha1.BpfProgCondLoaded), fentryBpfProg.Status.Conditions[0].Type)
294-
295-
// // do kprobe program
296-
// // First reconcile should create the bpf program object
297-
// res, err = r.Reconcile(ctx, req)
298-
// if err != nil {
299-
// t.Fatalf("reconcile: (%v)", err)
300-
// }
301-
302-
// rkprobe := &KprobeProgramReconciler{ClusterProgramReconciler: rc, ourNode: fakeNode}
303-
// err = r.getBpfProgram(ctx, rkprobe, name, kprobeAppProgramId, kprobeAttachPoint, kprobeBpfProg)
304-
// require.NoError(t, err)
305-
306-
// require.NotEmpty(t, kprobeBpfProg)
307-
// // Finalizer is written
308-
// require.Equal(t, internal.BpfApplicationControllerFinalizer, kprobeBpfProg.Finalizers[0])
309-
// // owningConfig Label was correctly set
310-
// require.Equal(t, name, kprobeBpfProg.Labels[internal.BpfProgramOwner])
311-
// // node Label was correctly set
312-
// require.Equal(t, fakeNode.Name, kprobeBpfProg.Labels[internal.K8sHostLabel])
313-
// // fentry function Annotation was correctly set
314-
// require.Equal(t, kprobeFunctionName, kprobeBpfProg.Annotations[internal.KprobeProgramFunction])
315-
// // Type is set
316-
// require.Equal(t, r.getRecType(), kprobeBpfProg.Spec.Type)
317-
// // Require no requeue
318-
// require.False(t, res.Requeue)
319-
320-
// // Update UID of bpfProgram with Fake UID since the fake API server won't
321-
// kprobeBpfProg.UID = types.UID(kprobeFakeUID)
322-
// err = cl.Update(ctx, kprobeBpfProg)
323-
// require.NoError(t, err)
324-
325-
// // Second reconcile should create the bpfman Load Request and update the
326-
// // BpfProgram object's maps field and id annotation.
327-
// res, err = r.Reconcile(ctx, req)
328-
// if err != nil {
329-
// t.Fatalf("reconcile: (%v)", err)
330-
// }
331-
332-
// // Require no requeue
333-
// require.False(t, res.Requeue)
334-
335-
// expectedLoadReq = &gobpfman.LoadRequest{
336-
// Bytecode: &gobpfman.BytecodeLocation{
337-
// Location: &gobpfman.BytecodeLocation_File{File: bytecodePath},
338-
// },
339-
// Name: bpfKprobeFunctionName,
340-
// ProgramType: *internal.Kprobe.Uint32(),
341-
// Metadata: map[string]string{internal.UuidMetadataKey: string(kprobeBpfProg.UID), internal.ProgramNameKey: name},
342-
// MapOwnerId: nil,
343-
// Attach: &gobpfman.AttachInfo{
344-
// Info: &gobpfman.AttachInfo_KprobeAttachInfo{
345-
// KprobeAttachInfo: &gobpfman.KprobeAttachInfo{
346-
// FnName: kprobeFunctionName,
347-
// Offset: uint64(kprobeOffset),
348-
// Retprobe: kprobeRetprobe,
349-
// ContainerPid: &kprobecontainerpid,
350-
// },
351-
// },
352-
// },
353-
// }
354-
355-
// // Check that the bpfProgram's programs was correctly updated
356-
// err = r.getBpfProgram(ctx, rkprobe, name, kprobeAppProgramId, kprobeAttachPoint, kprobeBpfProg)
357-
// require.NoError(t, err)
358-
359-
// // prog ID should already have been set
360-
// id, err = GetID(kprobeBpfProg)
361-
// require.NoError(t, err)
362-
363-
// // Check the bpfLoadRequest was correctly Built
364-
// if !cmp.Equal(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform()) {
365-
// cmp.Diff(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform())
366-
// t.Logf("Diff %v", cmp.Diff(expectedLoadReq, cli.LoadRequests[int(*id)], protocmp.Transform()))
367-
// t.Fatal("Built bpfman LoadRequest does not match expected")
368-
// }
369-
370-
// // Third reconcile should set the status to loaded
371-
// res, err = r.Reconcile(ctx, req)
372-
// if err != nil {
373-
// t.Fatalf("reconcile: (%v)", err)
374-
// }
375-
376-
// // Require no requeue
377-
// require.False(t, res.Requeue)
378-
379-
// // Check that the bpfProgram's status was correctly updated
380-
// err = r.getBpfProgram(ctx, rkprobe, name, kprobeAppProgramId, kprobeAttachPoint, kprobeBpfProg)
381-
// require.NoError(t, err)
382-
383-
// require.Equal(t, string(bpfmaniov1alpha1.BpfProgCondLoaded), kprobeBpfProg.Status.Conditions[0].Type)
221+
require.Equal(t, xdpBpfFunctionName, loadRequest.Name)
222+
require.Equal(t, uint32(6), loadRequest.ProgramType)
384223
}

0 commit comments

Comments
 (0)