Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions api/v1alpha1/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ type Features struct {
// +optional
NamespaceScopeEnabled *bool `json:"nssEnabled,omitempty"`

// Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
// real node capacity. Default true.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Node CPU Capping Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch"
// +kubebuilder:default=true
// +optional
NodeCpuCappingEnabled *bool `json:"nodeCpuCappingEnabled,omitempty"`

// Enables the bearer-token / Kubernetes RBAC authentication path on the
// operand (TokenReview + SubjectAccessReview). When nil, defaults to true
// to preserve existing behavior.
// +optional
KubeRBACAuthEnabled *bool `json:"kubeRBACAuthEnabled,omitempty"`
Comment thread
Michal-Szczygiel marked this conversation as resolved.

// Special terms, must be granted by IBM Pricing.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Custom namespaces Config Map",xDescriptors="urn:alm:descriptor:com.tectonic.ui:hidden"
// +optional
Expand All @@ -65,6 +78,13 @@ func (spec *IBMLicensingSpec) IsNamespaceScopeEnabled() bool {
return spec.HaveFeatures() && spec.Features.NamespaceScopeEnabled != nil && *spec.Features.NamespaceScopeEnabled
}

func (spec *IBMLicensingSpec) IsKubeRBACAuthEnabled() bool {
if !spec.HaveFeatures() || spec.Features.KubeRBACAuthEnabled == nil {
return true
}
return *spec.Features.KubeRBACAuthEnabled
}

func (spec *IBMLicensingSpec) IsCustomNamespaceScopeConfigMap() bool {
return spec.HaveFeatures() && spec.Features != nil && spec.Features.CustomNamespaceScopeConfigMap != nil
}
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (spec *IBMLicensingSpec) IsChargebackEnabled() bool {

func (spec *IBMLicensingSpec) IsNodeCpuCappingEnabled() bool {
// Default true: nil treated as enabled.
return spec.NodeCpuCappingEnabled == nil || *spec.NodeCpuCappingEnabled
return spec.Features.NodeCpuCappingEnabled == nil || *spec.Features.NodeCpuCappingEnabled
Comment thread
Michal-Szczygiel marked this conversation as resolved.
Outdated
}

func (container *Container) initResourcesIfNil() {
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ func TestIsNodeCpuCappingEnabledNil(t *testing.T) {
}

func TestIsNodeCpuCappingEnabledExplicitTrue(t *testing.T) {
spec := &IBMLicensingSpec{NodeCpuCappingEnabled: new(true)}
spec := &IBMLicensingSpec{Features: &Features{NodeCpuCappingEnabled: new(true)}}
assert.True(t, spec.IsNodeCpuCappingEnabled(),
"NodeCpuCappingEnabled=true should return true.")
}

func TestIsNodeCpuCappingEnabledExplicitFalse(t *testing.T) {
spec := &IBMLicensingSpec{NodeCpuCappingEnabled: new(false)}
spec := &IBMLicensingSpec{Features: &Features{NodeCpuCappingEnabled: new(false)}}
assert.False(t, spec.IsNodeCpuCappingEnabled(),
"NodeCpuCappingEnabled=false should return false.")
}
10 changes: 10 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ metadata:
categories: Monitoring
certified: "false"
containerImage: icr.io/cpopen/ibm-licensing-operator:4.2.23
createdAt: "2026-05-15T12:42:13Z"
createdAt: "2026-05-29T09:56:04Z"
description: The IBM Licensing Operator provides a Kubernetes CRD-Based API to monitor the license usage of products.
features.operators.openshift.io/disconnected: "true"
features.operators.openshift.io/fips-compliant: "true"
Expand Down Expand Up @@ -224,6 +224,13 @@ spec:
path: features.hyperThreading
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
displayName: Node CPU Capping Enabled
path: features.nodeCpuCappingEnabled
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- description: Special terms, must be granted by IBM Pricing.
displayName: Custom namespaces Config Map
path: features.nssConfigMap
Expand Down
12 changes: 12 additions & 0 deletions bundle/manifests/operator.ibm.com_ibmlicensings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ spec:
required:
- threadsPerCore
type: object
kubeRBACAuthEnabled:
description: |-
Enables the bearer-token / Kubernetes RBAC authentication path on the
operand (TokenReview + SubjectAccessReview). When nil, defaults to true
to preserve existing behavior.
type: boolean
nodeCpuCappingEnabled:
default: true
description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
type: boolean
nssConfigMap:
description: Special terms, must be granted by IBM Pricing.
type: string
Expand Down
12 changes: 12 additions & 0 deletions config/crd/bases/operator.ibm.com_ibmlicensings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ spec:
required:
- threadsPerCore
type: object
kubeRBACAuthEnabled:
description: |-
Enables the bearer-token / Kubernetes RBAC authentication path on the
operand (TokenReview + SubjectAccessReview). When nil, defaults to true
to preserve existing behavior.
type: boolean
nodeCpuCappingEnabled:
default: true
description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
type: boolean
nssConfigMap:
description: Special terms, must be granted by IBM Pricing.
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ spec:
path: features.hyperThreading
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
displayName: Node CPU Capping Enabled
path: features.nodeCpuCappingEnabled
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:booleanSwitch
- description: Special terms, must be granted by IBM Pricing.
displayName: Custom namespaces Config Map
path: features.nssConfigMap
Expand Down
6 changes: 6 additions & 0 deletions controllers/resources/service/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ func getLicensingEnvironmentVariables(spec operatorv1alpha1.IBMLicensingSpec) []
Value: "false",
})
}
if !spec.IsKubeRBACAuthEnabled() {
environmentVariables = append(environmentVariables, corev1.EnvVar{
Name: "KUBE_RBAC_AUTH_ENABLED",
Value: "false",
})
}
if spec.IsPrometheusQuerySourceEnabled() && resources.IsServiceCAAPI {
environmentVariables = append(environmentVariables, corev1.EnvVar{
Name: "PROMETHEUS_QUERY_SOURCE_ENABLED",
Expand Down
63 changes: 57 additions & 6 deletions controllers/resources/service/containers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ func TestGetLicensingEnvironmentVariablesNodeCpuCappingDefault(t *testing.T) {

func TestGetLicensingEnvironmentVariablesNodeCpuCappingExplicitTrue(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
NodeCpuCappingEnabled: ptr.To(true),
InstanceNamespace: "namespace",
Datasource: "datacollector",
Features: &operatorv1alpha1.Features{NodeCpuCappingEnabled: ptr.To(true)},
}

envVars := getLicensingEnvironmentVariables(spec)
Expand All @@ -208,16 +208,67 @@ func TestGetLicensingEnvironmentVariablesNodeCpuCappingExplicitTrue(t *testing.T

func TestGetLicensingEnvironmentVariablesNodeCpuCappingExplicitFalse(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
NodeCpuCappingEnabled: ptr.To(false),
InstanceNamespace: "namespace",
Datasource: "datacollector",
Features: &operatorv1alpha1.Features{NodeCpuCappingEnabled: ptr.To(false)},
}

envVars := getLicensingEnvironmentVariables(spec)
assert.True(t, Contains(envVars, corev1.EnvVar{Name: "NODE_CPU_CAPPING_ENABLED", Value: "false"}),
"NodeCpuCappingEnabled=false, NODE_CPU_CAPPING_ENABLED=false should be added to Licensing pod.")
}

func TestGetLicensingEnvironmentVariablesKubeRBACAuthEnabledFeatureNil(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
}

envVars := getLicensingEnvironmentVariables(spec)
assert.False(t, Contains(envVars, corev1.EnvVar{Name: "KUBE_RBAC_AUTH_ENABLED", Value: "false"}),
"Features is nil, KUBE_RBAC_AUTH_ENABLED should not be added to Licensing pod.")
Comment thread
Michal-Szczygiel marked this conversation as resolved.
Outdated
}

func TestGetLicensingEnvironmentVariablesKubeRBACAuthEnabledPointerNil(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
Features: &operatorv1alpha1.Features{},
}

envVars := getLicensingEnvironmentVariables(spec)
assert.False(t, Contains(envVars, corev1.EnvVar{Name: "KUBE_RBAC_AUTH_ENABLED", Value: "false"}),
"KubeRBACAuthEnabled pointer is nil, KUBE_RBAC_AUTH_ENABLED should not be added to Licensing pod.")
}

func TestGetLicensingEnvironmentVariablesKubeRBACAuthEnabledExplicitTrue(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
Features: &operatorv1alpha1.Features{
KubeRBACAuthEnabled: ptr.To(true),
},
}

envVars := getLicensingEnvironmentVariables(spec)
assert.False(t, Contains(envVars, corev1.EnvVar{Name: "KUBE_RBAC_AUTH_ENABLED", Value: "false"}),
"KubeRBACAuthEnabled=true, KUBE_RBAC_AUTH_ENABLED should not be added to Licensing pod.")
}

func TestGetLicensingEnvironmentVariablesKubeRBACAuthEnabledExplicitFalse(t *testing.T) {
spec := operatorv1alpha1.IBMLicensingSpec{
InstanceNamespace: "namespace",
Datasource: "datacollector",
Features: &operatorv1alpha1.Features{
KubeRBACAuthEnabled: ptr.To(false),
},
}

envVars := getLicensingEnvironmentVariables(spec)
assert.True(t, Contains(envVars, corev1.EnvVar{Name: "KUBE_RBAC_AUTH_ENABLED", Value: "false"}),
"KubeRBACAuthEnabled=false, KUBE_RBAC_AUTH_ENABLED=false should be added to Licensing pod.")
}

func Contains[T comparable](s []T, e T) bool {
for _, v := range s {
if v == e {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,18 @@ spec:
required:
- threadsPerCore
type: object
kubeRBACAuthEnabled:
description: |-
Enables the bearer-token / Kubernetes RBAC authentication path on the
operand (TokenReview + SubjectAccessReview). When nil, defaults to true
to preserve existing behavior.
type: boolean
nodeCpuCappingEnabled:
default: true
description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
type: boolean
nssConfigMap:
description: Special terms, must be granted by IBM Pricing.
type: string
Expand Down Expand Up @@ -483,10 +495,9 @@ spec:
- VERBOSE
type: string
nodeCpuCappingEnabled:
default: true
description: |-
Enables node CPU capping. When false, the operand will skip calls to the Kubernetes node API; node-capping is not applied and metrics may exceed
real node capacity. Default true.
real node capacity. Defaults to true.
Comment thread
NorbertKoziana marked this conversation as resolved.
Outdated
type: boolean
resources:
description: ResourceRequirements describes the compute resource requirements.
Expand Down