diff --git a/config/crd/bases/bpfman.io_bpfapplications.yaml b/config/crd/bases/bpfman.io_bpfapplications.yaml index 295294ae7..ea865814c 100644 --- a/config/crd/bases/bpfman.io_bpfapplications.yaml +++ b/config/crd/bases/bpfman.io_bpfapplications.yaml @@ -39,6 +39,51 @@ spec: spec: description: BpfApplicationSpec defines the desired state of BpfApplication properties: + bytecode: + description: |- + Bytecode configures where the bpf program's bytecode should be loaded + from. + properties: + image: + description: Image used to specify a bytecode container image. + properties: + imagepullpolicy: + default: IfNotPresent + description: PullPolicy describes a policy for if/when to + pull a bytecode image. Defaults to IfNotPresent. + enum: + - Always + - Never + - IfNotPresent + type: string + imagepullsecret: + description: |- + ImagePullSecret is the name of the secret bpfman should use to get remote image + repository secrets. + properties: + name: + description: Name of the secret which contains the credentials + to access the image repository. + type: string + namespace: + description: Namespace of the secret which contains the + credentials to access the image repository. + type: string + required: + - name + - namespace + type: object + url: + description: Valid container image URL used to reference a + remote bytecode image. + type: string + required: + - url + type: object + path: + description: Path is used to specify a bytecode object via filepath. + type: string + type: object globaldata: additionalProperties: format: byte @@ -116,53 +161,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object func_name: description: Function to attach the fentry to. type: string @@ -218,7 +216,6 @@ spec: x-kubernetes-map-type: atomic required: - bpffunctionname - - bytecode - func_name type: object fexit: @@ -230,53 +227,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object func_name: description: Function to attach the fexit to. type: string @@ -332,7 +282,6 @@ spec: x-kubernetes-map-type: atomic required: - bpffunctionname - - bytecode - func_name type: object kprobe: @@ -344,53 +293,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object func_name: description: Functions to attach the kprobe to. type: string @@ -458,7 +360,6 @@ spec: type: boolean required: - bpffunctionname - - bytecode - func_name type: object kretprobe: @@ -470,53 +371,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object func_name: description: Functions to attach the kprobe to. type: string @@ -584,7 +438,6 @@ spec: type: boolean required: - bpffunctionname - - bytecode - func_name type: object tc: @@ -596,53 +449,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object direction: description: |- Direction specifies the direction of traffic the tc program should @@ -753,7 +559,6 @@ spec: type: array required: - bpffunctionname - - bytecode - direction - interfaceselector - priority @@ -767,53 +572,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object mapownerselector: description: |- MapOwnerSelector is used to select the loaded eBPF program this eBPF program @@ -873,7 +631,6 @@ spec: type: array required: - bpffunctionname - - bytecode - names type: object type: @@ -899,53 +656,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object containers: description: |- Containers identifes the set of containers in which to attach the uprobe. @@ -1093,7 +803,6 @@ spec: type: string required: - bpffunctionname - - bytecode - target type: object uretprobe: @@ -1105,53 +814,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object containers: description: |- Containers identifes the set of containers in which to attach the uprobe. @@ -1299,7 +961,6 @@ spec: type: string required: - bpffunctionname - - bytecode - target type: object xdp: @@ -1311,53 +972,6 @@ spec: BpfFunctionName is the name of the function that is the entry point for the BPF program type: string - bytecode: - description: |- - Bytecode configures where the bpf program's bytecode should be loaded - from. - properties: - image: - description: Image used to specify a bytecode container - image. - properties: - imagepullpolicy: - default: IfNotPresent - description: PullPolicy describes a policy for if/when - to pull a bytecode image. Defaults to IfNotPresent. - enum: - - Always - - Never - - IfNotPresent - type: string - imagepullsecret: - description: |- - ImagePullSecret is the name of the secret bpfman should use to get remote image - repository secrets. - properties: - name: - description: Name of the secret which contains - the credentials to access the image repository. - type: string - namespace: - description: Namespace of the secret which contains - the credentials to access the image repository. - type: string - required: - - name - - namespace - type: object - url: - description: Valid container image URL used to reference - a remote bytecode image. - type: string - required: - - url - type: object - path: - description: Path is used to specify a bytecode object - via filepath. - type: string - type: object interfaceselector: description: Selector to determine the network interface (or interfaces) @@ -1452,7 +1066,6 @@ spec: type: array required: - bpffunctionname - - bytecode - interfaceselector - priority type: object @@ -1460,6 +1073,7 @@ spec: minItems: 1 type: array required: + - bytecode - nodeselector type: object status: diff --git a/controllers/bpfman-agent/application-program.go b/controllers/bpfman-agent/application-program.go index 64d131afb..b6387a72c 100644 --- a/controllers/bpfman-agent/application-program.go +++ b/controllers/bpfman-agent/application-program.go @@ -49,6 +49,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque r.currentApp = &bpfmaniov1alpha1.BpfApplication{} r.ourNode = &v1.Node{} r.Logger = ctrl.Log.WithName("application") + r.appOwner = &bpfmaniov1alpha1.BpfApplication{} ctxLogger := log.FromContext(ctx) ctxLogger.Info("Reconcile Application: Enter", "ReconcileKey", req) @@ -75,9 +76,12 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque var res ctrl.Result var err error + var complete bool for _, a := range appPrograms.Items { + complete = false for _, p := range a.Spec.Programs { + complete = false switch p.Type { case bpfmaniov1alpha1.ProgTypeFentry: fentryProgram := bpfmaniov1alpha1.FentryProgram{ @@ -95,7 +99,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } fentryObjects := []client.Object{&fentryProgram} // Reconcile FentryProgram. - res, err = r.reconcileCommon(ctx, rec, fentryObjects) + complete, res, err = r.reconcileCommon(ctx, rec, fentryObjects) case bpfmaniov1alpha1.ProgTypeFexit: fexitProgram := bpfmaniov1alpha1.FexitProgram{ @@ -113,7 +117,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } fexitObjects := []client.Object{&fexitProgram} // Reconcile FexitProgram. - res, err = r.reconcileCommon(ctx, rec, fexitObjects) + complete, res, err = r.reconcileCommon(ctx, rec, fexitObjects) case bpfmaniov1alpha1.ProgTypeKprobe, bpfmaniov1alpha1.ProgTypeKretprobe: @@ -132,7 +136,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } kprobeObjects := []client.Object{&kprobeProgram} // Reconcile KprobeProgram or KpretprobeProgram. - res, err = r.reconcileCommon(ctx, rec, kprobeObjects) + complete, res, err = r.reconcileCommon(ctx, rec, kprobeObjects) case bpfmaniov1alpha1.ProgTypeUprobe, bpfmaniov1alpha1.ProgTypeUretprobe: @@ -151,7 +155,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } uprobeObjects := []client.Object{&uprobeProgram} // Reconcile UprobeProgram or UpretprobeProgram. - res, err = r.reconcileCommon(ctx, rec, uprobeObjects) + complete, res, err = r.reconcileCommon(ctx, rec, uprobeObjects) case bpfmaniov1alpha1.ProgTypeTracepoint: tracepointProgram := bpfmaniov1alpha1.TracepointProgram{ @@ -169,7 +173,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } tracepointObjects := []client.Object{&tracepointProgram} // Reconcile TracepointProgram. - res, err = r.reconcileCommon(ctx, rec, tracepointObjects) + complete, res, err = r.reconcileCommon(ctx, rec, tracepointObjects) case bpfmaniov1alpha1.ProgTypeTC, bpfmaniov1alpha1.ProgTypeTCX: @@ -188,7 +192,7 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } tcObjects := []client.Object{&tcProgram} // Reconcile TcProgram. - res, err = r.reconcileCommon(ctx, rec, tcObjects) + complete, res, err = r.reconcileCommon(ctx, rec, tcObjects) case bpfmaniov1alpha1.ProgTypeXDP: xdpProgram := bpfmaniov1alpha1.XdpProgram{ @@ -206,12 +210,26 @@ func (r *BpfApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Reque } xdpObjects := []client.Object{&xdpProgram} // Reconcile XdpProgram. - res, err = r.reconcileCommon(ctx, rec, xdpObjects) + complete, res, err = r.reconcileCommon(ctx, rec, xdpObjects) default: r.Logger.Info("Unsupported Bpf program type", "ProgType", p.Type) - return ctrl.Result{Requeue: false}, nil + continue } + + if complete { + // We've completed reconciling this program, continue to the next one + continue + } else { + return res, err + } + } + + if complete { + // We've completed reconciling all programs for this application, continue to the next one + continue + } else { + return res, err } } @@ -227,6 +245,7 @@ func (r *BpfApplicationReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&bpfmaniov1alpha1.BpfApplication{}, builder.WithPredicates(predicate.And(predicate.GenerationChangedPredicate{}, predicate.ResourceVersionChangedPredicate{}))). Owns(&bpfmaniov1alpha1.BpfProgram{}, builder.WithPredicates(predicate.And( + internal.BpfProgramTypePredicate(internal.ApplicationString), internal.BpfProgramNodePredicate(r.NodeName)), ), ). diff --git a/controllers/bpfman-agent/application-program_test.go b/controllers/bpfman-agent/application-program_test.go index 7f2813408..2a43b8aa5 100644 --- a/controllers/bpfman-agent/application-program_test.go +++ b/controllers/bpfman-agent/application-program_test.go @@ -34,6 +34,9 @@ func TestBpfApplicationControllerCreate(t *testing.T) { Spec: bpfmaniov1alpha1.BpfApplicationSpec{ BpfAppCommon: bpfmaniov1alpha1.BpfAppCommon{ NodeSelector: metav1.LabelSelector{}, + ByteCode: bpfmaniov1alpha1.BytecodeSelector{ + Path: &bytecodePath, + }, }, Programs: []bpfmaniov1alpha1.BpfApplicationProgram{ { @@ -41,9 +44,6 @@ func TestBpfApplicationControllerCreate(t *testing.T) { Fentry: &bpfmaniov1alpha1.FentryProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfFentryFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, FunctionName: functionFentryName, }, @@ -53,9 +53,6 @@ func TestBpfApplicationControllerCreate(t *testing.T) { Kprobe: &bpfmaniov1alpha1.KprobeProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfKprobeFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, FunctionName: functionKprobeName, Offset: uint64(offset), @@ -67,9 +64,6 @@ func TestBpfApplicationControllerCreate(t *testing.T) { Tracepoint: &bpfmaniov1alpha1.TracepointProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfTracepointFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, Names: []string{tracepointName}, }, diff --git a/controllers/bpfman-agent/common.go b/controllers/bpfman-agent/common.go index 6485dd417..6c16c6482 100644 --- a/controllers/bpfman-agent/common.go +++ b/controllers/bpfman-agent/common.go @@ -71,6 +71,7 @@ type ReconcilerCommon struct { Logger logr.Logger NodeName string progId *uint32 + appOwner metav1.Object // Set if the owner is an application } // bpfmanReconciler defines a generic bpfProgram K8s object reconciler which can @@ -88,6 +89,9 @@ type bpfmanReconciler interface { // getFinalizer returns the string used for the finalizer to prevent the // BpfProgram object from deletion until cleanup can be performed getFinalizer() string + // getOwner returns the owner of the BpfProgram object. This is either the + // *Program or the BpfApplicationProgram that created it. + getOwner() metav1.Object // getRecType returns the type of the reconciler. This is often the string // representation of the ProgramType, but in cases where there are multiple // reconcilers for a single ProgramType, it may be different (e.g., uprobe, @@ -119,13 +123,16 @@ type bpfmanReconciler interface { } // reconcileCommon is the common reconciler loop called by each bpfman -// reconciler. It reconciles each program in the list. reconcileCommon should -// not return error because it will trigger an infinite reconcile loop. -// Instead, it should report the error to user and retry if specified. For some -// errors the controller may decide not to retry. Note: This only results in -// calls to bpfman if we need to change something +// reconciler. It reconciles each program in the list. The boolean return +// value is set to true if we've made it through all the programs in the list +// without anything being updated and a reque has not been requested. Otherwise, +// it's set to false. reconcileCommon should not return error because it will +// trigger an infinite reconcile loop. Instead, it should report the error to +// user and retry if specified. For some errors the controller may decide not to +// retry. Note: This only results in calls to bpfman if we need to change +// something func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconciler, - programs []client.Object) (ctrl.Result, error) { + programs []client.Object) (bool, ctrl.Result, error) { r.Logger.V(1).Info("Start reconcileCommon()") @@ -133,7 +140,7 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc loadedBpfPrograms, err := bpfmanagentinternal.ListBpfmanPrograms(ctx, r.BpfmanClient, rec.getProgType()) if err != nil { r.Logger.Error(err, "failed to list loaded bpfman programs") - return ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil + return false, ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil } requeue := false // initialize requeue to false @@ -144,7 +151,7 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc err := rec.setCurrentProgram(program) if err != nil { r.Logger.Error(err, "Failed to set current program") - return ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil + return false, ctrl.Result{Requeue: true, RequeueAfter: retryDurationAgent}, nil } result, err := r.reconcileProgram(ctx, rec, program, loadedBpfPrograms) @@ -157,7 +164,7 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc // continue with next program case internal.Updated: // return - return ctrl.Result{Requeue: false}, nil + return false, ctrl.Result{Requeue: false}, nil case internal.Requeue: // remember to do a requeue when we're done and continue with next program requeue = true @@ -166,11 +173,11 @@ func (r *ReconcilerCommon) reconcileCommon(ctx context.Context, rec bpfmanReconc if requeue { // A requeue has been requested - return ctrl.Result{RequeueAfter: retryDurationAgent}, nil + return false, ctrl.Result{RequeueAfter: retryDurationAgent}, nil } else { // We've made it through all the programs in the list without anything being // updated and a reque has not been requested. - return ctrl.Result{Requeue: false}, nil + return true, ctrl.Result{Requeue: false}, nil } } diff --git a/controllers/bpfman-agent/fentry-program.go b/controllers/bpfman-agent/fentry-program.go index 872f6b77d..4a7c03169 100644 --- a/controllers/bpfman-agent/fentry-program.go +++ b/controllers/bpfman-agent/fentry-program.go @@ -50,8 +50,20 @@ func (r *FentryProgramReconciler) getFinalizer() string { return internal.FentryProgramControllerFinalizer } +func (r *FentryProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentFentryProgram + } else { + return r.appOwner + } +} + func (r *FentryProgramReconciler) getRecType() string { - return internal.FentryString + if r.appOwner == nil { + return internal.FentryString + } else { + return internal.ApplicationString + } } func (r *FentryProgramReconciler) getProgType() internal.ProgramType { @@ -122,7 +134,7 @@ func (r *FentryProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (* annotations := map[string]string{internal.FentryProgramFunction: r.currentFentryProgram.Spec.FunctionName} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentFentryProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -168,7 +180,8 @@ func (r *FentryProgramReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Reconcile each FentryProgram. - return r.reconcileCommon(ctx, r, fentryObjects) + _, result, err := r.reconcileCommon(ctx, r, fentryObjects) + return result, err } func (r *FentryProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/fexit-program.go b/controllers/bpfman-agent/fexit-program.go index ca45313cd..4843937cc 100644 --- a/controllers/bpfman-agent/fexit-program.go +++ b/controllers/bpfman-agent/fexit-program.go @@ -50,8 +50,20 @@ func (r *FexitProgramReconciler) getFinalizer() string { return internal.FexitProgramControllerFinalizer } +func (r *FexitProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentFexitProgram + } else { + return r.appOwner + } +} + func (r *FexitProgramReconciler) getRecType() string { - return internal.FexitString + if r.appOwner == nil { + return internal.FexitString + } else { + return internal.ApplicationString + } } func (r *FexitProgramReconciler) getProgType() internal.ProgramType { @@ -122,7 +134,7 @@ func (r *FexitProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*b annotations := map[string]string{internal.FexitProgramFunction: r.currentFexitProgram.Spec.FunctionName} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentFexitProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -168,7 +180,8 @@ func (r *FexitProgramReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Reconcile each FexitProgram. - return r.reconcileCommon(ctx, r, fexitObjects) + _, result, err := r.reconcileCommon(ctx, r, fexitObjects) + return result, err } func (r *FexitProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/kprobe-program.go b/controllers/bpfman-agent/kprobe-program.go index 01766e103..d823ba307 100644 --- a/controllers/bpfman-agent/kprobe-program.go +++ b/controllers/bpfman-agent/kprobe-program.go @@ -50,8 +50,20 @@ func (r *KprobeProgramReconciler) getFinalizer() string { return internal.KprobeProgramControllerFinalizer } +func (r *KprobeProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentKprobeProgram + } else { + return r.appOwner + } +} + func (r *KprobeProgramReconciler) getRecType() string { - return internal.Kprobe.String() + if r.appOwner == nil { + return internal.Kprobe.String() + } else { + return internal.ApplicationString + } } func (r *KprobeProgramReconciler) getProgType() internal.ProgramType { @@ -122,7 +134,7 @@ func (r *KprobeProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (* annotations := map[string]string{internal.KprobeProgramFunction: r.currentKprobeProgram.Spec.FunctionName} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentKprobeProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -168,7 +180,8 @@ func (r *KprobeProgramReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Reconcile each KprobeProgram. - return r.reconcileCommon(ctx, r, kprobeObjects) + _, result, err := r.reconcileCommon(ctx, r, kprobeObjects) + return result, err } func (r *KprobeProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/tc-program.go b/controllers/bpfman-agent/tc-program.go index 935b04f26..d9571b1d1 100644 --- a/controllers/bpfman-agent/tc-program.go +++ b/controllers/bpfman-agent/tc-program.go @@ -51,8 +51,20 @@ func (r *TcProgramReconciler) getFinalizer() string { return internal.TcProgramControllerFinalizer } +func (r *TcProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentTcProgram + } else { + return r.appOwner + } +} + func (r *TcProgramReconciler) getRecType() string { - return internal.Tc.String() + if r.appOwner == nil { + return internal.Tc.String() + } else { + return internal.ApplicationString + } } func (r *TcProgramReconciler) getProgType() internal.ProgramType { @@ -164,7 +176,7 @@ func (r *TcProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*bpfm bpfProgramName := fmt.Sprintf("%s-%s-%s", r.currentTcProgram.Name, r.NodeName, iface) annotations := map[string]string{internal.TcProgramInterface: iface} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentTcProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -211,7 +223,8 @@ func (r *TcProgramReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( } // Reconcile each TcProgram. - return r.reconcileCommon(ctx, r, tcObjects) + _, result, err := r.reconcileCommon(ctx, r, tcObjects) + return result, err } func (r *TcProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/tracepoint-program.go b/controllers/bpfman-agent/tracepoint-program.go index fdc00bf53..741203422 100644 --- a/controllers/bpfman-agent/tracepoint-program.go +++ b/controllers/bpfman-agent/tracepoint-program.go @@ -50,8 +50,20 @@ func (r *TracepointProgramReconciler) getFinalizer() string { return internal.TracepointProgramControllerFinalizer } +func (r *TracepointProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentTracepointProgram + } else { + return r.appOwner + } +} + func (r *TracepointProgramReconciler) getRecType() string { - return internal.Tracepoint.String() + if r.appOwner == nil { + return internal.Tracepoint.String() + } else { + return internal.ApplicationString + } } func (r *TracepointProgramReconciler) getProgType() internal.ProgramType { @@ -123,7 +135,7 @@ func (r *TracepointProgramReconciler) getExpectedBpfPrograms(ctx context.Context annotations := map[string]string{internal.TracepointProgramTracepoint: tracepoint} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentTracepointProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -170,7 +182,8 @@ func (r *TracepointProgramReconciler) Reconcile(ctx context.Context, req ctrl.Re } // Reconcile each TcProgram. - return r.reconcileCommon(ctx, r, tracepointObjects) + _, result, err := r.reconcileCommon(ctx, r, tracepointObjects) + return result, err } func (r *TracepointProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/uprobe-program.go b/controllers/bpfman-agent/uprobe-program.go index c1092ae01..c88ab0397 100644 --- a/controllers/bpfman-agent/uprobe-program.go +++ b/controllers/bpfman-agent/uprobe-program.go @@ -51,8 +51,20 @@ func (r *UprobeProgramReconciler) getFinalizer() string { return internal.UprobeProgramControllerFinalizer } +func (r *UprobeProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentUprobeProgram + } else { + return r.appOwner + } +} + func (r *UprobeProgramReconciler) getRecType() string { - return internal.UprobeString + if r.appOwner == nil { + return internal.UprobeString + } else { + return internal.ApplicationString + } } func (r *UprobeProgramReconciler) getProgType() internal.ProgramType { @@ -171,7 +183,7 @@ func (r *UprobeProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (* bpfProgramName := fmt.Sprintf("%s-%s", bpfProgramNameBase, "no-containers-on-node") - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentUprobeProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramNameBase, err) } @@ -188,7 +200,7 @@ func (r *UprobeProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (* bpfProgramName := fmt.Sprintf("%s-%s-%s", bpfProgramNameBase, container.podName, container.containerName) - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentUprobeProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -199,7 +211,7 @@ func (r *UprobeProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (* } else { annotations := map[string]string{internal.UprobeProgramTarget: r.currentUprobeProgram.Spec.Target} - prog, err := r.createBpfProgram(bpfProgramNameBase, r.getFinalizer(), r.currentUprobeProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramNameBase, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramNameBase, err) } @@ -246,7 +258,8 @@ func (r *UprobeProgramReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Reconcile each TcProgram. - return r.reconcileCommon(ctx, r, uprobeObjects) + _, result, err := r.reconcileCommon(ctx, r, uprobeObjects) + return result, err } func (r *UprobeProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-agent/xdp-program.go b/controllers/bpfman-agent/xdp-program.go index ff185f668..8b30023f1 100644 --- a/controllers/bpfman-agent/xdp-program.go +++ b/controllers/bpfman-agent/xdp-program.go @@ -50,10 +50,21 @@ func (r *XdpProgramReconciler) getFinalizer() string { return internal.XdpProgramControllerFinalizer } -func (r *XdpProgramReconciler) getRecType() string { - return internal.Xdp.String() +func (r *XdpProgramReconciler) getOwner() metav1.Object { + if r.appOwner == nil { + return r.currentXdpProgram + } else { + return r.appOwner + } } +func (r *XdpProgramReconciler) getRecType() string { + if r.appOwner == nil { + return internal.Xdp.String() + } else { + return internal.ApplicationString + } +} func (r *XdpProgramReconciler) getProgType() internal.ProgramType { return internal.Xdp } @@ -150,7 +161,7 @@ func (r *XdpProgramReconciler) getExpectedBpfPrograms(ctx context.Context) (*bpf bpfProgramName := fmt.Sprintf("%s-%s-%s", r.currentXdpProgram.Name, r.NodeName, iface) annotations := map[string]string{internal.XdpProgramInterface: iface} - prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.currentXdpProgram, r.getRecType(), annotations) + prog, err := r.createBpfProgram(bpfProgramName, r.getFinalizer(), r.getOwner(), r.getRecType(), annotations) if err != nil { return nil, fmt.Errorf("failed to create BpfProgram %s: %v", bpfProgramName, err) } @@ -196,7 +207,8 @@ func (r *XdpProgramReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Reconcile each TcProgram. - return r.reconcileCommon(ctx, r, xdpObjects) + _, result, err := r.reconcileCommon(ctx, r, xdpObjects) + return result, err } func (r *XdpProgramReconciler) getLoadRequest(bpfProgram *bpfmaniov1alpha1.BpfProgram, mapOwnerId *uint32) (*gobpfman.LoadRequest, error) { diff --git a/controllers/bpfman-operator/application-program_test.go b/controllers/bpfman-operator/application-program_test.go index c4ed5064b..257b977a4 100644 --- a/controllers/bpfman-operator/application-program_test.go +++ b/controllers/bpfman-operator/application-program_test.go @@ -64,6 +64,9 @@ func appProgramReconcile(t *testing.T, multiCondition bool) { Spec: bpfmaniov1alpha1.BpfApplicationSpec{ BpfAppCommon: bpfmaniov1alpha1.BpfAppCommon{ NodeSelector: metav1.LabelSelector{}, + ByteCode: bpfmaniov1alpha1.BytecodeSelector{ + Path: &bytecodePath, + }, }, Programs: []bpfmaniov1alpha1.BpfApplicationProgram{ { @@ -71,9 +74,6 @@ func appProgramReconcile(t *testing.T, multiCondition bool) { Fentry: &bpfmaniov1alpha1.FentryProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfFentryFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, FunctionName: functionFentryName, }, @@ -83,9 +83,6 @@ func appProgramReconcile(t *testing.T, multiCondition bool) { Kprobe: &bpfmaniov1alpha1.KprobeProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfKprobeFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, FunctionName: functionKprobeName, Offset: uint64(offset), @@ -97,9 +94,6 @@ func appProgramReconcile(t *testing.T, multiCondition bool) { Tracepoint: &bpfmaniov1alpha1.TracepointProgramInfo{ BpfProgramCommon: bpfmaniov1alpha1.BpfProgramCommon{ BpfFunctionName: bpfTracepointFunctionName, - ByteCode: bpfmaniov1alpha1.BytecodeSelector{ - Path: &bytecodePath, - }, }, Names: []string{tracepointName}, }, diff --git a/internal/constants.go b/internal/constants.go index d6d2533f3..84449b30e 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -228,6 +228,7 @@ func (p ProgramType) String() string { const UprobeString = "uprobe" const FentryString = "fentry" const FexitString = "fexit" +const ApplicationString = "application" type ReconcileResult uint8