diff --git a/apis/v1alpha1/bpf_application_state_types.go b/apis/v1alpha1/bpf_application_state_types.go index f3142de3b..da695e66d 100644 --- a/apis/v1alpha1/bpf_application_state_types.go +++ b/apis/v1alpha1/bpf_application_state_types.go @@ -18,8 +18,6 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - metav1types "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" ) // +union @@ -52,7 +50,7 @@ type BpfApplicationProgramState struct { // +unionDiscriminator // +required // +kubebuilder:validation:Enum:="XDP";"TC";"TCX";"UProbe";"URetProbe" - Type EBPFProgType `json:"type"` + Type EBPFProgType `json:"type,omitempty"` // xdp contains the attachment data for an XDP program when type is set to XDP. // +unionMember @@ -83,15 +81,32 @@ type BpfApplicationProgramState struct { } type BpfApplicationStateStatus struct { - // UpdateCount tracks the number of times the BpfApplicationState object has + // conditions contains the summary state of the BpfApplication for the given + // Kubernetes node. If one or more programs failed to load or attach to the + // designated attachment point, the condition will report the error. If more + // than one error has occurred, condition will contain the first error + // encountered. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + // +optional + // +kubebuilder:validation:MaxItems=1023 + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + // updateCount tracks the number of times the BpfApplicationState object has // been updated. The bpfman agent initializes it to 1 when it creates the // object, and then increments it before each subsequent update. It serves // as a lightweight sequence number to verify that the API server is serving // the most recent version of the object before beginning a new Reconcile // operation. - UpdateCount int64 `json:"updateCount"` - // node is the name of the Kubernets node for this BpfApplicationState. - Node string `json:"node"` + // +kubebuilder:validation:Minimum=1 + // +optional + UpdateCount int64 `json:"updateCount,omitempty"` + // node is the name of the Kubernetes node for this BpfApplicationState. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Node string `json:"node,omitempty"` // appLoadStatus reflects the status of loading the eBPF application on the // given node. // @@ -113,21 +128,15 @@ type BpfApplicationStateStatus struct { // // UnloadError is returned if one or more programs encountered an error when // being unloaded. - AppLoadStatus AppLoadStatus `json:"appLoadStatus"` + // +optional + AppLoadStatus AppLoadStatus `json:"appLoadStatus,omitempty"` // programs is a list of eBPF programs contained in the parent BpfApplication // instance. Each entry in the list contains the derived program attributes as // well as the attach status for each program on the given Kubernetes node. + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + // +optional Programs []BpfApplicationProgramState `json:"programs,omitempty"` - // conditions contains the summary state of the BpfApplication for the given - // Kubernetes node. If one or more programs failed to load or attach to the - // designated attachment point, the condition will report the error. If more - // than one error has occurred, condition will contain the first error - // encountered. - // +patchMergeKey=type - // +patchStrategy=merge - // +listType=map - // +listMapKey=type - Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` } // +genclient @@ -143,13 +152,16 @@ type BpfApplicationStateStatus struct { // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[0].reason` // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" type BpfApplicationState struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // metadata is the object's metadata. + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // status reflects the status of a BpfApplication instance for the given node. // appLoadStatus and conditions provide an overall status for the given node, // while each item in the programs list provides a per eBPF program status for // the given node. + // +optional Status BpfApplicationStateStatus `json:"status,omitempty"` } @@ -160,31 +172,3 @@ type BpfApplicationStateList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []BpfApplicationState `json:"items"` } - -func (an BpfApplicationState) GetName() string { - return an.Name -} - -func (an BpfApplicationState) GetUID() metav1types.UID { - return an.UID -} - -func (an BpfApplicationState) GetAnnotations() map[string]string { - return an.Annotations -} - -func (an BpfApplicationState) GetLabels() map[string]string { - return an.Labels -} - -func (an BpfApplicationState) GetConditions() []metav1.Condition { - return an.Status.Conditions -} - -func (an BpfApplicationState) GetClientObject() client.Object { - return &an -} - -func (anl BpfApplicationStateList) GetItems() []BpfApplicationState { - return anl.Items -} diff --git a/apis/v1alpha1/bpf_application_types.go b/apis/v1alpha1/bpf_application_types.go index 29b2d8ac6..f3016ab5b 100644 --- a/apis/v1alpha1/bpf_application_types.go +++ b/apis/v1alpha1/bpf_application_types.go @@ -31,12 +31,12 @@ type BpfApplicationProgram struct { // name is a required field and is the name of the function that is the entry // point for the eBPF program. name must not be an empty string, must not // exceed 64 characters in length, must start with alpha characters and must - // only contain alphanumeric characters. + // only contain alphanumeric characters and underscores. // +required // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Name string `json:"name"` + Name string `json:"name,omitempty"` // type is a required field used to specify the type of the eBPF program. // @@ -73,7 +73,7 @@ type BpfApplicationProgram struct { // +unionDiscriminator // +required // +kubebuilder:validation:Enum:="XDP";"TC";"TCX";"UProbe";"URetProbe" - Type EBPFProgType `json:"type"` + Type EBPFProgType `json:"type,omitempty"` // xdp is an optional field, but required when the type field is set to XDP. // xdp defines the desired state of the application's XDP programs. XDP program @@ -163,7 +163,9 @@ type BpfApplicationSpec struct { // programs in the list to be reloaded, which could be temporarily service // effecting. For this reason, modifying the list is currently not allowed. // +required - // +kubebuilder:validation:MinItems:=1 + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Programs []BpfApplicationProgram `json:"programs,omitempty"` } @@ -185,11 +187,17 @@ type BpfApplicationSpec struct { // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[0].reason` // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" type BpfApplication struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // metadata is the object's metadata. + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` - Spec BpfApplicationSpec `json:"spec,omitempty"` - Status BpfAppStatus `json:"status,omitempty"` + // spec defines the desired state of the BpfApplication. + // +required + Spec BpfApplicationSpec `json:"spec,omitzero"` + // status reflects the observed state of the BpfApplication. + // +optional + Status BpfAppStatus `json:"status,omitempty"` } // +kubebuilder:object:root=true diff --git a/apis/v1alpha1/cluster_bpf_application_state_types.go b/apis/v1alpha1/cluster_bpf_application_state_types.go index 1d55fba90..87de8f7f2 100644 --- a/apis/v1alpha1/cluster_bpf_application_state_types.go +++ b/apis/v1alpha1/cluster_bpf_application_state_types.go @@ -18,8 +18,6 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - metav1types "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" ) // +union @@ -73,7 +71,7 @@ type ClBpfApplicationProgramState struct { // +unionDiscriminator // +required // +kubebuilder:validation:Enum:="FEntry";"FExit";"KProbe";"KRetProbe";"TC";"TCX";"TracePoint";"UProbe";"URetProbe";"XDP" - Type EBPFProgType `json:"type"` + Type EBPFProgType `json:"type,omitempty"` // xdp contains the attachment data for an XDP program when type is set to XDP. // +unionMember @@ -134,15 +132,32 @@ type ClBpfApplicationProgramState struct { } type ClBpfApplicationStateStatus struct { - // UpdateCount tracks the number of times the BpfApplicationState object has + // conditions contains the summary state of the ClusterBpfApplication for the + // given Kubernetes node. If one or more programs failed to load or attach to + // the designated attachment point, the condition will report the error. If + // more than one error has occurred, condition will contain the first error + // encountered. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + // +optional + // +kubebuilder:validation:MaxItems=1023 + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + // updateCount tracks the number of times the BpfApplicationState object has // been updated. The bpfman agent initializes it to 1 when it creates the // object, and then increments it before each subsequent update. It serves // as a lightweight sequence number to verify that the API server is serving // the most recent version of the object before beginning a new Reconcile // operation. - UpdateCount int64 `json:"updateCount"` + // +kubebuilder:validation:Minimum=1 + // +optional + UpdateCount int64 `json:"updateCount,omitempty"` // node is the name of the Kubernetes node for this ClusterBpfApplicationState. - Node string `json:"node"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Node string `json:"node,omitempty"` // appLoadStatus reflects the status of loading the eBPF application on the // given node. // @@ -162,22 +177,16 @@ type ClBpfApplicationStateStatus struct { // // UnloadError is returned if one or more programs encountered an error when // being unloaded. - AppLoadStatus AppLoadStatus `json:"appLoadStatus"` + // +optional + AppLoadStatus AppLoadStatus `json:"appLoadStatus,omitempty"` // programs is a list of eBPF programs contained in the parent // ClusterBpfApplication instance. Each entry in the list contains the derived // program attributes as well as the attach status for each program on the // given Kubernetes node. + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + // +optional Programs []ClBpfApplicationProgramState `json:"programs,omitempty"` - // conditions contains the summary state of the ClusterBpfApplication for the - // given Kubernetes node. If one or more programs failed to load or attach to - // the designated attachment point, the condition will report the error. If - // more than one error has occurred, condition will contain the first error - // encountered. - // +patchMergeKey=type - // +patchStrategy=merge - // +listType=map - // +listMapKey=type - Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` } // +genclient @@ -194,13 +203,16 @@ type ClBpfApplicationStateStatus struct { // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[0].reason` // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" type ClusterBpfApplicationState struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // metadata is the object's metadata. + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // status reflects the status of a ClusterBpfApplication instance for the given // node. appLoadStatus and conditions provide an overall status for the given // node, while each item in the programs list provides a per eBPF program // status for the given node. + // +optional Status ClBpfApplicationStateStatus `json:"status,omitempty"` } @@ -211,31 +223,3 @@ type ClusterBpfApplicationStateList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []ClusterBpfApplicationState `json:"items"` } - -func (an ClusterBpfApplicationState) GetName() string { - return an.Name -} - -func (an ClusterBpfApplicationState) GetUID() metav1types.UID { - return an.UID -} - -func (an ClusterBpfApplicationState) GetAnnotations() map[string]string { - return an.Annotations -} - -func (an ClusterBpfApplicationState) GetLabels() map[string]string { - return an.Labels -} - -func (an ClusterBpfApplicationState) GetConditions() []metav1.Condition { - return an.Status.Conditions -} - -func (an ClusterBpfApplicationState) GetClientObject() client.Object { - return &an -} - -func (anl ClusterBpfApplicationStateList) GetItems() []ClusterBpfApplicationState { - return anl.Items -} diff --git a/apis/v1alpha1/cluster_bpf_application_types.go b/apis/v1alpha1/cluster_bpf_application_types.go index 97b91eb40..c82062f66 100644 --- a/apis/v1alpha1/cluster_bpf_application_types.go +++ b/apis/v1alpha1/cluster_bpf_application_types.go @@ -77,12 +77,12 @@ type ClBpfApplicationProgram struct { // name is a required field and is the name of the function that is the entry // point for the eBPF program. name must not be an empty string, must not // exceed 64 characters in length, must start with alpha characters and must - // only contain alphanumeric characters. + // only contain alphanumeric characters and underscores. // +required // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Name string `json:"name"` + Name string `json:"name,omitempty"` // type is a required field used to specify the type of the eBPF program. // @@ -143,7 +143,7 @@ type ClBpfApplicationProgram struct { // +unionDiscriminator // +required // +kubebuilder:validation:Enum:="XDP";"TC";"TCX";"FEntry";"FExit";"KProbe";"KRetProbe";"UProbe";"URetProbe";"TracePoint" - Type EBPFProgType `json:"type"` + Type EBPFProgType `json:"type,omitempty"` // xdp is an optional field, but required when the type field is set to XDP. // xdp defines the desired state of the application's XDP programs. XDP program @@ -293,7 +293,9 @@ type ClBpfApplicationSpec struct { // effecting. For this reason, modifying the list is currently not allowed. // +required // +kubebuilder:validation:MinItems:=1 - Programs []ClBpfApplicationProgram `json:"programs"` + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + Programs []ClBpfApplicationProgram `json:"programs,omitempty"` } // +genclient @@ -316,11 +318,17 @@ type ClBpfApplicationSpec struct { // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[0].reason` // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" type ClusterBpfApplication struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // metadata is the standard object's metadata. + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ClBpfApplicationSpec `json:"spec,omitempty"` - Status BpfAppStatus `json:"status,omitempty"` + // spec defines the desired state of the BpfApplication. + // +required + Spec ClBpfApplicationSpec `json:"spec,omitzero"` + // status reflects the observed state of the BpfApplication. + // +optional + Status BpfAppStatus `json:"status,omitempty"` } // +kubebuilder:object:root=true diff --git a/apis/v1alpha1/cluster_fentry_program_types.go b/apis/v1alpha1/cluster_fentry_program_types.go index ceab34dbf..732e8433f 100644 --- a/apis/v1alpha1/cluster_fentry_program_types.go +++ b/apis/v1alpha1/cluster_fentry_program_types.go @@ -30,6 +30,7 @@ type ClFentryProgramInfo struct { // the program, add an entry to links with mode set to Attach. To detach it, // remove the entry from links. // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=1 Links []ClFentryAttachInfo `json:"links,omitempty"` } @@ -43,7 +44,7 @@ type ClFentryLoadInfo struct { // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Function string `json:"function"` + Function string `json:"function,omitempty"` } type AttachTypeAttach string @@ -57,7 +58,7 @@ type ClFentryAttachInfo struct { // attempt to be attached. To detach the FEntry program, remove the link entry. // +required // +kubebuilder:validation:Enum=Attach; - Mode AttachTypeAttach `json:"mode"` + Mode AttachTypeAttach `json:"mode,omitempty"` } type ClFentryProgramInfoState struct { @@ -68,6 +69,7 @@ type ClFentryProgramInfoState struct { // successful or not on this node, a linkId, which is the kernel ID for the // link if successfully attached, and other attachment specific data. // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=1 Links []ClFentryAttachInfoState `json:"links,omitempty"` } diff --git a/apis/v1alpha1/cluster_fexit_program_types.go b/apis/v1alpha1/cluster_fexit_program_types.go index a37110bc7..0cc1e20a8 100644 --- a/apis/v1alpha1/cluster_fexit_program_types.go +++ b/apis/v1alpha1/cluster_fexit_program_types.go @@ -30,6 +30,7 @@ type ClFexitProgramInfo struct { // the program, add an entry to links with mode set to Attach. To detach it, // remove the entry from links. // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=1 Links []ClFexitAttachInfo `json:"links,omitempty"` } @@ -37,13 +38,14 @@ type ClFexitProgramInfo struct { type ClFexitLoadInfo struct { // function is a required field and specifies the name of the Linux kernel // function to attach the FExit program. function must not be an empty string, - // must not exceed 64 characters in length, must start with alpha characters - // and must only contain alphanumeric characters. + // must be between 1 and 64 characters in length, must start with alpha + // characters and must only contain alphanumeric characters and underscores. + // The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. // +required // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Function string `json:"function"` + Function string `json:"function,omitempty"` } type ClFexitAttachInfo struct { @@ -51,7 +53,7 @@ type ClFexitAttachInfo struct { // attempt to be attached. To detach the FExit program, remove the link entry. // +required // +kubebuilder:validation:Enum=Attach; - Mode AttachTypeAttach `json:"mode"` + Mode AttachTypeAttach `json:"mode,omitempty"` } type ClFexitProgramInfoState struct { @@ -62,6 +64,7 @@ type ClFexitProgramInfoState struct { // successful or not, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=1 Links []ClFexitAttachInfoState `json:"links,omitempty"` } diff --git a/apis/v1alpha1/cluster_kprobe_program_types.go b/apis/v1alpha1/cluster_kprobe_program_types.go index cff43a95c..f61fd1758 100644 --- a/apis/v1alpha1/cluster_kprobe_program_types.go +++ b/apis/v1alpha1/cluster_kprobe_program_types.go @@ -31,19 +31,22 @@ type ClKprobeProgramInfo struct { // default, the eBPF program is triggered at the entry of the attachment point, // but the attachment point can be adjusted using an optional offset. // +optional + // +kubebuilder:validation:MaxItems=1 + // +listType=atomic Links []ClKprobeAttachInfo `json:"links,omitempty"` } type ClKprobeAttachInfo struct { // function is a required field and specifies the name of the Linux kernel // function to attach the KProbe program. function must not be an empty string, - // must not exceed 64 characters in length, must start with alpha characters - // and must only contain alphanumeric characters. + // must be between 1 and 64 characters in length, must start with alpha + // characters and must only contain alphanumeric characters and underscores. + // The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. // +required // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Function string `json:"function"` + Function string `json:"function,omitempty"` // offset is an optional field and the value is added to the address of the // attachment point function. If not provided, offset defaults to 0. @@ -58,16 +61,23 @@ type ClKprobeProgramInfoState struct { // successful or not on this node, a linkId, which is the kernel ID for the // link if successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClKprobeAttachInfoState `json:"links,omitempty"` } type ClKprobeAttachInfoState struct { AttachInfoStateCommon `json:",inline"` - // function is the provisioned name of the Linux kernel function the KProbe - // program should be attached. + // function is a required field and specifies the name of the Linux kernel + // function to attach the Kprobe. function must not be an empty + // string, must not exceed 64 characters in length, must start with alpha + // characters and must only contain alphanumeric characters. // +required - Function string `json:"function"` + // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + Function string `json:"function,omitempty"` // offset is the provisioned offset, whose value is added to the address of the // attachment point function. diff --git a/apis/v1alpha1/cluster_kretprobe_program_types.go b/apis/v1alpha1/cluster_kretprobe_program_types.go index 606b3c1a6..de27ca267 100644 --- a/apis/v1alpha1/cluster_kretprobe_program_types.go +++ b/apis/v1alpha1/cluster_kretprobe_program_types.go @@ -29,6 +29,8 @@ type ClKretprobeProgramInfo struct { // // The attachment point for a KRetProbe program is a Linux kernel function. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClKretprobeAttachInfo `json:"links,omitempty"` } @@ -41,7 +43,7 @@ type ClKretprobeAttachInfo struct { // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Function string `json:"function"` + Function string `json:"function,omitempty"` } type ClKretprobeProgramInfoState struct { @@ -50,13 +52,21 @@ type ClKretprobeProgramInfoState struct { // successful or not on this node, a linkId, which is the kernel ID for the // link if successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClKretprobeAttachInfoState `json:"links,omitempty"` } type ClKretprobeAttachInfoState struct { AttachInfoStateCommon `json:",inline"` - // function is the provisioned name of the Linux kernel function the KRetProbe - // program should be attached. - Function string `json:"function"` + // function is a required field and specifies the name of the Linux kernel + // function to attach the KRetProbe program. function must not be an empty + // string, must not exceed 64 characters in length, must start with alpha + // characters and must only contain alphanumeric characters. + // +required + // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + Function string `json:"function,omitempty"` } diff --git a/apis/v1alpha1/cluster_tc_program_types.go b/apis/v1alpha1/cluster_tc_program_types.go index 73978fd51..63feb048d 100644 --- a/apis/v1alpha1/cluster_tc_program_types.go +++ b/apis/v1alpha1/cluster_tc_program_types.go @@ -35,6 +35,8 @@ type ClTcProgramInfo struct { // bpfman to use the primary interface of a Kubernetes node. Optionally, the // TC program can also be installed into a set of network namespaces. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTcAttachInfo `json:"links,omitempty"` } @@ -44,7 +46,7 @@ type ClTcAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces is an optional field that identifies the set of network // namespaces in which to attach the eBPF program. If networkNamespaces is not @@ -63,7 +65,7 @@ type ClTcAttachInfo struct { // transmitted by the interface. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is an optional field and determines the execution order of the TC // program relative to other TC programs attached to the same attachment point. @@ -90,6 +92,8 @@ type ClTcAttachInfo struct { // next TC program in the chain will NOT be called. // +optional // +kubebuilder:default:={Pipe,DispatcherReturn} + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic ProceedOn []TcProceedOnValue `json:"proceedOn,omitempty"` } @@ -99,6 +103,8 @@ type ClTcProgramInfoState struct { // or not on this node, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTcAttachInfoState `json:"links,omitempty"` } @@ -108,18 +114,22 @@ type ClTcAttachInfoState struct { // interfaceName is the name of the interface the TC program should be // attached. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the optional path to the network namespace inside of which the // TC program should be attached. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 NetnsPath string `json:"netnsPath,omitempty"` // direction is the provisioned direction of traffic, Ingress or Egress, the TC // program should be attached for a given network device. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is the provisioned priority of the TC program in relation to other // programs of the same type with the same attach point. It is a value from 0 @@ -133,5 +143,7 @@ type ClTcAttachInfoState struct { // user to call other TC programs in a chain, or not call the next program in a // chain based on the exit code of a TC program .Multiple values are supported. // +required - ProceedOn []TcProceedOnValue `json:"proceedOn"` + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + ProceedOn []TcProceedOnValue `json:"proceedOn,omitempty"` } diff --git a/apis/v1alpha1/cluster_tcx_program_types.go b/apis/v1alpha1/cluster_tcx_program_types.go index 1c629cda7..084bfee63 100644 --- a/apis/v1alpha1/cluster_tcx_program_types.go +++ b/apis/v1alpha1/cluster_tcx_program_types.go @@ -33,6 +33,8 @@ type ClTcxProgramInfo struct { // bpfman to use the primary interface of a Kubernetes node. Optionally, the // TCX program can also be installed into a set of network namespaces. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTcxAttachInfo `json:"links,omitempty"` } @@ -42,7 +44,7 @@ type ClTcxAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces is an optional field that identifies the set of network // namespaces in which to attach the eBPF program. If networkNamespaces is not @@ -61,7 +63,7 @@ type ClTcxAttachInfo struct { // transmitted by the interface. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is an optional field and determines the execution order of the TCX // program relative to other TCX programs attached to the same attachment @@ -80,8 +82,11 @@ type ClTcxProgramInfoState struct { // links is a list of attachment points for the TCX program. Each entry in the // list includes a linkStatus, which indicates if the attachment was successful // or not on this node, a linkId, which is the kernel ID for the link if - // successfully attached, and other attachment specific data. + // successfully attached, and other attachment specific data. The list is + // limited to a maximum of 1023 entries. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTcxAttachInfoState `json:"links,omitempty"` } @@ -89,20 +94,25 @@ type ClTcxAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // interfaceName is the name of the interface the TCX program should be - // attached. + // attached. interfaceName must not exceed 63 characters in length. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the optional path to the network namespace inside of which the - // TCX program should be attached. + // TCX program should be attached. If not provided, the default network + // namespace is used. netnsPath must not exceed 1023 characters in length. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 NetnsPath string `json:"netnsPath,omitempty"` // direction is the provisioned direction of traffic, Ingress or Egress, the TC // program should be attached for a given network device. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is the provisioned priority of the TCX program in relation to other // programs of the same type with the same attach point. It is a value from 0 diff --git a/apis/v1alpha1/cluster_tracepoint_program_types.go b/apis/v1alpha1/cluster_tracepoint_program_types.go index 14b5e5304..f389084db 100644 --- a/apis/v1alpha1/cluster_tracepoint_program_types.go +++ b/apis/v1alpha1/cluster_tracepoint_program_types.go @@ -27,8 +27,10 @@ type ClTracepointProgramInfo struct { // the Tracepoint program to be attached or detached. // // The attachment point for a Tracepoint program is a one of a predefined set - // of Linux kernel functions. + // of Linux kernel functions. The list is limited to a maximum of 1023 entries. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTracepointAttachInfo `json:"links,omitempty"` } @@ -41,24 +43,28 @@ type ClTracepointAttachInfo struct { // +kubebuilder:validation:Pattern="^[a-zA-Z][a-zA-Z0-9_]+." // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=64 - Name string `json:"name"` + Name string `json:"name,omitempty"` } type ClTracepointProgramInfoState struct { // links is a list of attachment points for the Tracepoint program. Each entry // in the list includes a linkStatus, which indicates if the attachment was // successful or not on this node, a linkId, which is the kernel ID for the - // link if successfully attached, and other attachment specific data. + // link if successfully attached, and other attachment specific data. The list + // is limited to a maximum of 1023 entries. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClTracepointAttachInfoState `json:"links,omitempty"` } type ClTracepointAttachInfoState struct { AttachInfoStateCommon `json:",inline"` - // The name of a kernel tracepoint to attach the bpf program to. - // name is the provisioned name of the Linux kernel tracepoint function the - // Tracepoint program should be attached. + // name is the provisioned name of the Linux kernel tracepoint function to which + // the BPF program should be attached. name must not exceed 64 characters in length. // +required - Name string `json:"name"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + Name string `json:"name,omitempty"` } diff --git a/apis/v1alpha1/cluster_uprobe_program_types.go b/apis/v1alpha1/cluster_uprobe_program_types.go index 0c061f9bf..ff5de68a0 100644 --- a/apis/v1alpha1/cluster_uprobe_program_types.go +++ b/apis/v1alpha1/cluster_uprobe_program_types.go @@ -32,6 +32,8 @@ type ClUprobeProgramInfo struct { // optional function name and/or offset. Optionally, the eBPF program can be // installed in a set of containers or limited to a specified PID. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClUprobeAttachInfo `json:"links,omitempty"` } @@ -56,7 +58,9 @@ type ClUprobeAttachInfo struct { // target is a required field and is the user-space library name or the // absolute path to a binary or library. // +required - Target string `json:"target"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + Target string `json:"target,omitempty"` // pid is an optional field and if provided, limits the execution of the UProbe // or URetProbe to the provided process identification number (PID). If pid is @@ -68,7 +72,7 @@ type ClUprobeAttachInfo struct { // which to attach the UProbe or URetProbe program. If containers is not // specified, the eBPF program will be attached in the bpfman container. // +optional - Containers *ClContainerSelector `json:"containers,omitempty"` + Containers *ClContainerSelector `json:"containers,omitzero"` } type ClUprobeProgramInfoState struct { @@ -77,6 +81,8 @@ type ClUprobeProgramInfoState struct { // successful or not on this node, a linkId, which is the kernel ID for the // link if successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClUprobeAttachInfoState `json:"links,omitempty"` } @@ -86,6 +92,8 @@ type ClUprobeAttachInfoState struct { // function is the provisioned name of the user-space function the UProbe // program should be attached. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 Function string `json:"function,omitempty"` // offset is the provisioned offset, whose value is added to the address of the @@ -97,7 +105,9 @@ type ClUprobeAttachInfoState struct { // target is the provisioned user-space library name or the absolute path to a // binary or library. // +required - Target string `json:"target"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + Target string `json:"target,omitempty"` // pid is the provisioned pid. If set, pid limits the execution of the UProbe // or URetProbe to the provided process identification number (PID). If pid is @@ -105,9 +115,9 @@ type ClUprobeAttachInfoState struct { // +optional Pid *int32 `json:"pid,omitempty"` - // If containers is provisioned in the ClusterBpfApplication instance, - // containerPid is the derived PID of the container the UProbe or URetProbe this - // attachment point is attached. + // containerPid is the derived PID of the container to which this UProbe or + // URetProbe attachment point is attached. This field is populated when + // containers are provisioned in the ClusterBpfApplication instance. // +optional ContainerPid *int32 `json:"containerPid,omitempty"` } diff --git a/apis/v1alpha1/cluster_xdp_program_types.go b/apis/v1alpha1/cluster_xdp_program_types.go index 3f25e801a..0e8dcab47 100644 --- a/apis/v1alpha1/cluster_xdp_program_types.go +++ b/apis/v1alpha1/cluster_xdp_program_types.go @@ -35,6 +35,8 @@ type ClXdpProgramInfo struct { // bpfman to use the primary interface of a Kubernetes node. Optionally, the // XDP program can also be installed into a set of network namespaces. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClXdpAttachInfo `json:"links,omitempty"` } @@ -44,7 +46,7 @@ type ClXdpAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces identifies the set of network namespaces in which to // attach the eBPF program. If networkNamespaces is not specified, the eBPF @@ -76,6 +78,8 @@ type ClXdpAttachInfo struct { // next XDP program in the chain will NOT be called. // +optional // +kubebuilder:default:={Pass,DispatcherReturn} + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic ProceedOn []XdpProceedOnValue `json:"proceedOn,omitempty"` } @@ -85,6 +89,8 @@ type ClXdpProgramInfoState struct { // or not on this node, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []ClXdpAttachInfoState `json:"links,omitempty"` } @@ -92,13 +98,18 @@ type ClXdpAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // interfaceName is the name of the interface the XDP program should be - // attached. + // attached. interfaceName must not exceed 63 characters in length. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the optional path to the network namespace inside of which the - // XDP program should be attached. + // XDP program should be attached. If not provided, the default network + // namespace is used. netnsPath must not exceed 1023 characters in length. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 NetnsPath string `json:"netnsPath,omitempty"` // priority is the provisioned priority of the XDP program in relation to other @@ -113,5 +124,7 @@ type ClXdpAttachInfoState struct { // user to call other TC programs in a chain, or not call the next program in a // chain based on the exit code of a TC program .Multiple values are supported. // +required - ProceedOn []XdpProceedOnValue `json:"proceedOn"` + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + ProceedOn []XdpProceedOnValue `json:"proceedOn,omitempty"` } diff --git a/apis/v1alpha1/config_types.go b/apis/v1alpha1/config_types.go index 5db892e6e..1665badad 100644 --- a/apis/v1alpha1/config_types.go +++ b/apis/v1alpha1/config_types.go @@ -28,63 +28,89 @@ import ( // Config holds the configuration for bpfman-operator. // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Progressing",type="string",JSONPath=".status.conditions[?(@.type=='Progressing')].status" +// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.conditions[?(@.type=='Available')].status" type Config struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // metadata is the object's metadata. + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` + // spec defines the desired state of the bpfman-operator. + // +required + Spec ConfigSpec `json:"spec,omitzero"` + // status reflects the observed state of the bpfman-operator. + // +optional Status ConfigStatus `json:"status,omitempty"` } -// Spec defines the desired state of the bpfman-operator. +// spec defines the desired state of the bpfman-operator. type ConfigSpec struct { - // Agent holds the configuration for the bpfman agent. + // agent specifies the configuration for the bpfman agent DaemonSet. // +required - Agent AgentSpec `json:"agent,omitempty"` - // Configuration holds the content of bpfman.toml. + Agent AgentSpec `json:"agent,omitzero"` + // configuration specifies the content of bpfman.toml configuration file used by the bpfman DaemonSet. // +required - // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 - Configuration string `json:"configuration"` - // Image holds the image of the bpfman DaemonSets. + // +kubebuilder:validation:MaxLength=65536 + Configuration string `json:"configuration,omitempty"` + // image specifies the container image for the bpfman DaemonSet. // +required - // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 - Image string `json:"image"` - // LogLevel holds the log level for the bpfman-operator. + // +kubebuilder:validation:MaxLength=1023 + Image string `json:"image,omitempty"` + // logLevel specifies the log level for the bpfman DaemonSet via the RUST_LOG environment variable. + // The RUST_LOG environment variable controls logging with the syntax: RUST_LOG=[target][=][level][,...]. + // For further information, see https://docs.rs/env_logger/latest/env_logger/. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 LogLevel string `json:"logLevel,omitempty"` - // Namespace holds the namespace where bpfman-operator resources shall be - // deployed. + // namespace specifies the namespace where bpfman-operator resources will be deployed. + // If not specified, resources will be deployed in the default bpfman namespace. + // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=256 Namespace string `json:"namespace,omitempty"` } // AgentSpec defines the desired state of the bpfman agent. type AgentSpec struct { - // HealthProbePort holds the health probe bind port for the bpfman agent. + // healthProbePort specifies the port on which the bpfman agent's health probe endpoint will listen. + // If unspecified, the default port will be used. // +optional - // +kubebuilder:default=8175 // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=65535 - HealthProbePort int `json:"healthProbePort"` - // Image holds the image for the bpfman agent. + HealthProbePort int32 `json:"healthProbePort,omitempty"` + // image specifies the container image for the bpfman agent DaemonSet. // +required - // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 - Image string `json:"image"` - // LogLevel holds the log level for the bpfman agent. + // +kubebuilder:validation:MaxLength=1023 + Image string `json:"image,omitempty"` + // logLevel specifies the verbosity of logs produced by the bpfman agent. + // Valid values are: "info", "debug", "trace". // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=256 + // +kubebuilder:validation:Enum=info;debug;trace LogLevel string `json:"logLevel,omitempty"` } // status reflects the status of the bpfman-operator configuration. type ConfigStatus struct { - // conditions store the status conditions of the bpfman-operator. + // conditions represents the current state conditions of the bpfman-operator and its components. + // +optional // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type + // +kubebuilder:validation:MaxItems=1023 Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + + // components represents the operational status of each individual bpfman-operator component such as the deployed + // DaemonSets. + // +optional + Components map[string]ConfigComponentStatus `json:"components,omitempty"` } // +kubebuilder:object:root=true @@ -94,3 +120,15 @@ type ConfigList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []Config `json:"items"` } + +// ConfigComponentStatus holds the status of a single Config component. +type ConfigComponentStatus string + +const ( + // ConfigStatusUnknown indicates the component state cannot be determined. + ConfigStatusUnknown ConfigComponentStatus = "Unknown" + // ConfigStatusProgressing indicates the component is being updated or reconciled. + ConfigStatusProgressing ConfigComponentStatus = "Progressing" + // ConfigStatusReady indicates the component is fully operational and ready. + ConfigStatusReady ConfigComponentStatus = "Ready" +) diff --git a/apis/v1alpha1/shared_types.go b/apis/v1alpha1/shared_types.go index 3e20dc29d..e89a27132 100644 --- a/apis/v1alpha1/shared_types.go +++ b/apis/v1alpha1/shared_types.go @@ -24,6 +24,7 @@ type InterfaceDiscovery struct { // interfaceAutoDiscovery is an optional field. When enabled, the agent // monitors the creation and deletion of interfaces and automatically // attached eBPF programs to the newly discovered interfaces. + // Valid values are "Enabled", "Disabled" (default). // CAUTION: This has the potential to attach a given eBPF program to a large // number of interfaces. Use with caution. // +optional @@ -34,9 +35,14 @@ type InterfaceDiscovery struct { // names that are excluded from interface discovery. The interface names in // the list are case-sensitive. By default, the list contains the loopback // interface, "lo". This field is only taken into consideration if - // interfaceAutoDiscovery is set to true. + // interfaceAutoDiscovery is set to true. The list is limited to a maximum of + // 1023 entries, and each interface name must not exceed 63 characters in + // length. // +optional // +kubebuilder:default:={"lo"} + // +kubebuilder:validation:MaxItems=1023 + // +kubebuilder:validation:items:MaxLength=63 + // +listType=atomic ExcludeInterfaces []string `json:"excludeInterfaces,omitempty"` // allowedInterfaces is an optional field that contains a list of interface @@ -47,12 +53,17 @@ type InterfaceDiscovery struct { // `/veth*/`, then the entry is considered as a regular expression for // matching. Otherwise, the interface names in the list are case-sensitive. // This field is only taken into consideration if interfaceAutoDiscovery is set - // to true. + // to true. The list is limited to a maximum of 1023 entries, and each + // interface name must not exceed 63 characters in length. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +kubebuilder:validation:items:MaxLength=63 + // +listType=atomic AllowedInterfaces []string `json:"allowedInterfaces,omitempty"` } // InterfaceSelector describes the set of interfaces to attach a program to. +// Exactly one of interfacesDiscoveryConfig, interfaces, or primaryNodeInterface must be specified. // +kubebuilder:validation:MaxProperties=1 // +kubebuilder:validation:MinProperties=1 type InterfaceSelector struct { @@ -66,7 +77,12 @@ type InterfaceSelector struct { // interfaces is an optional field and is a list of network interface names to // attach the eBPF program. The interface names in the list are case-sensitive. + // The list is limited to a maximum of 1023 entries, and each interface name + // must not exceed 63 characters in length. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +kubebuilder:validation:items:MaxLength=63 + // +listType=atomic Interfaces []string `json:"interfaces,omitempty"` // primaryNodeInterface is and optional field and indicates to attach the eBPF @@ -80,18 +96,25 @@ type InterfaceSelector struct { type ClContainerSelector struct { // namespace is an optional field and indicates the target Kubernetes // namespace. If not provided, all Kubernetes namespaces are included. + // namespace must not exceed 253 characters in length. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 Namespace string `json:"namespace,omitempty"` // pods is a required field and indicates the target pods. To select all pods // use the standard metav1.LabelSelector semantics and make it empty. // +required - Pods metav1.LabelSelector `json:"pods"` + Pods metav1.LabelSelector `json:"pods,omitempty"` // containerNames is an optional field and is a list of container names in a // pod to attach the eBPF program. If no names are specified, all containers - // in the pod are selected. + // in the pod are selected. The list is limited to a maximum of 1023 entries, + // and each container name must not exceed 253 characters in length. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +kubebuilder:validation:items:MaxLength=253 + // +listType=atomic ContainerNames []string `json:"containerNames,omitempty"` } @@ -102,12 +125,16 @@ type ContainerSelector struct { // pods is a required field and indicates the target pods. To select all pods // use the standard metav1.LabelSelector semantics and make it empty. // +required - Pods metav1.LabelSelector `json:"pods"` + Pods metav1.LabelSelector `json:"pods,omitempty"` // containerNames is an optional field and is a list of container names in a // pod to attach the eBPF program. If no names are specified, all containers - // in the pod are selected. + // in the pod are selected. The list is limited to a maximum of 1023 entries, + // and each container name must not exceed 253 characters in length. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +kubebuilder:validation:items:MaxLength=253 + // +listType=atomic ContainerNames []string `json:"containerNames,omitempty"` } @@ -115,14 +142,17 @@ type ContainerSelector struct { // program types in the cluster-scoped ClusterBpfApplication object. type ClNetworkNamespaceSelector struct { // namespace is an optional field and indicates the target network namespace. - // If not provided, the default network namespace is used. + // If not provided, the default network namespace is used. namespace must not + // exceed 253 characters in length. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 Namespace string `json:"namespace,omitempty"` // pods is a required field and indicates the target pods. To select all pods // use the standard metav1.LabelSelector semantics and make it empty. // +required - Pods metav1.LabelSelector `json:"pods"` + Pods metav1.LabelSelector `json:"pods,omitempty"` } // NetworkNamespaceSelector identifies a network namespace for network-related @@ -131,7 +161,7 @@ type NetworkNamespaceSelector struct { // pods is a required field and indicates the target pods. To select all pods // use the standard metav1.LabelSelector semantics and make it empty. // +required - Pods metav1.LabelSelector `json:"pods"` + Pods metav1.LabelSelector `json:"pods,omitempty"` } // BpfAppCommon defines the common attributes for all BpfApp programs @@ -140,7 +170,7 @@ type BpfAppCommon struct { // Kubernetes nodes to deploy the eBPF programs. To select all nodes use // standard metav1.LabelSelector semantics and make it empty. // +required - NodeSelector metav1.LabelSelector `json:"nodeSelector"` + NodeSelector metav1.LabelSelector `json:"nodeSelector,omitempty"` // globalData is an optional field that allows the user to set global variables // when the program is loaded. This allows the same compiled bytecode to be @@ -152,11 +182,11 @@ type BpfAppCommon struct { // +optional GlobalData map[string][]byte `json:"globalData,omitempty"` - // bytecode is a required field and configures where the eBPF program's + // byteCode is a required field and configures where the eBPF program's // bytecode should be loaded from. The image must contain one or more // eBPF programs. // +required - ByteCode ByteCodeSelector `json:"byteCode"` + ByteCode ByteCodeSelector `json:"byteCode,omitzero"` // mapOwnerSelector is an optional field used to share maps across // applications. eBPF programs loaded with the same ClusterBpfApplication or @@ -177,38 +207,47 @@ type BpfAppStatus struct { // +patchStrategy=merge // +listType=map // +listMapKey=type + // +kubebuilder:validation:MaxItems=1023 + // +optional Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` } // AttachInfoStateCommon reflects the status for one attach point for a given bpf -// application program +// application program. type AttachInfoStateCommon struct { // shouldAttach reflects whether the attachment should exist. // +required ShouldAttach bool `json:"shouldAttach"` // uuid is an Unique identifier for the attach point assigned by bpfman agent. + // uuid must not exceed 64 characters in length. // +required - UUID string `json:"uuid"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + UUID string `json:"uuid,omitempty"` // linkId is an identifier for the link assigned by bpfman. This field is // empty until the program is successfully attached and bpfman returns the // id. // +optional LinkId *uint32 `json:"linkId,omitempty"` // linkStatus reflects whether the attachment has been reconciled - // successfully, and if not, why. + // successfully, and if not, why. Valid values are documented in the + // LinkStatus type definition. // +required - LinkStatus LinkStatus `json:"linkStatus"` + LinkStatus LinkStatus `json:"linkStatus,omitempty"` } type BpfProgramStateCommon struct { // name is the name of the function that is the entry point for the eBPF - // program + // program. name must not exceed 64 characters in length. // +required - Name string `json:"name"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + Name string `json:"name,omitempty"` // programLinkStatus reflects whether all links requested for the program - // are in the correct state. + // are in the correct state. Valid values are documented in the + // ProgramLinkStatus type definition. // +required - ProgramLinkStatus ProgramLinkStatus `json:"programLinkStatus"` + ProgramLinkStatus ProgramLinkStatus `json:"programLinkStatus,omitempty"` // programId is the id of the program in the kernel. Not set until the // program is loaded. // +optional @@ -229,6 +268,7 @@ const ( ) // ByteCodeSelector defines the various ways to reference BPF bytecode objects. +// Exactly one of image or path must be specified. // +kubebuilder:validation:MaxProperties=1 // +kubebuilder:validation:MinProperties=1 type ByteCodeSelector struct { @@ -238,9 +278,11 @@ type ByteCodeSelector struct { Image *ByteCodeImage `json:"image,omitempty"` // path is an optional field and used to specify a bytecode object file via - // filepath on a Kubernetes node. + // filepath on a Kubernetes node. The path must be a valid absolute path with no null bytes, + // matching the pattern ^(/[^/\0]+)+/?$. path must not exceed 1023 characters in length. // +optional // +kubebuilder:validation:Pattern=`^(/[^/\0]+)+/?$` + // +kubebuilder:validation:MaxLength=1023 Path *string `json:"path,omitempty"` } @@ -250,12 +292,12 @@ type ByteCodeImage struct { // a remote bytecode image. url must not be an empty string, must not exceed // 525 characters in length and must be a valid URL. // +required - // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength:=1 // +kubebuilder:validation:MaxLength:=525 // +kubebuilder:validation:Pattern=`[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}` - Url string `json:"url"` + Url string `json:"url,omitempty"` - // pullPolicy is an optional field that describes a policy for if/when to pull + // imagePullPolicy is an optional field that describes a policy for if/when to pull // a bytecode image. Defaults to IfNotPresent. Allowed values are: // Always, IfNotPresent and Never // @@ -280,14 +322,20 @@ type ByteCodeImage struct { // ImagePullSecretSelector defines the name and namespace of an image pull secret. type ImagePullSecretSelector struct { // name is a required field and is the name of the secret which contains the - // credentials to access the image repository. + // credentials to access the image repository. name must not exceed 253 + // characters in length. // +required - Name string `json:"name"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name,omitempty"` // namespace is a required field and is the namespace of the secret which - // contains the credentials to access the image repository. + // contains the credentials to access the image repository. namespace must not + // exceed 253 characters in length. // +required - Namespace string `json:"namespace"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Namespace string `json:"namespace,omitempty"` } // ----------------------------------------------------------------------------- @@ -460,6 +508,8 @@ func (b BpfApplicationStateConditionType) Condition() metav1.Condition { return cond } +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=1023 type AppLoadStatus string const ( @@ -479,6 +529,8 @@ const ( ProgListChangedError AppLoadStatus = "ProgramListChangedError" ) +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=1023 type ProgramLinkStatus string const ( @@ -492,6 +544,8 @@ const ( UpdateAttachInfoError ProgramLinkStatus = "UpdateAttachInfoError" ) +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=1023 type LinkStatus string const ( diff --git a/apis/v1alpha1/tc_program_types.go b/apis/v1alpha1/tc_program_types.go index efe56e3d4..87c15a8dd 100644 --- a/apis/v1alpha1/tc_program_types.go +++ b/apis/v1alpha1/tc_program_types.go @@ -32,6 +32,8 @@ type TcProgramInfo struct { // bpfman to use the primary interface of a Kubernetes node. Optionally, the // TC program can also be installed into a set of network namespaces. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []TcAttachInfo `json:"links,omitempty"` } @@ -41,12 +43,12 @@ type TcAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces is a required field that identifies the set of network // namespaces in which to attach the eBPF program. // +required - NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces"` + NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces,omitzero"` // direction is a required field and specifies the direction of traffic. // Allowed values are: @@ -59,7 +61,7 @@ type TcAttachInfo struct { // transmitted by the interface. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is an optional field and determines the execution order of the TC // program relative to other TC programs attached to the same attachment point. @@ -86,6 +88,8 @@ type TcAttachInfo struct { // next TC program in the chain will NOT be called. // +optional // +kubebuilder:default:={Pipe,DispatcherReturn} + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic ProceedOn []TcProceedOnValue `json:"proceedOn,omitempty"` } @@ -95,6 +99,8 @@ type TcProgramInfoState struct { // or not on this node, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []TcAttachInfoState `json:"links,omitempty"` } @@ -102,20 +108,25 @@ type TcAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // interfaceName is the name of the interface the TC program should be - // attached. + // attached. interfaceName must not exceed 63 characters in length. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the path to the network namespace inside of which the TC - // program should be attached. + // program should be attached. netnsPath must not exceed 1023 characters in + // length. // +required - NetnsPath string `json:"netnsPath"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + NetnsPath string `json:"netnsPath,omitempty"` // direction is the provisioned direction of traffic, Ingress or Egress, the TC // program should be attached for a given network device. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is the provisioned priority of the TC program in relation to other // programs of the same type with the same attach point. It is a value from 0 @@ -129,5 +140,7 @@ type TcAttachInfoState struct { // user to call other TC programs in a chain, or not call the next program in a // chain based on the exit code of a TC program .Multiple values are supported. // +required - ProceedOn []TcProceedOnValue `json:"proceedOn"` + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + ProceedOn []TcProceedOnValue `json:"proceedOn,omitempty"` } diff --git a/apis/v1alpha1/tcx_program_types.go b/apis/v1alpha1/tcx_program_types.go index 9c0b54729..a1609868d 100644 --- a/apis/v1alpha1/tcx_program_types.go +++ b/apis/v1alpha1/tcx_program_types.go @@ -33,6 +33,8 @@ type TcxProgramInfo struct { // bpfman to use the primary interface of a Kubernetes node. Optionally, the // TCX program can also be installed into a set of network namespaces. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []TcxAttachInfo `json:"links,omitempty"` } @@ -42,12 +44,12 @@ type TcxAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces is a required field that identifies the set of network // namespaces in which to attach the eBPF program. // +required - NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces"` + NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces,omitzero"` // direction is a required field and specifies the direction of traffic. // Allowed values are: @@ -60,7 +62,7 @@ type TcxAttachInfo struct { // transmitted by the interface. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is an optional field and determines the execution order of the TCX // program relative to other TCX programs attached to the same attachment @@ -81,6 +83,8 @@ type TcxProgramInfoState struct { // or not on this node, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []TcxAttachInfoState `json:"links,omitempty"` } @@ -88,20 +92,25 @@ type TcxAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // interfaceName is the name of the interface the TCX program should be - // attached. + // attached. interfaceName must not exceed 63 characters in length. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the path to the network namespace inside of which the TCX - // program should be attached. + // program should be attached. netnsPath must not exceed 1023 characters in + // length. // +required - NetnsPath string `json:"netnsPath"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + NetnsPath string `json:"netnsPath,omitempty"` // direction is the provisioned direction of traffic, Ingress or Egress, the // TCX program should be attached for a given network device. // +required // +kubebuilder:validation:Enum=Ingress;Egress - Direction TCDirectionType `json:"direction"` + Direction TCDirectionType `json:"direction,omitempty"` // priority is the provisioned priority of the TCX program in relation to other // programs of the same type with the same attach point. It is a value from 0 diff --git a/apis/v1alpha1/uprobe_program_types.go b/apis/v1alpha1/uprobe_program_types.go index 9176a4520..01b000fae 100644 --- a/apis/v1alpha1/uprobe_program_types.go +++ b/apis/v1alpha1/uprobe_program_types.go @@ -32,6 +32,8 @@ type UprobeProgramInfo struct { // optional function name and/or offset. Optionally, the eBPF program can be // installed in a set of containers or limited to a specified PID. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []UprobeAttachInfo `json:"links,omitempty"` } @@ -54,9 +56,12 @@ type UprobeAttachInfo struct { Offset uint64 `json:"offset"` // target is a required field and is the user-space library name or the - // absolute path to a binary or library. + // absolute path to a binary or library. target must not exceed 1023 characters + // in length. // +required - Target string `json:"target"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + Target string `json:"target,omitempty"` // pid is an optional field and if provided, limits the execution of the UProbe // or URetProbe to the provided process identification number (PID). If pid is @@ -68,7 +73,8 @@ type UprobeAttachInfo struct { // which to attach the UProbe or URetProbe program. If containers is not // specified, the eBPF program will be attached in the bpfman container. // uprobe. - Containers ContainerSelector `json:"containers"` + // +optional + Containers ContainerSelector `json:"containers,omitempty"` } type UprobeProgramInfoState struct { @@ -77,6 +83,8 @@ type UprobeProgramInfoState struct { // successful or not on this node, a linkId, which is the kernel ID for the // link if successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []UprobeAttachInfoState `json:"links,omitempty"` } @@ -84,8 +92,10 @@ type UprobeAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // function is the provisioned name of the user-space function the UProbe - // program should be attached. + // program should be attached. function must not exceed 64 characters in length. // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 Function string `json:"function,omitempty"` // offset is the provisioned offset, whose value is added to the address of the @@ -95,9 +105,11 @@ type UprobeAttachInfoState struct { Offset uint64 `json:"offset"` // target is the provisioned user-space library name or the absolute path to a - // binary or library. + // binary or library. target must not exceed 1023 characters in length. // +required - Target string `json:"target"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + Target string `json:"target,omitempty"` // pid is the provisioned pid. If set, pid limits the execution of the UProbe // or URetProbe to the provided process identification number (PID). If pid is @@ -105,9 +117,11 @@ type UprobeAttachInfoState struct { // +optional Pid *int32 `json:"pid,omitempty"` - // If containers is provisioned in the BpfApplication instance, containerPid is - // the derived PID of the container the UProbe or URetProbe this attachment - // point is attached. + // containerPid is the derived PID of the container the UProbe or URetProbe + // this attachment point is attached to, if containers is provisioned in the + // BpfApplication instance. // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=2147483647 ContainerPid int32 `json:"containerPid,omitempty"` } diff --git a/apis/v1alpha1/xdp_program_types.go b/apis/v1alpha1/xdp_program_types.go index 872c053ff..e3d58ad3e 100644 --- a/apis/v1alpha1/xdp_program_types.go +++ b/apis/v1alpha1/xdp_program_types.go @@ -31,6 +31,8 @@ type XdpProgramInfo struct { // interface, or by setting the primaryNodeInterface flag, which instructs // bpfman to use the primary interface of a Kubernetes node. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []XdpAttachInfo `json:"links,omitempty"` } @@ -40,12 +42,12 @@ type XdpAttachInfo struct { // by providing a list of interface names, enabling auto discovery, or setting // the primaryNodeInterface flag, but only one option is allowed. // +required - InterfaceSelector InterfaceSelector `json:"interfaceSelector"` + InterfaceSelector InterfaceSelector `json:"interfaceSelector,omitzero"` // networkNamespaces is a required field that identifies the set of network // namespaces in which to attach the eBPF program. // +required - NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces"` + NetworkNamespaces NetworkNamespaceSelector `json:"networkNamespaces,omitzero"` // priority is an optional field and determines the execution order of the XDP // program relative to other XDP programs attached to the same attachment @@ -71,6 +73,8 @@ type XdpAttachInfo struct { // next XDP program in the chain will NOT be called. // +optional // +kubebuilder:default:={Pass,DispatcherReturn} + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic ProceedOn []XdpProceedOnValue `json:"proceedOn,omitempty"` } @@ -80,6 +84,8 @@ type XdpProgramInfoState struct { // or not on this node, a linkId, which is the kernel ID for the link if // successfully attached, and other attachment specific data. // +optional + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic Links []XdpAttachInfoState `json:"links,omitempty"` } @@ -87,14 +93,19 @@ type XdpAttachInfoState struct { AttachInfoStateCommon `json:",inline"` // interfaceName is the name of the interface the XDP program should be - // attached. + // attached. interfaceName must not exceed 63 characters in length. // +required - InterfaceName string `json:"interfaceName"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + InterfaceName string `json:"interfaceName,omitempty"` // netnsPath is the path to the network namespace inside of which the XDP - // program should be attached. + // program should be attached. netnsPath must not exceed 1023 characters in + // length. // +required - NetnsPath string `json:"netnsPath"` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1023 + NetnsPath string `json:"netnsPath,omitempty"` // priority is the provisioned priority of the XDP program in relation to other // programs of the same type with the same attach point. It is a value from 0 @@ -108,5 +119,7 @@ type XdpAttachInfoState struct { // user to call other TC programs in a chain, or not call the next program in a // chain based on the exit code of a TC program .Multiple values are supported. // +required - ProceedOn []XdpProceedOnValue `json:"proceedOn"` + // +kubebuilder:validation:MaxItems=1023 + // +listType=atomic + ProceedOn []XdpProceedOnValue `json:"proceedOn,omitempty"` } diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 454bbc333..112ce723d 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -344,16 +344,16 @@ func (in *BpfApplicationStateList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BpfApplicationStateStatus) DeepCopyInto(out *BpfApplicationStateStatus) { *out = *in - if in.Programs != nil { - in, out := &in.Programs, &out.Programs - *out = make([]BpfApplicationProgramState, len(*in)) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + if in.Programs != nil { + in, out := &in.Programs, &out.Programs + *out = make([]BpfApplicationProgramState, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -592,16 +592,16 @@ func (in *ClBpfApplicationSpec) DeepCopy() *ClBpfApplicationSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClBpfApplicationStateStatus) DeepCopyInto(out *ClBpfApplicationStateStatus) { *out = *in - if in.Programs != nil { - in, out := &in.Programs, &out.Programs - *out = make([]ClBpfApplicationProgramState, len(*in)) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + if in.Programs != nil { + in, out := &in.Programs, &out.Programs + *out = make([]ClBpfApplicationProgramState, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -1614,6 +1614,13 @@ func (in *ConfigStatus) DeepCopyInto(out *ConfigStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(map[string]ConfigComponentStatus, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigStatus. diff --git a/bundle/manifests/bpfman-operator.clusterserviceversion.yaml b/bundle/manifests/bpfman-operator.clusterserviceversion.yaml index 0a7f0c16f..efe0b9bee 100644 --- a/bundle/manifests/bpfman-operator.clusterserviceversion.yaml +++ b/bundle/manifests/bpfman-operator.clusterserviceversion.yaml @@ -1012,7 +1012,7 @@ metadata: capabilities: Basic Install categories: OpenShift Optional containerImage: quay.io/bpfman/bpfman-operator:latest - createdAt: "2025-09-26T11:09:36Z" + createdAt: "2025-10-21T15:42:33Z" description: The bpfman Operator is designed to manage eBPF programs for applications. features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" @@ -1502,6 +1502,14 @@ spec: - configs/finalizers verbs: - update + - apiGroups: + - bpfman.io + resources: + - configs/status + verbs: + - get + - patch + - update - apiGroups: - "" resources: @@ -1514,6 +1522,13 @@ spec: - patch - update - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - "" resources: diff --git a/bundle/manifests/bpfman.io_bpfapplications.yaml b/bundle/manifests/bpfman.io_bpfapplications.yaml index 6776fdb82..f383e8ed6 100644 --- a/bundle/manifests/bpfman.io_bpfapplications.yaml +++ b/bundle/manifests/bpfman.io_bpfapplications.yaml @@ -57,17 +57,11 @@ spec: metadata: type: object spec: - description: |- - spec defines the desired state of the BpfApplication. The BpfApplication - describes the set of one or more namespace scoped eBPF programs that should - be loaded for a given application and attributes for how they should be - loaded. eBPF programs that are grouped together under the same - BpfApplication instance can share maps and global data between the eBPF - programs loaded on the same Kubernetes Node. + description: spec defines the desired state of the BpfApplication. properties: byteCode: description: |- - bytecode is a required field and configures where the eBPF program's + byteCode is a required field and configures where the eBPF program's bytecode should be loaded from. The image must contain one or more eBPF programs. maxProperties: 1 @@ -81,7 +75,7 @@ spec: imagePullPolicy: default: IfNotPresent description: |- - pullPolicy is an optional field that describes a policy for if/when to pull + imagePullPolicy is an optional field that describes a policy for if/when to pull a bytecode image. Defaults to IfNotPresent. Allowed values are: Always, IfNotPresent and Never @@ -109,16 +103,19 @@ spec: name: description: |- name is a required field and is the name of the secret which contains the - credentials to access the image repository. + credentials to access the image repository. name must not exceed 253 + characters in length. + maxLength: 253 + minLength: 1 type: string namespace: description: |- namespace is a required field and is the namespace of the secret which - contains the credentials to access the image repository. + contains the credentials to access the image repository. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string - required: - - name - - namespace type: object url: description: |- @@ -126,15 +123,16 @@ spec: a remote bytecode image. url must not be an empty string, must not exceed 525 characters in length and must be a valid URL. maxLength: 525 + minLength: 1 pattern: '[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}' type: string - required: - - url type: object path: description: |- path is an optional field and used to specify a bytecode object file via - filepath on a Kubernetes node. + filepath on a Kubernetes node. The path must be a valid absolute path with no null bytes, + matching the pattern ^(/[^/\0]+)+/?$. path must not exceed 1023 characters in length. + maxLength: 1023 pattern: ^(/[^/\0]+)+/?$ type: string type: object @@ -274,7 +272,7 @@ spec: name is a required field and is the name of the function that is the entry point for the eBPF program. name must not be an empty string, must not exceed 64 characters in length, must start with alpha characters and must - only contain alphanumeric characters. + only contain alphanumeric characters and underscores. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -340,9 +338,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -361,10 +364,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -373,16 +380,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -448,8 +461,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -495,13 +506,16 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - - direction - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: |- @@ -564,9 +578,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -585,10 +604,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -597,16 +620,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -672,8 +701,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -689,11 +716,12 @@ spec: minimum: 0 type: integer required: - - direction - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -783,10 +811,14 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic pods: description: |- pods is a required field and indicates the target pods. To select all pods @@ -836,8 +868,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -867,13 +897,15 @@ spec: target: description: |- target is a required field and is the user-space library name or the - absolute path to a binary or library. + absolute path to a binary or library. target must not exceed 1023 characters + in length. + maxLength: 1023 + minLength: 1 type: string - required: - - containers - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -917,10 +949,14 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic pods: description: |- pods is a required field and indicates the target pods. To select all pods @@ -970,8 +1006,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1001,13 +1035,15 @@ spec: target: description: |- target is a required field and is the user-space library name or the - absolute path to a binary or library. + absolute path to a binary or library. target must not exceed 1023 characters + in length. + maxLength: 1023 + minLength: 1 type: string - required: - - containers - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: |- @@ -1049,9 +1085,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -1070,10 +1111,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -1082,16 +1127,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -1157,8 +1208,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -1198,16 +1247,17 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -1230,16 +1280,15 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''URetProbe'' ? has(self.uretprobe) : !has(self.uretprobe)' + maxItems: 1023 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - byteCode - - nodeSelector type: object status: - description: |- - status reflects the status of a BPF Application and indicates if all the - eBPF programs for a given instance loaded successfully or not. + description: status reflects the observed state of the BpfApplication. properties: conditions: description: |- @@ -1312,11 +1361,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/bundle/manifests/bpfman.io_bpfapplicationstates.yaml b/bundle/manifests/bpfman.io_bpfapplicationstates.yaml index 4423ddd49..dac9f540f 100644 --- a/bundle/manifests/bpfman.io_bpfapplicationstates.yaml +++ b/bundle/manifests/bpfman.io_bpfapplicationstates.yaml @@ -86,6 +86,8 @@ spec: UnloadError is returned if one or more programs encountered an error when being unloaded. + maxLength: 1023 + minLength: 1 type: string conditions: description: |- @@ -161,12 +163,15 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map node: - description: node is the name of the Kubernets node for this BpfApplicationState. + description: node is the name of the Kubernetes node for this BpfApplicationState. + maxLength: 253 + minLength: 1 type: string programs: description: |- @@ -178,7 +183,9 @@ spec: name: description: |- name is the name of the function that is the entry point for the eBPF - program + program. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string programId: description: |- @@ -189,7 +196,10 @@ spec: programLinkStatus: description: |- programLinkStatus reflects whether all links requested for the program - are in the correct state. + are in the correct state. Valid values are documented in the + ProgramLinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string tc: description: tc contains the attachment data for a TC program @@ -214,7 +224,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TC program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -226,12 +238,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the TC - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -261,26 +279,27 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - - netnsPath - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: tcx contains the attachment data for a TCX program @@ -305,7 +324,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TCX program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -317,12 +338,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the TCX - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -338,19 +365,19 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - - netnsPath - priority - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -399,15 +426,19 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the BpfApplication instance, containerPid is - the derived PID of the container the UProbe or URetProbe this attachment - point is attached. + containerPid is the derived PID of the container the UProbe or URetProbe + this attachment point is attached to, if containers is provisioned in the + BpfApplication instance. format: int32 + maximum: 2147483647 + minimum: 1 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe - program should be attached. + program should be attached. function must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string linkId: description: |- @@ -419,7 +450,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -442,19 +476,23 @@ spec: target: description: |- target is the provisioned user-space library name or the absolute path to a - binary or library. + binary or library. target must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -471,15 +509,19 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the BpfApplication instance, containerPid is - the derived PID of the container the UProbe or URetProbe this attachment - point is attached. + containerPid is the derived PID of the container the UProbe or URetProbe + this attachment point is attached to, if containers is provisioned in the + BpfApplication instance. format: int32 + maximum: 2147483647 + minimum: 1 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe - program should be attached. + program should be attached. function must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string linkId: description: |- @@ -491,7 +533,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -514,19 +559,23 @@ spec: target: description: |- target is the provisioned user-space library name or the absolute path to a - binary or library. + binary or library. target must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: xdp contains the attachment data for an XDP program @@ -543,7 +592,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the XDP program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -555,12 +606,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the XDP - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -585,30 +642,28 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - interfaceName - - linkStatus - - netnsPath - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - programLinkStatus - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -631,21 +686,20 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''URetProbe'' ? has(self.uretprobe) : !has(self.uretprobe)' + maxItems: 1023 type: array + x-kubernetes-list-type: atomic updateCount: description: |- - UpdateCount tracks the number of times the BpfApplicationState object has + updateCount tracks the number of times the BpfApplicationState object has been updated. The bpfman agent initializes it to 1 when it creates the object, and then increments it before each subsequent update. It serves as a lightweight sequence number to verify that the API server is serving the most recent version of the object before beginning a new Reconcile operation. format: int64 + minimum: 1 type: integer - required: - - appLoadStatus - - node - - updateCount type: object type: object served: true diff --git a/bundle/manifests/bpfman.io_clusterbpfapplications.yaml b/bundle/manifests/bpfman.io_clusterbpfapplications.yaml index 10bf4705e..fcdbc054b 100644 --- a/bundle/manifests/bpfman.io_clusterbpfapplications.yaml +++ b/bundle/manifests/bpfman.io_clusterbpfapplications.yaml @@ -58,17 +58,11 @@ spec: metadata: type: object spec: - description: |- - spec defines the desired state of the ClusterBpfApplication. The - ClusterBpfApplication describes the set of one or more cluster scoped eBPF - programs that should be loaded for a given application and attributes for - how they should be loaded. eBPF programs that are grouped together under the - same ClusterBpfApplication instance can share maps and global data between - the eBPF programs loaded on the same Kubernetes Node. + description: spec defines the desired state of the BpfApplication. properties: byteCode: description: |- - bytecode is a required field and configures where the eBPF program's + byteCode is a required field and configures where the eBPF program's bytecode should be loaded from. The image must contain one or more eBPF programs. maxProperties: 1 @@ -82,7 +76,7 @@ spec: imagePullPolicy: default: IfNotPresent description: |- - pullPolicy is an optional field that describes a policy for if/when to pull + imagePullPolicy is an optional field that describes a policy for if/when to pull a bytecode image. Defaults to IfNotPresent. Allowed values are: Always, IfNotPresent and Never @@ -110,16 +104,19 @@ spec: name: description: |- name is a required field and is the name of the secret which contains the - credentials to access the image repository. + credentials to access the image repository. name must not exceed 253 + characters in length. + maxLength: 253 + minLength: 1 type: string namespace: description: |- namespace is a required field and is the namespace of the secret which - contains the credentials to access the image repository. + contains the credentials to access the image repository. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string - required: - - name - - namespace type: object url: description: |- @@ -127,15 +124,16 @@ spec: a remote bytecode image. url must not be an empty string, must not exceed 525 characters in length and must be a valid URL. maxLength: 525 + minLength: 1 pattern: '[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}' type: string - required: - - url type: object path: description: |- path is an optional field and used to specify a bytecode object file via - filepath on a Kubernetes node. + filepath on a Kubernetes node. The path must be a valid absolute path with no null bytes, + matching the pattern ^(/[^/\0]+)+/?$. path must not exceed 1023 characters in length. + maxLength: 1023 pattern: ^(/[^/\0]+)+/?$ type: string type: object @@ -307,13 +305,10 @@ spec: enum: - Attach type: string - required: - - mode type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object fexit: description: |- @@ -330,8 +325,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the FExit program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -356,13 +352,10 @@ spec: enum: - Attach type: string - required: - - mode type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object kprobe: description: |- @@ -395,8 +388,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the KProbe program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -408,10 +402,10 @@ spec: attachment point function. If not provided, offset defaults to 0. format: int64 type: integer - required: - - function type: object + maxItems: 1 type: array + x-kubernetes-list-type: atomic type: object kretprobe: description: |- @@ -446,17 +440,17 @@ spec: minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string - required: - - function type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object name: description: |- name is a required field and is the name of the function that is the entry point for the eBPF program. name must not be an empty string, must not exceed 64 characters in length, must start with alpha characters and must - only contain alphanumeric characters. + only contain alphanumeric characters and underscores. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -522,9 +516,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -543,10 +542,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -555,16 +558,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -585,7 +594,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -636,8 +648,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -683,12 +693,15 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - - direction - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: |- @@ -751,9 +764,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -772,10 +790,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -784,16 +806,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -814,7 +842,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -865,8 +896,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -882,10 +911,11 @@ spec: minimum: 0 type: integer required: - - direction - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tracepoint: description: |- @@ -913,7 +943,7 @@ spec: The attachment point for a Tracepoint program is a one of a predefined set - of Linux kernel functions. + of Linux kernel functions. The list is limited to a maximum of 1023 entries. items: properties: name: @@ -926,10 +956,10 @@ spec: minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string - required: - - name type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -1052,14 +1082,21 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic namespace: description: |- namespace is an optional field and indicates the target Kubernetes namespace. If not provided, all Kubernetes namespaces are included. + namespace must not exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1110,8 +1147,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1142,11 +1177,13 @@ spec: description: |- target is a required field and is the user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string - required: - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -1189,14 +1226,21 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic namespace: description: |- namespace is an optional field and indicates the target Kubernetes namespace. If not provided, all Kubernetes namespaces are included. + namespace must not exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1247,8 +1291,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1279,11 +1321,13 @@ spec: description: |- target is a required field and is the user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string - required: - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: |- @@ -1326,9 +1370,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -1347,10 +1396,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -1359,16 +1412,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -1389,7 +1448,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1440,8 +1502,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -1481,15 +1541,16 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -1532,17 +1593,15 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''TracePoint'' ? has(self.tracepoint) : !has(self.tracepoint)' + maxItems: 1023 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - byteCode - - nodeSelector - - programs type: object status: - description: |- - status reflects the status of a BPF Application and indicates if all the - eBPF programs for a given instance loaded successfully or not. + description: status reflects the observed state of the BpfApplication. properties: conditions: description: |- @@ -1615,11 +1674,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/bundle/manifests/bpfman.io_clusterbpfapplicationstates.yaml b/bundle/manifests/bpfman.io_clusterbpfapplicationstates.yaml index 5ee01d9da..8c69a3c3b 100644 --- a/bundle/manifests/bpfman.io_clusterbpfapplicationstates.yaml +++ b/bundle/manifests/bpfman.io_clusterbpfapplicationstates.yaml @@ -84,6 +84,8 @@ spec: UnloadError is returned if one or more programs encountered an error when being unloaded. + maxLength: 1023 + minLength: 1 type: string conditions: description: |- @@ -159,12 +161,15 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map node: description: node is the name of the Kubernetes node for this ClusterBpfApplicationState. + maxLength: 253 + minLength: 1 type: string programs: description: |- @@ -207,25 +212,28 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - uuid type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object fexit: description: |- @@ -236,8 +244,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the FExit program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -260,25 +269,28 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - uuid type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object kprobe: description: |- @@ -295,8 +307,13 @@ spec: properties: function: description: |- - function is the provisioned name of the Linux kernel function the KProbe - program should be attached. + function is a required field and specifies the name of the Linux kernel + function to attach the Kprobe. function must not be an empty + string, must not exceed 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters. + maxLength: 64 + minLength: 1 + pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string linkId: description: |- @@ -308,7 +325,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -322,16 +342,18 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - function - - linkStatus - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object kretprobe: description: |- @@ -348,8 +370,13 @@ spec: properties: function: description: |- - function is the provisioned name of the Linux kernel function the KRetProbe - program should be attached. + function is a required field and specifies the name of the Linux kernel + function to attach the KRetProbe program. function must not be an empty + string, must not exceed 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters. + maxLength: 64 + minLength: 1 + pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string linkId: description: |- @@ -361,28 +388,35 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - function - - linkStatus - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object name: description: |- name is the name of the function that is the entry point for the eBPF - program + program. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string programId: description: |- @@ -393,7 +427,10 @@ spec: programLinkStatus: description: |- programLinkStatus reflects whether all links requested for the program - are in the correct state. + are in the correct state. Valid values are documented in the + ProgramLinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string tc: description: tc contains the attachment data for a TC program @@ -419,6 +456,8 @@ spec: description: |- interfaceName is the name of the interface the TC program should be attached. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -430,12 +469,17 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the TC program should be attached. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -465,25 +509,27 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: tcx contains the attachment data for a TCX program @@ -494,7 +540,8 @@ spec: links is a list of attachment points for the TCX program. Each entry in the list includes a linkStatus, which indicates if the attachment was successful or not on this node, a linkId, which is the kernel ID for the link if - successfully attached, and other attachment specific data. + successfully attached, and other attachment specific data. The list is + limited to a maximum of 1023 entries. items: properties: direction: @@ -508,7 +555,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TCX program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -520,12 +569,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the - TCX program should be attached. + TCX program should be attached. If not provided, the default network + namespace is used. netnsPath must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -541,18 +596,19 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - priority - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tracepoint: description: |- @@ -564,7 +620,8 @@ spec: links is a list of attachment points for the Tracepoint program. Each entry in the list includes a linkStatus, which indicates if the attachment was successful or not on this node, a linkId, which is the kernel ID for the - link if successfully attached, and other attachment specific data. + link if successfully attached, and other attachment specific data. The list + is limited to a maximum of 1023 entries. items: properties: linkId: @@ -577,29 +634,35 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string name: description: |- - The name of a kernel tracepoint to attach the bpf program to. - name is the provisioned name of the Linux kernel tracepoint function the - Tracepoint program should be attached. + name is the provisioned name of the Linux kernel tracepoint function to which + the BPF program should be attached. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - - name - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -674,15 +737,17 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the ClusterBpfApplication instance, - containerPid is the derived PID of the container the UProbe or URetProbe this - attachment point is attached. + containerPid is the derived PID of the container to which this UProbe or + URetProbe attachment point is attached. This field is populated when + containers are provisioned in the ClusterBpfApplication instance. format: int32 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe program should be attached. + maxLength: 1023 + minLength: 1 type: string linkId: description: |- @@ -694,7 +759,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -718,18 +786,22 @@ spec: description: |- target is the provisioned user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -746,15 +818,17 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the ClusterBpfApplication instance, - containerPid is the derived PID of the container the UProbe or URetProbe this - attachment point is attached. + containerPid is the derived PID of the container to which this UProbe or + URetProbe attachment point is attached. This field is populated when + containers are provisioned in the ClusterBpfApplication instance. format: int32 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe program should be attached. + maxLength: 1023 + minLength: 1 type: string linkId: description: |- @@ -766,7 +840,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -790,18 +867,22 @@ spec: description: |- target is the provisioned user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: xdp contains the attachment data for an XDP program @@ -818,7 +899,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the XDP program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -830,12 +913,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the - XDP program should be attached. + XDP program should be attached. If not provided, the default network + namespace is used. netnsPath must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -860,29 +949,28 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - interfaceName - - linkStatus - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - programLinkStatus - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -925,21 +1013,20 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''TracePoint'' ? has(self.tracepoint) : !has(self.tracepoint)' + maxItems: 1023 type: array + x-kubernetes-list-type: atomic updateCount: description: |- - UpdateCount tracks the number of times the BpfApplicationState object has + updateCount tracks the number of times the BpfApplicationState object has been updated. The bpfman agent initializes it to 1 when it creates the object, and then increments it before each subsequent update. It serves as a lightweight sequence number to verify that the API server is serving the most recent version of the object before beginning a new Reconcile operation. format: int64 + minimum: 1 type: integer - required: - - appLoadStatus - - node - - updateCount type: object type: object served: true diff --git a/bundle/manifests/bpfman.io_configs.yaml b/bundle/manifests/bpfman.io_configs.yaml index ac0c836a8..c2af3bd42 100644 --- a/bundle/manifests/bpfman.io_configs.yaml +++ b/bundle/manifests/bpfman.io_configs.yaml @@ -18,6 +18,12 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + - jsonPath: .status.conditions[?(@.type=='Progressing')].status + name: Progressing + type: string + - jsonPath: .status.conditions[?(@.type=='Available')].status + name: Available + type: string name: v1alpha1 schema: openAPIV3Schema: @@ -41,53 +47,82 @@ spec: metadata: type: object spec: - description: Spec defines the desired state of the bpfman-operator. + description: spec defines the desired state of the bpfman-operator. properties: agent: - description: Agent holds the configuration for the bpfman agent. + description: agent specifies the configuration for the bpfman agent + DaemonSet. properties: healthProbePort: - default: 8175 - description: HealthProbePort holds the health probe bind port - for the bpfman agent. + description: |- + healthProbePort specifies the port on which the bpfman agent's health probe endpoint will listen. + If unspecified, the default port will be used. + format: int32 maximum: 65535 minimum: 1 type: integer image: - description: Image holds the image for the bpfman agent. + description: image specifies the container image for the bpfman + agent DaemonSet. + maxLength: 1023 minLength: 1 type: string logLevel: - description: LogLevel holds the log level for the bpfman agent. + description: |- + logLevel specifies the verbosity of logs produced by the bpfman agent. + Valid values are: "info", "debug", "trace". + enum: + - info + - debug + - trace + maxLength: 256 + minLength: 1 type: string - required: - - image type: object configuration: - description: Configuration holds the content of bpfman.toml. + description: configuration specifies the content of bpfman.toml configuration + file used by the bpfman DaemonSet. + maxLength: 65536 minLength: 1 type: string image: - description: Image holds the image of the bpfman DaemonSets. + description: image specifies the container image for the bpfman DaemonSet. + maxLength: 1023 minLength: 1 type: string logLevel: - description: LogLevel holds the log level for the bpfman-operator. + description: |- + logLevel specifies the log level for the bpfman DaemonSet via the RUST_LOG environment variable. + The RUST_LOG environment variable controls logging with the syntax: RUST_LOG=[target][=][level][,...]. + For further information, see https://docs.rs/env_logger/latest/env_logger/. + maxLength: 1024 + minLength: 1 type: string namespace: description: |- - Namespace holds the namespace where bpfman-operator resources shall be - deployed. + namespace specifies the namespace where bpfman-operator resources will be deployed. + If not specified, resources will be deployed in the default bpfman namespace. + maxLength: 256 + minLength: 1 type: string required: - - configuration - - image + - agent type: object status: - description: status reflects the status of the bpfman-operator configuration. + description: status reflects the observed state of the bpfman-operator. properties: + components: + additionalProperties: + description: ConfigComponentStatus holds the status of a single + Config component. + type: string + description: |- + components represents the operational status of each individual bpfman-operator component such as the deployed + DaemonSets. + type: object conditions: - description: conditions store the status conditions of the bpfman-operator. + description: conditions represents the current state conditions of + the bpfman-operator and its components. items: description: "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for @@ -155,11 +190,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/cmd/bpfman-operator/main.go b/cmd/bpfman-operator/main.go index 5d79a9046..df3e267b0 100644 --- a/cmd/bpfman-operator/main.go +++ b/cmd/bpfman-operator/main.go @@ -162,7 +162,7 @@ func main() { } } - commonApp := bpfmanoperator.ReconcilerCommon[bpfmaniov1alpha1.ClusterBpfApplicationState, bpfmaniov1alpha1.ClusterBpfApplicationStateList]{ + commonApp := bpfmanoperator.ReconcilerCommon{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), } @@ -171,7 +171,7 @@ func main() { ReconcilerCommon: commonApp, } - commonNsApp := bpfmanoperator.ReconcilerCommon[bpfmaniov1alpha1.BpfApplicationState, bpfmaniov1alpha1.BpfApplicationStateList]{ + commonNsApp := bpfmanoperator.ReconcilerCommon{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), } @@ -201,6 +201,7 @@ func main() { CsiDriverDS: internal.BpfmanCsiDriverPath, RestrictedSCC: internal.BpfmanRestrictedSCCPath, IsOpenshift: isOpenshift, + Recorder: mgr.GetEventRecorderFor("config-controller"), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create bpfmanConfig controller") os.Exit(1) diff --git a/config/crd/bases/bpfman.io_bpfapplications.yaml b/config/crd/bases/bpfman.io_bpfapplications.yaml index 598b86664..4c76ce8f3 100644 --- a/config/crd/bases/bpfman.io_bpfapplications.yaml +++ b/config/crd/bases/bpfman.io_bpfapplications.yaml @@ -57,17 +57,11 @@ spec: metadata: type: object spec: - description: |- - spec defines the desired state of the BpfApplication. The BpfApplication - describes the set of one or more namespace scoped eBPF programs that should - be loaded for a given application and attributes for how they should be - loaded. eBPF programs that are grouped together under the same - BpfApplication instance can share maps and global data between the eBPF - programs loaded on the same Kubernetes Node. + description: spec defines the desired state of the BpfApplication. properties: byteCode: description: |- - bytecode is a required field and configures where the eBPF program's + byteCode is a required field and configures where the eBPF program's bytecode should be loaded from. The image must contain one or more eBPF programs. maxProperties: 1 @@ -81,7 +75,7 @@ spec: imagePullPolicy: default: IfNotPresent description: |- - pullPolicy is an optional field that describes a policy for if/when to pull + imagePullPolicy is an optional field that describes a policy for if/when to pull a bytecode image. Defaults to IfNotPresent. Allowed values are: Always, IfNotPresent and Never @@ -109,16 +103,19 @@ spec: name: description: |- name is a required field and is the name of the secret which contains the - credentials to access the image repository. + credentials to access the image repository. name must not exceed 253 + characters in length. + maxLength: 253 + minLength: 1 type: string namespace: description: |- namespace is a required field and is the namespace of the secret which - contains the credentials to access the image repository. + contains the credentials to access the image repository. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string - required: - - name - - namespace type: object url: description: |- @@ -126,15 +123,16 @@ spec: a remote bytecode image. url must not be an empty string, must not exceed 525 characters in length and must be a valid URL. maxLength: 525 + minLength: 1 pattern: '[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}' type: string - required: - - url type: object path: description: |- path is an optional field and used to specify a bytecode object file via - filepath on a Kubernetes node. + filepath on a Kubernetes node. The path must be a valid absolute path with no null bytes, + matching the pattern ^(/[^/\0]+)+/?$. path must not exceed 1023 characters in length. + maxLength: 1023 pattern: ^(/[^/\0]+)+/?$ type: string type: object @@ -274,7 +272,7 @@ spec: name is a required field and is the name of the function that is the entry point for the eBPF program. name must not be an empty string, must not exceed 64 characters in length, must start with alpha characters and must - only contain alphanumeric characters. + only contain alphanumeric characters and underscores. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -340,9 +338,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -361,10 +364,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -373,16 +380,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -448,8 +461,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -495,13 +506,16 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - - direction - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: |- @@ -564,9 +578,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -585,10 +604,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -597,16 +620,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -672,8 +701,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -689,11 +716,12 @@ spec: minimum: 0 type: integer required: - - direction - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -783,10 +811,14 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic pods: description: |- pods is a required field and indicates the target pods. To select all pods @@ -836,8 +868,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -867,13 +897,15 @@ spec: target: description: |- target is a required field and is the user-space library name or the - absolute path to a binary or library. + absolute path to a binary or library. target must not exceed 1023 characters + in length. + maxLength: 1023 + minLength: 1 type: string - required: - - containers - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -917,10 +949,14 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic pods: description: |- pods is a required field and indicates the target pods. To select all pods @@ -970,8 +1006,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1001,13 +1035,15 @@ spec: target: description: |- target is a required field and is the user-space library name or the - absolute path to a binary or library. + absolute path to a binary or library. target must not exceed 1023 characters + in length. + maxLength: 1023 + minLength: 1 type: string - required: - - containers - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: |- @@ -1049,9 +1085,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -1070,10 +1111,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -1082,16 +1127,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -1157,8 +1208,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -1198,16 +1247,17 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - interfaceSelector - networkNamespaces type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -1230,16 +1280,15 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''URetProbe'' ? has(self.uretprobe) : !has(self.uretprobe)' + maxItems: 1023 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - byteCode - - nodeSelector type: object status: - description: |- - status reflects the status of a BPF Application and indicates if all the - eBPF programs for a given instance loaded successfully or not. + description: status reflects the observed state of the BpfApplication. properties: conditions: description: |- @@ -1312,11 +1361,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/config/crd/bases/bpfman.io_bpfapplicationstates.yaml b/config/crd/bases/bpfman.io_bpfapplicationstates.yaml index 40ae123e9..f6ecb65e5 100644 --- a/config/crd/bases/bpfman.io_bpfapplicationstates.yaml +++ b/config/crd/bases/bpfman.io_bpfapplicationstates.yaml @@ -86,6 +86,8 @@ spec: UnloadError is returned if one or more programs encountered an error when being unloaded. + maxLength: 1023 + minLength: 1 type: string conditions: description: |- @@ -161,12 +163,15 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map node: - description: node is the name of the Kubernets node for this BpfApplicationState. + description: node is the name of the Kubernetes node for this BpfApplicationState. + maxLength: 253 + minLength: 1 type: string programs: description: |- @@ -178,7 +183,9 @@ spec: name: description: |- name is the name of the function that is the entry point for the eBPF - program + program. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string programId: description: |- @@ -189,7 +196,10 @@ spec: programLinkStatus: description: |- programLinkStatus reflects whether all links requested for the program - are in the correct state. + are in the correct state. Valid values are documented in the + ProgramLinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string tc: description: tc contains the attachment data for a TC program @@ -214,7 +224,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TC program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -226,12 +238,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the TC - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -261,26 +279,27 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - - netnsPath - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: tcx contains the attachment data for a TCX program @@ -305,7 +324,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TCX program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -317,12 +338,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the TCX - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -338,19 +365,19 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - - netnsPath - priority - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -399,15 +426,19 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the BpfApplication instance, containerPid is - the derived PID of the container the UProbe or URetProbe this attachment - point is attached. + containerPid is the derived PID of the container the UProbe or URetProbe + this attachment point is attached to, if containers is provisioned in the + BpfApplication instance. format: int32 + maximum: 2147483647 + minimum: 1 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe - program should be attached. + program should be attached. function must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string linkId: description: |- @@ -419,7 +450,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -442,19 +476,23 @@ spec: target: description: |- target is the provisioned user-space library name or the absolute path to a - binary or library. + binary or library. target must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -471,15 +509,19 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the BpfApplication instance, containerPid is - the derived PID of the container the UProbe or URetProbe this attachment - point is attached. + containerPid is the derived PID of the container the UProbe or URetProbe + this attachment point is attached to, if containers is provisioned in the + BpfApplication instance. format: int32 + maximum: 2147483647 + minimum: 1 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe - program should be attached. + program should be attached. function must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string linkId: description: |- @@ -491,7 +533,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -514,19 +559,23 @@ spec: target: description: |- target is the provisioned user-space library name or the absolute path to a - binary or library. + binary or library. target must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: xdp contains the attachment data for an XDP program @@ -543,7 +592,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the XDP program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -555,12 +606,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the path to the network namespace inside of which the XDP - program should be attached. + program should be attached. netnsPath must not exceed 1023 characters in + length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -585,30 +642,28 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - interfaceName - - linkStatus - - netnsPath - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - programLinkStatus - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -631,21 +686,20 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''URetProbe'' ? has(self.uretprobe) : !has(self.uretprobe)' + maxItems: 1023 type: array + x-kubernetes-list-type: atomic updateCount: description: |- - UpdateCount tracks the number of times the BpfApplicationState object has + updateCount tracks the number of times the BpfApplicationState object has been updated. The bpfman agent initializes it to 1 when it creates the object, and then increments it before each subsequent update. It serves as a lightweight sequence number to verify that the API server is serving the most recent version of the object before beginning a new Reconcile operation. format: int64 + minimum: 1 type: integer - required: - - appLoadStatus - - node - - updateCount type: object type: object served: true diff --git a/config/crd/bases/bpfman.io_clusterbpfapplications.yaml b/config/crd/bases/bpfman.io_clusterbpfapplications.yaml index 199f3400d..1d1b41a46 100644 --- a/config/crd/bases/bpfman.io_clusterbpfapplications.yaml +++ b/config/crd/bases/bpfman.io_clusterbpfapplications.yaml @@ -58,17 +58,11 @@ spec: metadata: type: object spec: - description: |- - spec defines the desired state of the ClusterBpfApplication. The - ClusterBpfApplication describes the set of one or more cluster scoped eBPF - programs that should be loaded for a given application and attributes for - how they should be loaded. eBPF programs that are grouped together under the - same ClusterBpfApplication instance can share maps and global data between - the eBPF programs loaded on the same Kubernetes Node. + description: spec defines the desired state of the BpfApplication. properties: byteCode: description: |- - bytecode is a required field and configures where the eBPF program's + byteCode is a required field and configures where the eBPF program's bytecode should be loaded from. The image must contain one or more eBPF programs. maxProperties: 1 @@ -82,7 +76,7 @@ spec: imagePullPolicy: default: IfNotPresent description: |- - pullPolicy is an optional field that describes a policy for if/when to pull + imagePullPolicy is an optional field that describes a policy for if/when to pull a bytecode image. Defaults to IfNotPresent. Allowed values are: Always, IfNotPresent and Never @@ -110,16 +104,19 @@ spec: name: description: |- name is a required field and is the name of the secret which contains the - credentials to access the image repository. + credentials to access the image repository. name must not exceed 253 + characters in length. + maxLength: 253 + minLength: 1 type: string namespace: description: |- namespace is a required field and is the namespace of the secret which - contains the credentials to access the image repository. + contains the credentials to access the image repository. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string - required: - - name - - namespace type: object url: description: |- @@ -127,15 +124,16 @@ spec: a remote bytecode image. url must not be an empty string, must not exceed 525 characters in length and must be a valid URL. maxLength: 525 + minLength: 1 pattern: '[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}' type: string - required: - - url type: object path: description: |- path is an optional field and used to specify a bytecode object file via - filepath on a Kubernetes node. + filepath on a Kubernetes node. The path must be a valid absolute path with no null bytes, + matching the pattern ^(/[^/\0]+)+/?$. path must not exceed 1023 characters in length. + maxLength: 1023 pattern: ^(/[^/\0]+)+/?$ type: string type: object @@ -307,13 +305,10 @@ spec: enum: - Attach type: string - required: - - mode type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object fexit: description: |- @@ -330,8 +325,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the FExit program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -356,13 +352,10 @@ spec: enum: - Attach type: string - required: - - mode type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object kprobe: description: |- @@ -395,8 +388,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the KProbe program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -408,10 +402,10 @@ spec: attachment point function. If not provided, offset defaults to 0. format: int64 type: integer - required: - - function type: object + maxItems: 1 type: array + x-kubernetes-list-type: atomic type: object kretprobe: description: |- @@ -446,17 +440,17 @@ spec: minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string - required: - - function type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object name: description: |- name is a required field and is the name of the function that is the entry point for the eBPF program. name must not be an empty string, must not exceed 64 characters in length, must start with alpha characters and must - only contain alphanumeric characters. + only contain alphanumeric characters and underscores. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -522,9 +516,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -543,10 +542,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -555,16 +558,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -585,7 +594,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -636,8 +648,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -683,12 +693,15 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - - direction - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: |- @@ -751,9 +764,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -772,10 +790,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -784,16 +806,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -814,7 +842,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -865,8 +896,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -882,10 +911,11 @@ spec: minimum: 0 type: integer required: - - direction - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tracepoint: description: |- @@ -913,7 +943,7 @@ spec: The attachment point for a Tracepoint program is a one of a predefined set - of Linux kernel functions. + of Linux kernel functions. The list is limited to a maximum of 1023 entries. items: properties: name: @@ -926,10 +956,10 @@ spec: minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string - required: - - name type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -1052,14 +1082,21 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic namespace: description: |- namespace is an optional field and indicates the target Kubernetes namespace. If not provided, all Kubernetes namespaces are included. + namespace must not exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1110,8 +1147,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1142,11 +1177,13 @@ spec: description: |- target is a required field and is the user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string - required: - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -1189,14 +1226,21 @@ spec: description: |- containerNames is an optional field and is a list of container names in a pod to attach the eBPF program. If no names are specified, all containers - in the pod are selected. + in the pod are selected. The list is limited to a maximum of 1023 entries, + and each container name must not exceed 253 characters in length. items: + maxLength: 253 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic namespace: description: |- namespace is an optional field and indicates the target Kubernetes namespace. If not provided, all Kubernetes namespaces are included. + namespace must not exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1247,8 +1291,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object function: description: |- @@ -1279,11 +1321,13 @@ spec: description: |- target is a required field and is the user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string - required: - - target type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: |- @@ -1326,9 +1370,14 @@ spec: description: |- interfaces is an optional field and is a list of network interface names to attach the eBPF program. The interface names in the list are case-sensitive. + The list is limited to a maximum of 1023 entries, and each interface name + must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfacesDiscoveryConfig: description: |- interfacesDiscoveryConfig is an optional field that is used to control if @@ -1347,10 +1396,14 @@ spec: `/veth*/`, then the entry is considered as a regular expression for matching. Otherwise, the interface names in the list are case-sensitive. This field is only taken into consideration if interfaceAutoDiscovery is set - to true. + to true. The list is limited to a maximum of 1023 entries, and each + interface name must not exceed 63 characters in length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic excludeInterfaces: default: - lo @@ -1359,16 +1412,22 @@ spec: names that are excluded from interface discovery. The interface names in the list are case-sensitive. By default, the list contains the loopback interface, "lo". This field is only taken into consideration if - interfaceAutoDiscovery is set to true. + interfaceAutoDiscovery is set to true. The list is limited to a maximum of + 1023 entries, and each interface name must not exceed 63 characters in + length. items: + maxLength: 63 type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic interfaceAutoDiscovery: default: false description: |- interfaceAutoDiscovery is an optional field. When enabled, the agent monitors the creation and deletion of interfaces and automatically attached eBPF programs to the newly discovered interfaces. + Valid values are "Enabled", "Disabled" (default). CAUTION: This has the potential to attach a given eBPF program to a large number of interfaces. Use with caution. type: boolean @@ -1389,7 +1448,10 @@ spec: namespace: description: |- namespace is an optional field and indicates the target network namespace. - If not provided, the default network namespace is used. + If not provided, the default network namespace is used. namespace must not + exceed 253 characters in length. + maxLength: 253 + minLength: 1 type: string pods: description: |- @@ -1440,8 +1502,6 @@ spec: type: object type: object x-kubernetes-map-type: atomic - required: - - pods type: object priority: default: 1000 @@ -1481,15 +1541,16 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic required: - interfaceSelector type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -1532,17 +1593,15 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''TracePoint'' ? has(self.tracepoint) : !has(self.tracepoint)' + maxItems: 1023 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - byteCode - - nodeSelector - - programs type: object status: - description: |- - status reflects the status of a BPF Application and indicates if all the - eBPF programs for a given instance loaded successfully or not. + description: status reflects the observed state of the BpfApplication. properties: conditions: description: |- @@ -1615,11 +1674,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/config/crd/bases/bpfman.io_clusterbpfapplicationstates.yaml b/config/crd/bases/bpfman.io_clusterbpfapplicationstates.yaml index c097dbfbd..c7ced2f45 100644 --- a/config/crd/bases/bpfman.io_clusterbpfapplicationstates.yaml +++ b/config/crd/bases/bpfman.io_clusterbpfapplicationstates.yaml @@ -84,6 +84,8 @@ spec: UnloadError is returned if one or more programs encountered an error when being unloaded. + maxLength: 1023 + minLength: 1 type: string conditions: description: |- @@ -159,12 +161,15 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map node: description: node is the name of the Kubernetes node for this ClusterBpfApplicationState. + maxLength: 253 + minLength: 1 type: string programs: description: |- @@ -207,25 +212,28 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - uuid type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object fexit: description: |- @@ -236,8 +244,9 @@ spec: description: |- function is a required field and specifies the name of the Linux kernel function to attach the FExit program. function must not be an empty string, - must not exceed 64 characters in length, must start with alpha characters - and must only contain alphanumeric characters. + must be between 1 and 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters and underscores. + The pattern ^[a-zA-Z][a-zA-Z0-9_]+. is enforced. maxLength: 64 minLength: 1 pattern: ^[a-zA-Z][a-zA-Z0-9_]+. @@ -260,25 +269,28 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - uuid type: object maxItems: 1 type: array - required: - - function + x-kubernetes-list-type: atomic type: object kprobe: description: |- @@ -295,8 +307,13 @@ spec: properties: function: description: |- - function is the provisioned name of the Linux kernel function the KProbe - program should be attached. + function is a required field and specifies the name of the Linux kernel + function to attach the Kprobe. function must not be an empty + string, must not exceed 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters. + maxLength: 64 + minLength: 1 + pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string linkId: description: |- @@ -308,7 +325,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -322,16 +342,18 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - function - - linkStatus - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object kretprobe: description: |- @@ -348,8 +370,13 @@ spec: properties: function: description: |- - function is the provisioned name of the Linux kernel function the KRetProbe - program should be attached. + function is a required field and specifies the name of the Linux kernel + function to attach the KRetProbe program. function must not be an empty + string, must not exceed 64 characters in length, must start with alpha + characters and must only contain alphanumeric characters. + maxLength: 64 + minLength: 1 + pattern: ^[a-zA-Z][a-zA-Z0-9_]+. type: string linkId: description: |- @@ -361,28 +388,35 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - function - - linkStatus - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object name: description: |- name is the name of the function that is the entry point for the eBPF - program + program. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string programId: description: |- @@ -393,7 +427,10 @@ spec: programLinkStatus: description: |- programLinkStatus reflects whether all links requested for the program - are in the correct state. + are in the correct state. Valid values are documented in the + ProgramLinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string tc: description: tc contains the attachment data for a TC program @@ -419,6 +456,8 @@ spec: description: |- interfaceName is the name of the interface the TC program should be attached. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -430,12 +469,17 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the TC program should be attached. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -465,25 +509,27 @@ spec: - Trap - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tcx: description: tcx contains the attachment data for a TCX program @@ -494,7 +540,8 @@ spec: links is a list of attachment points for the TCX program. Each entry in the list includes a linkStatus, which indicates if the attachment was successful or not on this node, a linkId, which is the kernel ID for the link if - successfully attached, and other attachment specific data. + successfully attached, and other attachment specific data. The list is + limited to a maximum of 1023 entries. items: properties: direction: @@ -508,7 +555,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the TCX program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -520,12 +569,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the - TCX program should be attached. + TCX program should be attached. If not provided, the default network + namespace is used. netnsPath must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -541,18 +596,19 @@ spec: should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - direction - - interfaceName - - linkStatus - priority - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object tracepoint: description: |- @@ -564,7 +620,8 @@ spec: links is a list of attachment points for the Tracepoint program. Each entry in the list includes a linkStatus, which indicates if the attachment was successful or not on this node, a linkId, which is the kernel ID for the - link if successfully attached, and other attachment specific data. + link if successfully attached, and other attachment specific data. The list + is limited to a maximum of 1023 entries. items: properties: linkId: @@ -577,29 +634,35 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string name: description: |- - The name of a kernel tracepoint to attach the bpf program to. - name is the provisioned name of the Linux kernel tracepoint function the - Tracepoint program should be attached. + name is the provisioned name of the Linux kernel tracepoint function to which + the BPF program should be attached. name must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - - name - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object type: description: |- @@ -674,15 +737,17 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the ClusterBpfApplication instance, - containerPid is the derived PID of the container the UProbe or URetProbe this - attachment point is attached. + containerPid is the derived PID of the container to which this UProbe or + URetProbe attachment point is attached. This field is populated when + containers are provisioned in the ClusterBpfApplication instance. format: int32 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe program should be attached. + maxLength: 1023 + minLength: 1 type: string linkId: description: |- @@ -694,7 +759,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -718,18 +786,22 @@ spec: description: |- target is the provisioned user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object uretprobe: description: |- @@ -746,15 +818,17 @@ spec: properties: containerPid: description: |- - If containers is provisioned in the ClusterBpfApplication instance, - containerPid is the derived PID of the container the UProbe or URetProbe this - attachment point is attached. + containerPid is the derived PID of the container to which this UProbe or + URetProbe attachment point is attached. This field is populated when + containers are provisioned in the ClusterBpfApplication instance. format: int32 type: integer function: description: |- function is the provisioned name of the user-space function the UProbe program should be attached. + maxLength: 1023 + minLength: 1 type: string linkId: description: |- @@ -766,7 +840,10 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string offset: default: 0 @@ -790,18 +867,22 @@ spec: description: |- target is the provisioned user-space library name or the absolute path to a binary or library. + maxLength: 1023 + minLength: 1 type: string uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - linkStatus - shouldAttach - - target - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object xdp: description: xdp contains the attachment data for an XDP program @@ -818,7 +899,9 @@ spec: interfaceName: description: |- interfaceName is the name of the interface the XDP program should be - attached. + attached. interfaceName must not exceed 63 characters in length. + maxLength: 63 + minLength: 1 type: string linkId: description: |- @@ -830,12 +913,18 @@ spec: linkStatus: description: |- linkStatus reflects whether the attachment has been reconciled - successfully, and if not, why. + successfully, and if not, why. Valid values are documented in the + LinkStatus type definition. + maxLength: 1023 + minLength: 1 type: string netnsPath: description: |- netnsPath is the optional path to the network namespace inside of which the - XDP program should be attached. + XDP program should be attached. If not provided, the default network + namespace is used. netnsPath must not exceed 1023 characters in length. + maxLength: 1023 + minLength: 1 type: string priority: description: |- @@ -860,29 +949,28 @@ spec: - ReDirect - DispatcherReturn type: string + maxItems: 1023 type: array + x-kubernetes-list-type: atomic shouldAttach: description: shouldAttach reflects whether the attachment should exist. type: boolean uuid: - description: uuid is an Unique identifier for the - attach point assigned by bpfman agent. + description: |- + uuid is an Unique identifier for the attach point assigned by bpfman agent. + uuid must not exceed 64 characters in length. + maxLength: 64 + minLength: 1 type: string required: - - interfaceName - - linkStatus - priority - - proceedOn - shouldAttach - - uuid type: object + maxItems: 1023 type: array + x-kubernetes-list-type: atomic type: object - required: - - name - - programLinkStatus - - type type: object x-kubernetes-validations: - message: xdp configuration is required when type is xdp, and forbidden @@ -925,21 +1013,20 @@ spec: and forbidden otherwise rule: 'has(self.type) && self.type == ''TracePoint'' ? has(self.tracepoint) : !has(self.tracepoint)' + maxItems: 1023 type: array + x-kubernetes-list-type: atomic updateCount: description: |- - UpdateCount tracks the number of times the BpfApplicationState object has + updateCount tracks the number of times the BpfApplicationState object has been updated. The bpfman agent initializes it to 1 when it creates the object, and then increments it before each subsequent update. It serves as a lightweight sequence number to verify that the API server is serving the most recent version of the object before beginning a new Reconcile operation. format: int64 + minimum: 1 type: integer - required: - - appLoadStatus - - node - - updateCount type: object type: object served: true diff --git a/config/crd/bases/bpfman.io_configs.yaml b/config/crd/bases/bpfman.io_configs.yaml index f94557cd9..b1291ee6c 100644 --- a/config/crd/bases/bpfman.io_configs.yaml +++ b/config/crd/bases/bpfman.io_configs.yaml @@ -18,6 +18,12 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + - jsonPath: .status.conditions[?(@.type=='Progressing')].status + name: Progressing + type: string + - jsonPath: .status.conditions[?(@.type=='Available')].status + name: Available + type: string name: v1alpha1 schema: openAPIV3Schema: @@ -41,53 +47,82 @@ spec: metadata: type: object spec: - description: Spec defines the desired state of the bpfman-operator. + description: spec defines the desired state of the bpfman-operator. properties: agent: - description: Agent holds the configuration for the bpfman agent. + description: agent specifies the configuration for the bpfman agent + DaemonSet. properties: healthProbePort: - default: 8175 - description: HealthProbePort holds the health probe bind port - for the bpfman agent. + description: |- + healthProbePort specifies the port on which the bpfman agent's health probe endpoint will listen. + If unspecified, the default port will be used. + format: int32 maximum: 65535 minimum: 1 type: integer image: - description: Image holds the image for the bpfman agent. + description: image specifies the container image for the bpfman + agent DaemonSet. + maxLength: 1023 minLength: 1 type: string logLevel: - description: LogLevel holds the log level for the bpfman agent. + description: |- + logLevel specifies the verbosity of logs produced by the bpfman agent. + Valid values are: "info", "debug", "trace". + enum: + - info + - debug + - trace + maxLength: 256 + minLength: 1 type: string - required: - - image type: object configuration: - description: Configuration holds the content of bpfman.toml. + description: configuration specifies the content of bpfman.toml configuration + file used by the bpfman DaemonSet. + maxLength: 65536 minLength: 1 type: string image: - description: Image holds the image of the bpfman DaemonSets. + description: image specifies the container image for the bpfman DaemonSet. + maxLength: 1023 minLength: 1 type: string logLevel: - description: LogLevel holds the log level for the bpfman-operator. + description: |- + logLevel specifies the log level for the bpfman DaemonSet via the RUST_LOG environment variable. + The RUST_LOG environment variable controls logging with the syntax: RUST_LOG=[target][=][level][,...]. + For further information, see https://docs.rs/env_logger/latest/env_logger/. + maxLength: 1024 + minLength: 1 type: string namespace: description: |- - Namespace holds the namespace where bpfman-operator resources shall be - deployed. + namespace specifies the namespace where bpfman-operator resources will be deployed. + If not specified, resources will be deployed in the default bpfman namespace. + maxLength: 256 + minLength: 1 type: string required: - - configuration - - image + - agent type: object status: - description: status reflects the status of the bpfman-operator configuration. + description: status reflects the observed state of the bpfman-operator. properties: + components: + additionalProperties: + description: ConfigComponentStatus holds the status of a single + Config component. + type: string + description: |- + components represents the operational status of each individual bpfman-operator component such as the deployed + DaemonSets. + type: object conditions: - description: conditions store the status conditions of the bpfman-operator. + description: conditions represents the current state conditions of + the bpfman-operator and its components. items: description: "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for @@ -155,11 +190,14 @@ spec: - status - type type: object + maxItems: 1023 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map type: object + required: + - spec type: object served: true storage: true diff --git a/config/rbac/bpfman-operator/role.yaml b/config/rbac/bpfman-operator/role.yaml index 6db029f41..2790b97a7 100644 --- a/config/rbac/bpfman-operator/role.yaml +++ b/config/rbac/bpfman-operator/role.yaml @@ -101,6 +101,14 @@ rules: - configs/finalizers verbs: - update +- apiGroups: + - bpfman.io + resources: + - configs/status + verbs: + - get + - patch + - update - apiGroups: - "" resources: @@ -113,6 +121,13 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - "" resources: diff --git a/controllers/bpfman-agent/cl_application_program.go b/controllers/bpfman-agent/cl_application_program.go index 64cbf58b4..4b2b40a02 100644 --- a/controllers/bpfman-agent/cl_application_program.go +++ b/controllers/bpfman-agent/cl_application_program.go @@ -535,7 +535,7 @@ func (r *ClBpfApplicationReconciler) getBpfAppState(ctx context.Context) (*bpfma opts := []client.ListOption{ client.MatchingLabels{ - internal.BpfAppStateOwner: r.currentApp.GetName(), + internal.BpfAppStateOwner: r.currentApp.Name, internal.K8sHostLabel: r.NodeName, }, } @@ -566,7 +566,7 @@ func (r *ClBpfApplicationReconciler) initBpfAppState() error { Name: generateUniqueName(r.currentApp.Name), Finalizers: []string{r.finalizer}, Labels: map[string]string{ - internal.BpfAppStateOwner: r.currentApp.GetName(), + internal.BpfAppStateOwner: r.currentApp.Name, internal.K8sHostLabel: r.NodeName, }, }, diff --git a/controllers/bpfman-agent/ns_application_program.go b/controllers/bpfman-agent/ns_application_program.go index a642e0642..e855c5f6f 100644 --- a/controllers/bpfman-agent/ns_application_program.go +++ b/controllers/bpfman-agent/ns_application_program.go @@ -478,7 +478,7 @@ func (r *NsBpfApplicationReconciler) getBpfAppState(ctx context.Context) (*bpfma opts := []client.ListOption{ client.MatchingLabels{ - internal.BpfAppStateOwner: r.currentApp.GetName(), + internal.BpfAppStateOwner: r.currentApp.Name, internal.K8sHostLabel: r.NodeName, }, } @@ -510,7 +510,7 @@ func (r *NsBpfApplicationReconciler) initBpfAppState() error { Namespace: r.currentApp.Namespace, Finalizers: []string{r.finalizer}, Labels: map[string]string{ - internal.BpfAppStateOwner: r.currentApp.GetName(), + internal.BpfAppStateOwner: r.currentApp.Name, internal.K8sHostLabel: r.NodeName, }, }, diff --git a/controllers/bpfman-operator/cl_application_program_test.go b/controllers/bpfman-operator/cl_application_program_test.go index 216a4e17d..a2b7e4db9 100644 --- a/controllers/bpfman-operator/cl_application_program_test.go +++ b/controllers/bpfman-operator/cl_application_program_test.go @@ -178,7 +178,7 @@ func appProgramReconcile(t *testing.T, multiCondition bool) { // Create a fake client to mock API calls. cl := fake.NewClientBuilder().WithStatusSubresource(app).WithRuntimeObjects(objs...).Build() - rc := ReconcilerCommon[bpfmaniov1alpha1.ClusterBpfApplicationState, bpfmaniov1alpha1.ClusterBpfApplicationStateList]{ + rc := ReconcilerCommon{ Client: cl, Scheme: s, } diff --git a/controllers/bpfman-operator/cl_application_programs.go b/controllers/bpfman-operator/cl_application_programs.go index 5fca39db0..ad5ce06da 100644 --- a/controllers/bpfman-operator/cl_application_programs.go +++ b/controllers/bpfman-operator/cl_application_programs.go @@ -44,7 +44,7 @@ type BpfApplicationReconciler struct { } //lint:ignore U1000 Linter claims function unused, but generics confusing linter -func (r *BpfApplicationReconciler) getRecCommon() *ReconcilerCommon[bpfmaniov1alpha1.ClusterBpfApplicationState, bpfmaniov1alpha1.ClusterBpfApplicationStateList] { +func (r *BpfApplicationReconciler) getRecCommon() *ReconcilerCommon { return &r.ClusterApplicationReconciler.ReconcilerCommon } diff --git a/controllers/bpfman-operator/common.go b/controllers/bpfman-operator/common.go index eace41cb2..2bf53ae66 100644 --- a/controllers/bpfman-operator/common.go +++ b/controllers/bpfman-operator/common.go @@ -55,23 +55,23 @@ type BpfProgListOper[T any] interface { GetItems() []T } -type ReconcilerCommon[T BpfProgOper, TL BpfProgListOper[T]] struct { +type ReconcilerCommon struct { client.Client Scheme *runtime.Scheme Logger logr.Logger } // ApplicationReconciler defines a k8s reconciler which can program bpfman. -type ApplicationReconciler[T BpfProgOper, TL BpfProgListOper[T]] interface { +type ApplicationReconciler interface { // BPF Cluster of Namespaced Reconciler getAppStateList(ctx context.Context, appName string, appNamespace string, - ) (*TL, error) - containsFinalizer(bpfApplication *T, finalizer string) bool + ) (client.ObjectList, error) + containsFinalizer(bpfApplication client.Object, finalizer string) bool // *Program Reconciler - getRecCommon() *ReconcilerCommon[T, TL] + getRecCommon() *ReconcilerCommon updateStatus(ctx context.Context, namespace string, name string, @@ -80,9 +80,23 @@ type ApplicationReconciler[T BpfProgOper, TL BpfProgListOper[T]] interface { getFinalizer() string } -func reconcileBpfApplication[T BpfProgOper, TL BpfProgListOper[T]]( +// ValidReconciler encompasses BpfApplicationReconciler and BpfNSApplicationReconciler. +type ValidReconciler interface { + ValidReconcilerMethods + *BpfApplicationReconciler | *BpfNsApplicationReconciler +} + +type ValidReconcilerMethods interface { + getRecCommon() *ReconcilerCommon + getAppStateList(ctx context.Context, appName string, appNamespace string) (client.ObjectList, error) + updateStatus(ctx context.Context, namespace string, name string, cond bpfmaniov1alpha1.BpfApplicationConditionType, message string) (ctrl.Result, error) + containsFinalizer(bpfApplication client.Object, finalizer string) bool + getFinalizer() string +} + +func reconcileBpfApplication[T ValidReconciler]( ctx context.Context, - rec ApplicationReconciler[T, TL], + rec T, app client.Object, ) (ctrl.Result, error) { r := rec.getRecCommon() @@ -103,6 +117,12 @@ func reconcileBpfApplication[T BpfProgOper, TL BpfProgListOper[T]]( r.Logger.Error(err, "failed to get freshPrograms for full reconcile") return ctrl.Result{}, nil } + var bpfAppStateList []client.Object + _ = meta.EachListItem(bpfAppStateObjs, func(obj runtime.Object) error { + appState := obj.(client.Object) + bpfAppStateList = append(bpfAppStateList, appState) + return nil + }) // List all nodes since a BpfApplicationState object will always be created for each nodes := &corev1.NodeList{} @@ -116,7 +136,7 @@ func reconcileBpfApplication[T BpfProgOper, TL BpfProgListOper[T]]( if app.GetDeletionTimestamp().IsZero() { for _, node := range nodes.Items { nodeFound := false - for _, appState := range (*bpfAppStateObjs).GetItems() { + for _, appState := range bpfAppStateList { bpfProgramState := appState.GetLabels()[internal.K8sHostLabel] if node.Name == bpfProgramState { nodeFound = true @@ -133,13 +153,15 @@ func reconcileBpfApplication[T BpfProgOper, TL BpfProgListOper[T]]( failedBpfApplications := []string{} finalApplied := []string{} // Make sure no BpfApplications had any issues in the loading or unloading process - for _, bpfAppState := range (*bpfAppStateObjs).GetItems() { - - if rec.containsFinalizer(&bpfAppState, rec.getFinalizer()) { + for _, bpfAppState := range bpfAppStateList { + if rec.containsFinalizer(bpfAppState, rec.getFinalizer()) { finalApplied = append(finalApplied, bpfAppState.GetName()) } - conditions := bpfAppState.GetConditions() + conditions, err := getBpfApplicationConditions(bpfAppState) + if err != nil { + return ctrl.Result{}, err + } if bpfmanHelpers.IsBpfAppStateConditionFailure(conditions) { failedBpfApplications = append(failedBpfApplications, bpfAppState.GetName()) } else if bpfmanHelpers.IsBpfAppStateConditionPending(conditions) { @@ -169,7 +191,18 @@ func reconcileBpfApplication[T BpfProgOper, TL BpfProgListOper[T]]( return rec.updateStatus(ctx, appNamespace, appName, bpfmaniov1alpha1.BpfAppCondSuccess, "") } -func (r *ReconcilerCommon[T, TL]) removeFinalizer(ctx context.Context, bpfApp client.Object, finalizer string) (ctrl.Result, error) { +func getBpfApplicationConditions(bpfAppState client.Object) ([]metav1.Condition, error) { + switch v := bpfAppState.(type) { + case *bpfmaniov1alpha1.ClusterBpfApplicationState: + return v.Status.Conditions, nil + case *bpfmaniov1alpha1.BpfApplicationState: + return v.Status.Conditions, nil + } + return nil, fmt.Errorf("this error should never be triggered as only " + + "*BpfApplicationReconciler | *BpfNsApplicationReconciler are valid types for rec") +} + +func (r *ReconcilerCommon) removeFinalizer(ctx context.Context, bpfApp client.Object, finalizer string) (ctrl.Result, error) { r.Logger.Info("Calling KubeAPI to delete Program Finalizer", "Type", bpfApp.GetObjectKind().GroupVersionKind().Kind, "Name", bpfApp.GetName()) if changed := controllerutil.RemoveFinalizer(bpfApp, finalizer); changed { @@ -183,7 +216,7 @@ func (r *ReconcilerCommon[T, TL]) removeFinalizer(ctx context.Context, bpfApp cl return ctrl.Result{}, nil } -func (r *ReconcilerCommon[T, TL]) addFinalizer(ctx context.Context, app client.Object, finalizer string) (ctrl.Result, error) { +func (r *ReconcilerCommon) addFinalizer(ctx context.Context, app client.Object, finalizer string) (ctrl.Result, error) { controllerutil.AddFinalizer(app, finalizer) r.Logger.Info("Calling KubeAPI to add Program Finalizer", "Type", app.GetObjectKind().GroupVersionKind().Kind, "Name", app.GetName()) @@ -196,7 +229,7 @@ func (r *ReconcilerCommon[T, TL]) addFinalizer(ctx context.Context, app client.O return ctrl.Result{}, nil } -func (r *ReconcilerCommon[T, TL]) updateCondition( +func (r *ReconcilerCommon) updateCondition( ctx context.Context, obj client.Object, conditions *[]metav1.Condition, diff --git a/controllers/bpfman-operator/common_cluster.go b/controllers/bpfman-operator/common_cluster.go index e9c9e7081..0bc3d2cbc 100644 --- a/controllers/bpfman-operator/common_cluster.go +++ b/controllers/bpfman-operator/common_cluster.go @@ -30,7 +30,7 @@ import ( ) type ClusterApplicationReconciler struct { - ReconcilerCommon[bpfmaniov1alpha1.ClusterBpfApplicationState, bpfmaniov1alpha1.ClusterBpfApplicationStateList] + ReconcilerCommon } //lint:ignore U1000 Linter claims function unused, but generics confusing linter @@ -38,7 +38,7 @@ func (r *ClusterApplicationReconciler) getAppStateList( ctx context.Context, appName string, _appNamespace string, -) (*bpfmaniov1alpha1.ClusterBpfApplicationStateList, error) { +) (client.ObjectList, error) { appStateList := &bpfmaniov1alpha1.ClusterBpfApplicationStateList{} @@ -57,7 +57,7 @@ func (r *ClusterApplicationReconciler) getAppStateList( //lint:ignore U1000 Linter claims function unused, but generics confusing linter func (r *ClusterApplicationReconciler) containsFinalizer( - bpfAppState *bpfmaniov1alpha1.ClusterBpfApplicationState, + bpfAppState client.Object, finalizer string, ) bool { return controllerutil.ContainsFinalizer(bpfAppState, finalizer) diff --git a/controllers/bpfman-operator/common_namespace.go b/controllers/bpfman-operator/common_namespace.go index ec6776b42..cfdbc2cac 100644 --- a/controllers/bpfman-operator/common_namespace.go +++ b/controllers/bpfman-operator/common_namespace.go @@ -30,7 +30,7 @@ import ( ) type NamespaceApplicationReconciler struct { - ReconcilerCommon[bpfmaniov1alpha1.BpfApplicationState, bpfmaniov1alpha1.BpfApplicationStateList] + ReconcilerCommon } //lint:ignore U1000 Linter claims function unused, but generics confusing linter @@ -38,7 +38,7 @@ func (r *NamespaceApplicationReconciler) getAppStateList( ctx context.Context, appName string, appNamespace string, -) (*bpfmaniov1alpha1.BpfApplicationStateList, error) { +) (client.ObjectList, error) { appStateList := &bpfmaniov1alpha1.BpfApplicationStateList{} @@ -58,7 +58,7 @@ func (r *NamespaceApplicationReconciler) getAppStateList( //lint:ignore U1000 Linter claims function unused, but generics confusing linter func (r *NamespaceApplicationReconciler) containsFinalizer( - bpfAppState *bpfmaniov1alpha1.BpfApplicationState, + bpfAppState client.Object, finalizer string, ) bool { return controllerutil.ContainsFinalizer(bpfAppState, finalizer) diff --git a/controllers/bpfman-operator/config.go b/controllers/bpfman-operator/config.go index b082d6a7f..2e3cc0c86 100644 --- a/controllers/bpfman-operator/config.go +++ b/controllers/bpfman-operator/config.go @@ -29,9 +29,11 @@ import ( storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -51,7 +53,9 @@ import ( // +kubebuilder:rbac:groups=storage.k8s.io,resources=csidrivers,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=security.openshift.io,resources=securitycontextconstraints,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=bpfman.io,resources=configs,verbs=get;list;watch;update;patch;delete +// +kubebuilder:rbac:groups=bpfman.io,resources=configs/status,verbs=get;update;patch // +kubebuilder:rbac:groups=bpfman.io,resources=configs/finalizers,verbs=update +// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch type BpfmanConfigReconciler struct { ClusterApplicationReconciler @@ -60,6 +64,7 @@ type BpfmanConfigReconciler struct { CsiDriverDS string RestrictedSCC string IsOpenshift bool + Recorder record.EventRecorder } // SetupWithManager sets up the controller with the Manager. @@ -106,6 +111,14 @@ func (r *BpfmanConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } + // If we haven't added any conditions, yet, set them to unknown. + if len(bpfmanConfig.Status.Conditions) == 0 { + r.Logger.Info("Adding initial status conditions", "name", bpfmanConfig.Name) + if err := r.setStatusConditions(ctx, bpfmanConfig); err != nil { + return ctrl.Result{}, err + } + } + // Check if Config is being deleted first to prevent race // conditions. if !bpfmanConfig.DeletionTimestamp.IsZero() { @@ -121,7 +134,7 @@ func (r *BpfmanConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request r.Logger.Error(err, "Failed to add finalizer to Config") return ctrl.Result{}, err } - return ctrl.Result{}, nil + return ctrl.Result{}, r.setStatusConditions(ctx, bpfmanConfig) } // Normal reconciliation - safe to create/update resources. @@ -145,7 +158,7 @@ func (r *BpfmanConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - return ctrl.Result{}, nil + return ctrl.Result{}, r.setStatusConditions(ctx, bpfmanConfig) } func (r *BpfmanConfigReconciler) reconcileCM(ctx context.Context, bpfmanConfig *v1alpha1.Config) error { @@ -225,6 +238,176 @@ func (r *BpfmanConfigReconciler) reconcileMetricsProxyDS(ctx context.Context, bp }) } +// setStatusConditions checks the status of all Config components (ConfigMap, DaemonSets, CSIDriver, SCC) +// and updates the Config's status.componentStatuses and status.conditions accordingly. +// It emits Kubernetes events for status changes. After updating the status subresource, it re-fetches +// the Config object to ensure the in-memory representation reflects the latest server state, including +// any changes made by the API server (e.g., resource version updates). +func (r *BpfmanConfigReconciler) setStatusConditions(ctx context.Context, config *v1alpha1.Config) error { + if config == nil { + return fmt.Errorf("object Config config is nil") + } + if r.Recorder == nil { + return fmt.Errorf("object Recorder is nil") + } + + // Check each resource and set appropriate status. + statuses := make(map[string]v1alpha1.ConfigComponentStatus) + var err error + var status *v1alpha1.ConfigComponentStatus + + cm := &corev1.ConfigMap{} + key := types.NamespacedName{Name: internal.BpfmanCmName, Namespace: config.Spec.Namespace} + if status, err = r.checkResourceStatus(ctx, cm, key, nil); err != nil { + return err + } + if status != nil { + statuses["ConfigMap"] = *status + } + + ds := &appsv1.DaemonSet{} + key = types.NamespacedName{Name: internal.BpfmanDsName, Namespace: config.Spec.Namespace} + if status, err = r.checkResourceStatus(ctx, ds, key, isDaemonSetReady); err != nil { + return err + } + if status != nil { + statuses["DaemonSet"] = *status + } + + metricsDS := &appsv1.DaemonSet{} + key = types.NamespacedName{Name: internal.BpfmanMetricsProxyDsName, Namespace: config.Spec.Namespace} + if status, err = r.checkResourceStatus(ctx, metricsDS, key, isDaemonSetReady); err != nil { + return err + } + if status != nil { + statuses["MetricsProxyDaemonSet"] = *status + } + + csiDriver := &storagev1.CSIDriver{} + key = types.NamespacedName{Name: internal.BpfmanCsiDriverName} + if status, err = r.checkResourceStatus(ctx, csiDriver, key, nil); err != nil { + return err + } + if status != nil { + statuses["CsiDriver"] = *status + } + + if r.IsOpenshift { + scc := &osv1.SecurityContextConstraints{} + key = types.NamespacedName{Name: internal.BpfmanRestrictedSccName} + if status, err = r.checkResourceStatus(ctx, scc, key, nil); err != nil { + return err + } + if status != nil { + statuses["Scc"] = *status + } + } + + // If none of the components changed, do not update anything for the status. + if config.Status.Components != nil && internal.CCSEquals(statuses, config.Status.Components) { + return nil + } + + // Set component statuses, first. + config.Status.Components = statuses + + // Set conditions, next. + switch { + case internal.CCSAnyComponentProgressing(statuses, r.IsOpenshift): + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionTrue, + Reason: internal.ConfigReasonProgressing, + Message: internal.ConfigMessageProgressing, + }) + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionFalse, + Reason: internal.ConfigReasonProgressing, + Message: internal.ConfigMessageProgressing, + }) + r.Recorder.Event(config, "Normal", internal.ConfigReasonProgressing, internal.ConfigMessageProgressing) + case internal.CCSAllComponentsReady(statuses, r.IsOpenshift): + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionFalse, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + }) + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionTrue, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + }) + r.Recorder.Event(config, "Normal", internal.ConfigReasonAvailable, internal.ConfigMessageAvailable) + default: + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionUnknown, + Reason: internal.ConfigReasonUnknown, + Message: internal.ConfigMessageUnknown, + }) + meta.SetStatusCondition(&config.Status.Conditions, metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionUnknown, + Reason: internal.ConfigReasonUnknown, + Message: internal.ConfigMessageUnknown, + }) + r.Recorder.Event(config, "Normal", internal.ConfigReasonUnknown, internal.ConfigMessageUnknown) + } + + // Update the status. + if err := r.Status().Update(ctx, config); err != nil { + return fmt.Errorf("cannot update status for config %q, err: %w", config.Name, err) + } + + // Update the object again (config is a pointer). + return r.Get(ctx, types.NamespacedName{Name: config.Name}, config) +} + +// checkResourceStatus is a helper for setStatusConditions. It checks whether a given object (= resource) can be found +// and if it's ready. It'll return a status (Unknown, Progressing, Ready) for the object or an error. +func (r *BpfmanConfigReconciler) checkResourceStatus(ctx context.Context, obj client.Object, key types.NamespacedName, + readyCheck func(client.Object) bool) (*v1alpha1.ConfigComponentStatus, error) { + if err := r.Get(ctx, key, obj); err != nil { + if errors.IsNotFound(err) { + return ptr.To(v1alpha1.ConfigStatusUnknown), nil + } else { + return nil, err + } + } + if readyCheck == nil || readyCheck(obj) { + return ptr.To(v1alpha1.ConfigStatusReady), nil + } + return ptr.To(v1alpha1.ConfigStatusProgressing), nil +} + +// isDaemonSetReady returns true if we consider the DaemonSet to be ready. +// We consider a DaemonSet to be ready when: +// a) the DesiredNumberScheduled is > 0. For example, if a DaemonSet's node selector matches 0 nodes, we consider that +// it isn't ready. +// b) We check UpdatedNumberScheduled and NumberAvailable, the same as in +// https://github.com/kubernetes/kubernetes/blob/ad82c3d39f5e9f21e173ffeb8aa57953a0da4601/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/rollout_status.go#L95 +// c) In addition, we check that NumberReady matches DesiredNumberScheduled. +func isDaemonSetReady(obj client.Object) bool { + daemon := obj.(*appsv1.DaemonSet) + if daemon.Status.DesiredNumberScheduled <= 0 { + return false + } + if daemon.Status.UpdatedNumberScheduled < daemon.Status.DesiredNumberScheduled { + return false + } + if daemon.Status.NumberAvailable < daemon.Status.DesiredNumberScheduled { + return false + } + if daemon.Status.NumberReady < daemon.Status.DesiredNumberScheduled { + return false + } + fmt.Printf("akaris +%v\n", daemon.Status) + return true +} + // resourcePredicate creates a predicate that filters events based on resource name. // Only processes events for resources matching the specified resourceName. func resourcePredicate(resourceName string) predicate.Funcs { @@ -431,9 +614,12 @@ func (r *BpfmanConfigReconciler) handleDeletion(ctx context.Context, config *v1a return ctrl.Result{}, nil } -func healthProbeAddress(healthProbePort int) string { - if healthProbePort <= 0 || healthProbePort > 65535 { +func healthProbeAddress(healthProbePort int32) string { + if healthProbePort < 0 || healthProbePort > 65535 { return "" } + if healthProbePort == 0 { + healthProbePort = internal.DefaultHealthProbePort + } return fmt.Sprintf(":%d", healthProbePort) } diff --git a/controllers/bpfman-operator/config_test.go b/controllers/bpfman-operator/config_test.go index 35005e751..d6e4472e8 100644 --- a/controllers/bpfman-operator/config_test.go +++ b/controllers/bpfman-operator/config_test.go @@ -18,6 +18,7 @@ package bpfmanoperator import ( "context" + "encoding/json" "fmt" "os" "path/filepath" @@ -33,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -42,6 +44,7 @@ import ( "github.com/bpfman/bpfman-operator/apis/v1alpha1" "github.com/bpfman/bpfman-operator/internal" + "github.com/bpfman/bpfman-operator/test/testutil" ) const ( @@ -62,7 +65,8 @@ func TestReconcile(t *testing.T) { } { t.Run(fmt.Sprintf("isOpenShift: %v", tc.isOpenShift), func(t *testing.T) { t.Log("Setting up test environment") - r, bpfmanConfig, req, ctx, cl := setupTestEnvironment(tc.isOpenShift) + fakeRecorder := record.NewFakeRecorder(100) + r, bpfmanConfig, req, ctx, cl := setupTestEnvironment(tc.isOpenShift, fakeRecorder) t.Log("Checking the restricted SCC name") require.Equal(t, tc.isOpenShift, r.RestrictedSCC != "", @@ -78,6 +82,12 @@ func TestReconcile(t *testing.T) { t.Fatalf("initial reconcile failed: %v", err) } + t.Log("Checking status (should be unknown)") + err = testStatusSet(ctx, cl, internal.BpfmanConfigName, tc.isOpenShift, "unknown") + if err != nil { + t.Fatalf("unexpected status on config %q: %q", internal.BpfmanConfigName, err) + } + t.Log("Running second reconcile (creates resources)") _, err = r.Reconcile(ctx, req) if err != nil { @@ -90,6 +100,30 @@ func TestReconcile(t *testing.T) { t.Fatalf("not all objects present after initial reconcile: %q", err) } + t.Log("Checking status (should be progressing)") + err = testStatusSet(ctx, cl, internal.BpfmanConfigName, tc.isOpenShift, "progressing") + if err != nil { + t.Fatalf("unexpected status on config %q: %q", internal.BpfmanConfigName, err) + } + + t.Log("Marking DaemonSets as ready") + err = testReconcileDaemonSets(ctx, cl) + if err != nil { + t.Fatalf("couldn't reconcile DaemonSets, %q", err) + } + + t.Log("Running third reconcile (flips status to available)") + _, err = r.Reconcile(ctx, req) + if err != nil { + t.Fatalf("second reconcile failed: %v", err) + } + + t.Log("Checking status (should be available)") + err = testStatusSet(ctx, cl, internal.BpfmanConfigName, tc.isOpenShift, "available") + if err != nil { + t.Fatalf("unexpected status on config %q: %q", internal.BpfmanConfigName, err) + } + // Delete objects one by one to test restoration. objects := map[string]client.Object{ "configmap": &corev1.ConfigMap{ @@ -175,7 +209,7 @@ func TestReconcile(t *testing.T) { // - reconcile.Request: Mock reconcile request for testing // - context.Context: Test context // - client.Client: Fake Kubernetes client for API interactions -func setupTestEnvironment(isOpenShift bool) (*BpfmanConfigReconciler, *v1alpha1.Config, reconcile.Request, +func setupTestEnvironment(isOpenShift bool, recorder record.EventRecorder) (*BpfmanConfigReconciler, *v1alpha1.Config, reconcile.Request, context.Context, client.Client) { // A configMap for bpfman with metadata and spec. bpfmanConfig := &v1alpha1.Config{ @@ -208,12 +242,15 @@ func setupTestEnvironment(isOpenShift bool) (*BpfmanConfigReconciler, *v1alpha1. s.AddKnownTypes(osv1.GroupVersion, &osv1.SecurityContextConstraints{}) // Create a fake client to mock API calls. - cl := fake.NewClientBuilder().WithRuntimeObjects(objs...).Build() + // For WithStatusSubresource see: + // * https://github.com/kubernetes-sigs/controller-runtime/issues/2362#issuecomment-1837270195 + // * https://stackoverflow.com/questions/77489441/go-k8s-controller-runtime-upgrade-fake-client-lacks-functionality + cl := fake.NewClientBuilder().WithRuntimeObjects(objs...).WithStatusSubresource(bpfmanConfig).Build() // Set development Logger so we can see all logs in tests. logf.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true}))) - rc := ReconcilerCommon[v1alpha1.ClusterBpfApplicationState, v1alpha1.ClusterBpfApplicationStateList]{ + rc := ReconcilerCommon{ Client: cl, Scheme: s, } @@ -230,6 +267,7 @@ func setupTestEnvironment(isOpenShift bool) (*BpfmanConfigReconciler, *v1alpha1. BpfmanMetricsProxyDS: resolveConfigPath(internal.BpfmanMetricsProxyPath), CsiDriverDS: resolveConfigPath(internal.BpfmanCsiDriverPath), IsOpenshift: isOpenShift, + Recorder: recorder, } if isOpenShift { r.RestrictedSCC = resolveConfigPath(internal.BpfmanRestrictedSCCPath) @@ -578,3 +616,139 @@ func verifyCM(cm *corev1.ConfigMap, requiredFields map[string]*string) error { } return nil } + +// testStatusSet validates that the Config's status.conditions and status.componentStatuses +// match the expected state (unknown, progressing, or available) based on the test scenario. +func testStatusSet(ctx context.Context, cl client.Client, configName string, isOpenShift bool, expected string) error { + bpfmanConfig := &v1alpha1.Config{} + if err := cl.Get(ctx, types.NamespacedName{Name: configName}, bpfmanConfig); err != nil { + return err + } + + var expectedComponentStatuses map[string]v1alpha1.ConfigComponentStatus + var progressingCondition metav1.Condition + var availableCondition metav1.Condition + + switch expected { + case "available": + expectedComponentStatuses = map[string]v1alpha1.ConfigComponentStatus{ + "ConfigMap": v1alpha1.ConfigStatusReady, + "DaemonSet": v1alpha1.ConfigStatusReady, + "MetricsProxyDaemonSet": v1alpha1.ConfigStatusReady, + "CsiDriver": v1alpha1.ConfigStatusReady, + } + if isOpenShift { + expectedComponentStatuses["Scc"] = v1alpha1.ConfigStatusReady + } + progressingCondition = metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionFalse, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + } + availableCondition = metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionTrue, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + } + case "progressing": + expectedComponentStatuses = map[string]v1alpha1.ConfigComponentStatus{ + "ConfigMap": v1alpha1.ConfigStatusReady, + "DaemonSet": v1alpha1.ConfigStatusProgressing, + "MetricsProxyDaemonSet": v1alpha1.ConfigStatusProgressing, + "CsiDriver": v1alpha1.ConfigStatusReady, + } + if isOpenShift { + expectedComponentStatuses["Scc"] = v1alpha1.ConfigStatusReady + } + progressingCondition = metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionTrue, + Reason: internal.ConfigReasonProgressing, + Message: internal.ConfigMessageProgressing, + } + availableCondition = metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionFalse, + Reason: internal.ConfigReasonProgressing, + Message: internal.ConfigMessageProgressing, + } + default: + expectedComponentStatuses = map[string]v1alpha1.ConfigComponentStatus{ + "ConfigMap": v1alpha1.ConfigStatusUnknown, + "DaemonSet": v1alpha1.ConfigStatusUnknown, + "MetricsProxyDaemonSet": v1alpha1.ConfigStatusUnknown, + "CsiDriver": v1alpha1.ConfigStatusUnknown, + } + if isOpenShift { + expectedComponentStatuses["Scc"] = v1alpha1.ConfigStatusUnknown + } + progressingCondition = metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionUnknown, + Reason: internal.ConfigReasonUnknown, + Message: internal.ConfigMessageUnknown, + } + availableCondition = metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionUnknown, + Reason: internal.ConfigReasonUnknown, + Message: internal.ConfigMessageUnknown, + } + } + + if bpfmanConfig.Status.Components == nil || + !internal.CCSEquals(bpfmanConfig.Status.Components, expectedComponentStatuses) { + got := fmt.Sprintf("%v", bpfmanConfig.Status.Components) + want := fmt.Sprintf("%v", expectedComponentStatuses) + if b, err := json.Marshal(bpfmanConfig.Status.Components); err == nil { + got = string(b) + } + if b, err := json.Marshal(expectedComponentStatuses); err == nil { + want = string(b) + } + return fmt.Errorf("unexpected config.status.componentStatuses, got: %v, expected: %v", got, want) + } + if !testutil.ContainsCondition(bpfmanConfig.Status.Conditions, progressingCondition) { + return fmt.Errorf("conditions %v does not contain condition %v", + bpfmanConfig.Status.Conditions, progressingCondition) + } + if !testutil.ContainsCondition(bpfmanConfig.Status.Conditions, availableCondition) { + return fmt.Errorf("conditions %v does not contain condition %v", + bpfmanConfig.Status.Conditions, availableCondition) + } + return nil +} + +// testReconcileDaemonSets simulates DaemonSets becoming ready by setting their status +// fields to indicate all desired pods are ready and scheduled. +func testReconcileDaemonSets(ctx context.Context, cl client.Client) error { + bpfmanDs := &appsv1.DaemonSet{} + if err := cl.Get(ctx, types.NamespacedName{Name: internal.BpfmanDsName, Namespace: internal.BpfmanNamespace}, + bpfmanDs); err != nil { + return err + } + bpfmanDs.Status.DesiredNumberScheduled = 1 + bpfmanDs.Status.UpdatedNumberScheduled = bpfmanDs.Status.DesiredNumberScheduled + bpfmanDs.Status.NumberAvailable = bpfmanDs.Status.DesiredNumberScheduled + bpfmanDs.Status.NumberReady = bpfmanDs.Status.DesiredNumberScheduled + if err := cl.Status().Update(ctx, bpfmanDs); err != nil { + return err + } + + metricsProxyDs := &appsv1.DaemonSet{} + if err := cl.Get(ctx, types.NamespacedName{Name: internal.BpfmanMetricsProxyDsName, Namespace: internal.BpfmanNamespace}, + metricsProxyDs); err != nil { + return err + } + metricsProxyDs.Status.DesiredNumberScheduled = 1 + metricsProxyDs.Status.UpdatedNumberScheduled = metricsProxyDs.Status.DesiredNumberScheduled + metricsProxyDs.Status.NumberAvailable = metricsProxyDs.Status.DesiredNumberScheduled + metricsProxyDs.Status.NumberReady = metricsProxyDs.Status.DesiredNumberScheduled + if err := cl.Status().Update(ctx, metricsProxyDs); err != nil { + return err + } + + return nil +} diff --git a/controllers/bpfman-operator/ns_application_program_test.go b/controllers/bpfman-operator/ns_application_program_test.go index 6640b726f..5c9078fb2 100644 --- a/controllers/bpfman-operator/ns_application_program_test.go +++ b/controllers/bpfman-operator/ns_application_program_test.go @@ -137,7 +137,7 @@ func appNsProgramReconcile(t *testing.T, multiCondition bool) { // Create a fake client to mock API calls. cl := fake.NewClientBuilder().WithStatusSubresource(App).WithRuntimeObjects(objs...).Build() - rc := ReconcilerCommon[bpfmaniov1alpha1.BpfApplicationState, bpfmaniov1alpha1.BpfApplicationStateList]{ + rc := ReconcilerCommon{ Client: cl, Scheme: s, } diff --git a/controllers/bpfman-operator/ns_application_programs.go b/controllers/bpfman-operator/ns_application_programs.go index 3810165fa..db0e28eb2 100644 --- a/controllers/bpfman-operator/ns_application_programs.go +++ b/controllers/bpfman-operator/ns_application_programs.go @@ -45,7 +45,7 @@ type BpfNsApplicationReconciler struct { } //lint:ignore U1000 Linter claims function unused, but generics confusing linter -func (r *BpfNsApplicationReconciler) getRecCommon() *ReconcilerCommon[bpfmaniov1alpha1.BpfApplicationState, bpfmaniov1alpha1.BpfApplicationStateList] { +func (r *BpfNsApplicationReconciler) getRecCommon() *ReconcilerCommon { return &r.NamespaceApplicationReconciler.ReconcilerCommon } diff --git a/internal/constants.go b/internal/constants.go index 0b73f83c8..beb58197c 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -48,6 +48,7 @@ const ( BpfmanLogLevel = "bpfman.log.level" BpfmanAgentLogLevel = "bpfman.agent.log.level" BpfmanAgentHealthProbeAddress = "bpfman.agent.healthprobeaddr" + DefaultHealthProbePort = 8175 APIPrefix = "bpfman.io" ) @@ -248,3 +249,14 @@ func (r ReconcileResult) String() string { return fmt.Sprintf("INVALID RECONCILE RESULT (%d)", r) } } + +const ( + ConfigConditionProgressing = "Progressing" + ConfigConditionAvailable = "Available" + ConfigReasonUnknown = "Startup" + ConfigReasonProgressing = "ReconcileStarted" + ConfigReasonAvailable = "ReconcileComplete" + ConfigMessageUnknown = "Unknown state" + ConfigMessageProgressing = "Reconciliation in progress" + ConfigMessageAvailable = "Reconciliation complete" +) diff --git a/internal/k8s.go b/internal/k8s.go index 239236168..02d967849 100644 --- a/internal/k8s.go +++ b/internal/k8s.go @@ -17,6 +17,7 @@ limitations under the License. package internal import ( + "github.com/bpfman/bpfman-operator/apis/v1alpha1" "github.com/go-logr/logr" "k8s.io/client-go/discovery" "sigs.k8s.io/controller-runtime/pkg/event" @@ -86,3 +87,47 @@ func IsOpenShift(client discovery.DiscoveryInterface, setupLog logr.Logger) (boo } return false, nil } + +// CCSEquals compares two map[string]ConfigComponentStatus instances for equality. +func CCSEquals(ccs, c map[string]v1alpha1.ConfigComponentStatus) bool { + if len(ccs) != len(c) { + return false + } + for k, v := range ccs { + if c[k] != v { + return false + } + } + return true +} + +// CCSAnyComponentProgressing returns true if any component is in the Progressing state. +func CCSAnyComponentProgressing(ccs map[string]v1alpha1.ConfigComponentStatus, isOpenShift bool) bool { + requiredComponents := []string{"ConfigMap", "DaemonSet", "MetricsProxyDaemonSet", "CsiDriver"} + if isOpenShift { + requiredComponents = append(requiredComponents, "Scc") + } + + for _, component := range requiredComponents { + if status, ok := ccs[component]; ok && status == v1alpha1.ConfigStatusProgressing { + return true + } + } + return false +} + +// CCSAllComponentsReady returns true if all components are in the Ready state. +func CCSAllComponentsReady(ccs map[string]v1alpha1.ConfigComponentStatus, isOpenShift bool) bool { + requiredComponents := []string{"ConfigMap", "DaemonSet", "MetricsProxyDaemonSet", "CsiDriver"} + if isOpenShift { + requiredComponents = append(requiredComponents, "Scc") + } + + for _, component := range requiredComponents { + status, ok := ccs[component] + if !ok || status != v1alpha1.ConfigStatusReady { + return false + } + } + return true +} diff --git a/test/lifecycle/lifecycle_test.go b/test/lifecycle/lifecycle_test.go index 8435160fd..d5c162e79 100644 --- a/test/lifecycle/lifecycle_test.go +++ b/test/lifecycle/lifecycle_test.go @@ -21,6 +21,7 @@ import ( bpfmaniov1alpha1 "github.com/bpfman/bpfman-operator/apis/v1alpha1" "github.com/bpfman/bpfman-operator/internal" bpfmanHelpers "github.com/bpfman/bpfman-operator/pkg/helpers" + "github.com/bpfman/bpfman-operator/test/testutil" osv1 "github.com/openshift/api/security/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -51,7 +52,7 @@ var ( Spec: v1alpha1.ConfigSpec{ Namespace: "bpfman", Image: "quay.io/bpfman/bpfman:latest", - LogLevel: "bpfman=info", // Changed from debug to info + LogLevel: "bpfman=debug", // Changed from info to debug. Configuration: `[database] max_retries = 35 millisec_delay = 10000 @@ -59,9 +60,8 @@ millisec_delay = 10000 allow_unsigned = true verify_enabled = true`, Agent: v1alpha1.AgentSpec{ - Image: "quay.io/bpfman/bpfman-agent:latest", - LogLevel: "debug", // Changed from info to debug - HealthProbePort: 8175, + Image: "quay.io/bpfman/bpfman-agent:latest", + LogLevel: "debug", // Changed from info to debug. }, }, } @@ -126,10 +126,16 @@ func TestLifecycle(t *testing.T) { }() // Make sure that all resources are there at the start. - t.Logf("Running: TestEnsureResources") + t.Logf("Running: waitForResourceCreation, waitForAvailable and checkResourcesInDesiredState") if err := waitForResourceCreation(ctx); err != nil { t.Fatalf("Failed to ensure resources: %q", err) } + if err := waitForAvailable(ctx, isOpenShift); err != nil { + t.Fatalf("Config never reported status available: %q", err) + } + if err := checkResourcesInDesiredState(ctx); err != nil { + t.Fatalf("Failed to ensure resources: %q", err) + } // Test deleting resources. t.Logf("Running: TestResourceDeletion") @@ -770,3 +776,72 @@ func testConfigStuckDeletion(ctx context.Context, t *testing.T) error { t.Logf("Config stuck deletion test completed successfully") return nil } + +// podHasContainerArg checks if a DaemonSet has the given argument in any of its containers. +func podHasContainerArg(ds *appsv1.DaemonSet, arg string) bool { + for _, container := range ds.Spec.Template.Spec.Containers { + for _, containerArg := range container.Args { + if containerArg == arg { + return true + } + } + } + return false +} + +// waitForAvailable waits until the bpfman Config shows "Available" status conditions, +// indicating that all components are ready and reconciliation is complete. +func waitForAvailable(ctx context.Context, isOpenShift bool) error { + return waitUntilCondition(ctx, func() (bool, error) { + bpfmanConfig := &v1alpha1.Config{} + if err := runtimeClient.Get(ctx, types.NamespacedName{Name: internal.BpfmanConfigName}, bpfmanConfig); err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + progressingCondition := metav1.Condition{ + Type: internal.ConfigConditionProgressing, + Status: metav1.ConditionFalse, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + } + availableCondition := metav1.Condition{ + Type: internal.ConfigConditionAvailable, + Status: metav1.ConditionTrue, + Reason: internal.ConfigReasonAvailable, + Message: internal.ConfigMessageAvailable, + } + if !testutil.ContainsCondition(bpfmanConfig.Status.Conditions, progressingCondition) { + return false, nil + } + if !testutil.ContainsCondition(bpfmanConfig.Status.Conditions, availableCondition) { + return false, nil + } + componentsReady := bpfmanConfig.Status.Components != nil && + internal.CCSAllComponentsReady(bpfmanConfig.Status.Components, isOpenShift) + return componentsReady, nil + }) +} + +// checkResourcesInDesiredState makes sure that all resources are in the desired state. +// Right now, the only implemented validation in this function is a check for the health probe port. +// Returns error if timeout is reached or if context is cancelled. +func checkResourcesInDesiredState(ctx context.Context) error { + // Check DaemonSet is in desired state. + ds := &appsv1.DaemonSet{} + dsKey := types.NamespacedName{Name: internal.BpfmanDsName, Namespace: internal.BpfmanNamespace} + if err := runtimeClient.Get(ctx, dsKey, ds); err != nil && errors.IsNotFound(err) || ds.Status.NumberAvailable == 0 { + return nil + } else if err != nil { + return err + } + + arg := "--health-probe-bind-address=:8175" + // Check that the bpfman DaemonSet has the health probe bind address argument. + if !podHasContainerArg(ds, arg) { + return fmt.Errorf("bpfman DaemonSet missing argument %q", arg) + } + + return nil +} diff --git a/test/testutil/conditions.go b/test/testutil/conditions.go new file mode 100644 index 000000000..ef6898bef --- /dev/null +++ b/test/testutil/conditions.go @@ -0,0 +1,18 @@ +package testutil + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// ContainsCondition checks if the given condition exists in the conditions slice +// by comparing type, status, reason, and message fields. +func ContainsCondition(conditions []metav1.Condition, condition metav1.Condition) bool { + for _, c := range conditions { + if c.Type == condition.Type && + c.Status == condition.Status && + c.Reason == condition.Reason && + c.Message == condition.Message { + return true + } + } + + return false +}