Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
name: "KubeletConfig"
crdName: kubeletconfigs.machineconfiguration.openshift.io
tests:
onCreate:
# LogLevel Boundary Tests
- name: Should be able to set logLevel to 0 (minimum)
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 0
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 0
- name: Should be able to set logLevel to 10 (maximum)
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 10
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 10
- name: Should reject logLevel less than 0
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: -1
expectedError: "Invalid value"
- name: Should reject logLevel greater than 10
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 11
expectedError: "Invalid value"

# TLSSecurityProfile CEL Validation tests
- name: Should allow tlsSecurityProfile with Old type
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Old
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Old
- name: Should allow tlsSecurityProfile with Intermediate type
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Intermediate
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Intermediate
- name: Should allow tlsSecurityProfile with Modern type
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Modern
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Modern
- name: Should allow tlsSecurityProfile with Custom type
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Custom
custom:
ciphers:
- ECDHE-ECDSA-AES128-GCM-SHA256
minTLSVersion: VersionTLS12
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Custom
custom:
ciphers:
- ECDHE-ECDSA-AES128-GCM-SHA256
minTLSVersion: VersionTLS12
- name: Should reject tlsSecurityProfile with invalid type
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Invalid
expectedError: "Unsupported value: \"Invalid\""
# Note: enum validation runs before the CEL validation
- name: Should reject tlsSecurityProfile with Custom type and invalid minTLSVersion
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
type: Custom
custom:
ciphers:
- ECDHE-ECDSA-AES128-GCM-SHA256
minTLSVersion: VersionTLS14
expectedError: "Unsupported value: \"VersionTLS14\""
- name: Should allow tlsSecurityProfile without type field for backward compatibility
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
custom:
ciphers:
- ECDHE-ECDSA-AES128-GCM-SHA256
minTLSVersion: VersionTLS12
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
tlsSecurityProfile:
custom:
ciphers:
- ECDHE-ECDSA-AES128-GCM-SHA256
minTLSVersion: VersionTLS12

onUpdate:
# Ratcheting tests - ensure existing objects with previously valid values can be updated
- name: Should allow updating other fields with a previously valid logLevel outside current range
initialCRDPatches:
- op: remove
path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/logLevel/maximum
- op: remove
path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/logLevel/minimum
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 15
updated: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 15
autoSizingReserved: true
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 15
autoSizingReserved: true
- name: Should allow migrating from invalid logLevel to valid value
initialCRDPatches:
- op: remove
path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/logLevel/maximum
- op: remove
path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/logLevel/minimum
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 15
updated: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 5
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
spec:
logLevel: 5
34 changes: 24 additions & 10 deletions machineconfiguration/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,27 +737,41 @@ type KubeletConfig struct {
Status KubeletConfigStatus `json:"status"`
}

// KubeletConfigSpec defines the desired state of KubeletConfig
// KubeletConfigSpec configures the kubelet running on cluster nodes.
type KubeletConfigSpec struct {
// autoSizingReserved controls whether system-reserved CPU and memory are automatically
// calculated based on each node's installed capacity. When set to true, this prevents node failure
// from resource starvation of system components (kubelet, CRI-O) without manual configuration.
// When omitted, this means the user has no opinion and the platform is left to choose a reasonable default,
// which is subject to change over time. The current default is true for worker nodes and false for control plane nodes.
// When set to false, automatic resource reservation is disabled and manual settings must be configured.
// +optional
AutoSizingReserved *bool `json:"autoSizingReserved,omitempty"`
// logLevel sets the kubelet log verbosity, controlling the amount of detail in kubelet logs.
// Valid values range from 0 (minimal logging) to 10 (maximum verbosity with trace-level detail).
// Higher log levels may impact node performance. When omitted, the platform chooses a reasonable default,
// which is subject to change over time. The current default is 2 (standard informational logging).
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=10
// +optional
LogLevel *int32 `json:"logLevel,omitempty"`

// machineConfigPoolSelector selects which pools the KubeletConfig shoud apply to.
// A nil selector will result in no pools being selected.
// machineConfigPoolSelector selects which pools the KubeletConfig should apply to.
// When omitted or set to an empty selector {}, no pools are selected, which is equivalent
// to not matching any MachineConfigPool.
// +optional
MachineConfigPoolSelector *metav1.LabelSelector `json:"machineConfigPoolSelector,omitempty"`
// kubeletConfig fields are defined in kubernetes upstream. Please refer to the types defined in the version/commit used by
// OpenShift of the upstream kubernetes. It's important to note that, since the fields of the kubelet configuration are directly fetched from
// upstream the validation of those values is handled directly by the kubelet. Please refer to the upstream version of the relevant kubernetes
// for the valid values of these fields. Invalid values of the kubelet configuration fields may render cluster nodes unusable.
// kubeletConfig contains upstream Kubernetes kubelet configuration fields.
// Values are validated by the kubelet itself. Invalid values may render nodes unusable.
// Refer to OpenShift documentation for the Kubernetes version corresponding to your
// OpenShift release to find valid kubelet configuration options.
// +optional
KubeletConfig *runtime.RawExtension `json:"kubeletConfig,omitempty"`

// If unset, the default is based on the apiservers.config.openshift.io/cluster resource.
// Note that only Old and Intermediate profiles are currently supported, and
// the maximum available minTLSVersion is VersionTLS12.
// tlsSecurityProfile configures TLS settings for the kubelet.
// When omitted, the TLS configuration defaults to the value from apiservers.config.openshift.io/cluster.
// When specified, the type field can be set to either "Old", "Intermediate", "Modern", "Custom" or omitted for backward compatibility.
// +kubebuilder:validation:XValidation:rule="!has(self.type) || self.type == 'Old' || self.type == 'Intermediate' || self.type == 'Modern' || self.type == 'Custom'",message="only Old, Intermediate, Modern and Custom TLS profiles are supported for kubelet"
Comment on lines +773 to +774
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are allowing the type to be any of the types that are valid for the TLSSecurityProfile.Type field you probably don't need this validation - the type alias for that field already enforces an enum constraint with these same values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@everettraven Let's say there is a addition to TLSSecurityProfile.Type enum which kubelet doesn't support yet, then we need this validation right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, yes. In practice, this is unlikely. Any changes to the TLSSecurityProfile API will need to go through the feature promotion process which will include ensuring that all components either support the changes or they have been explicitly updated to not handle them prior to the promotion of the field.

// +optional
TLSSecurityProfile *configv1.TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,37 @@ spec:
description: spec contains the desired kubelet configuration.
properties:
autoSizingReserved:
description: |-
autoSizingReserved controls whether system-reserved CPU and memory are automatically
calculated based on each node's installed capacity. When set to true, this prevents node failure
from resource starvation of system components (kubelet, CRI-O) without manual configuration.
When omitted, this means the user has no opinion and the platform is left to choose a reasonable default,
which is subject to change over time. The current default is true for worker nodes and false for control plane nodes.
When set to false, automatic resource reservation is disabled and manual settings must be configured.
type: boolean
kubeletConfig:
description: |-
kubeletConfig fields are defined in kubernetes upstream. Please refer to the types defined in the version/commit used by
OpenShift of the upstream kubernetes. It's important to note that, since the fields of the kubelet configuration are directly fetched from
upstream the validation of those values is handled directly by the kubelet. Please refer to the upstream version of the relevant kubernetes
for the valid values of these fields. Invalid values of the kubelet configuration fields may render cluster nodes unusable.
kubeletConfig contains upstream Kubernetes kubelet configuration fields.
Values are validated by the kubelet itself. Invalid values may render nodes unusable.
Refer to OpenShift documentation for the Kubernetes version corresponding to your
OpenShift release to find valid kubelet configuration options.
type: object
x-kubernetes-preserve-unknown-fields: true
logLevel:
description: |-
logLevel sets the kubelet log verbosity, controlling the amount of detail in kubelet logs.
Valid values range from 0 (minimal logging) to 10 (maximum verbosity with trace-level detail).
Higher log levels may impact node performance. When omitted, the platform chooses a reasonable default,
which is subject to change over time. The current default is 2 (standard informational logging).
format: int32
maximum: 10
minimum: 0
type: integer
machineConfigPoolSelector:
description: |-
machineConfigPoolSelector selects which pools the KubeletConfig shoud apply to.
A nil selector will result in no pools being selected.
machineConfigPoolSelector selects which pools the KubeletConfig should apply to.
When omitted or set to an empty selector {}, no pools are selected, which is equivalent
to not matching any MachineConfigPool.
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
Expand Down Expand Up @@ -109,9 +124,9 @@ spec:
x-kubernetes-map-type: atomic
tlsSecurityProfile:
description: |-
If unset, the default is based on the apiservers.config.openshift.io/cluster resource.
Note that only Old and Intermediate profiles are currently supported, and
the maximum available minTLSVersion is VersionTLS12.
tlsSecurityProfile configures TLS settings for the kubelet.
When omitted, the TLS configuration defaults to the value from apiservers.config.openshift.io/cluster.
When specified, the type field can be set to either "Old", "Intermediate", "Modern", "Custom" or omitted for backward compatibility.
properties:
custom:
description: |-
Expand Down Expand Up @@ -240,6 +255,11 @@ spec:
- Custom
type: string
type: object
x-kubernetes-validations:
- message: only Old, Intermediate, Modern and Custom TLS profiles
are supported for kubelet
rule: '!has(self.type) || self.type == ''Old'' || self.type == ''Intermediate''
|| self.type == ''Modern'' || self.type == ''Custom'''
type: object
status:
description: status contains observed information about the kubelet configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,37 @@ spec:
description: spec contains the desired kubelet configuration.
properties:
autoSizingReserved:
description: |-
autoSizingReserved controls whether system-reserved CPU and memory are automatically
calculated based on each node's installed capacity. When set to true, this prevents node failure
from resource starvation of system components (kubelet, CRI-O) without manual configuration.
When omitted, this means the user has no opinion and the platform is left to choose a reasonable default,
which is subject to change over time. The current default is true for worker nodes and false for control plane nodes.
When set to false, automatic resource reservation is disabled and manual settings must be configured.
type: boolean
kubeletConfig:
description: |-
kubeletConfig fields are defined in kubernetes upstream. Please refer to the types defined in the version/commit used by
OpenShift of the upstream kubernetes. It's important to note that, since the fields of the kubelet configuration are directly fetched from
upstream the validation of those values is handled directly by the kubelet. Please refer to the upstream version of the relevant kubernetes
for the valid values of these fields. Invalid values of the kubelet configuration fields may render cluster nodes unusable.
kubeletConfig contains upstream Kubernetes kubelet configuration fields.
Values are validated by the kubelet itself. Invalid values may render nodes unusable.
Refer to OpenShift documentation for the Kubernetes version corresponding to your
OpenShift release to find valid kubelet configuration options.
type: object
x-kubernetes-preserve-unknown-fields: true
logLevel:
description: |-
logLevel sets the kubelet log verbosity, controlling the amount of detail in kubelet logs.
Valid values range from 0 (minimal logging) to 10 (maximum verbosity with trace-level detail).
Higher log levels may impact node performance. When omitted, the platform chooses a reasonable default,
which is subject to change over time. The current default is 2 (standard informational logging).
format: int32
maximum: 10
minimum: 0
type: integer
machineConfigPoolSelector:
description: |-
machineConfigPoolSelector selects which pools the KubeletConfig shoud apply to.
A nil selector will result in no pools being selected.
machineConfigPoolSelector selects which pools the KubeletConfig should apply to.
When omitted or set to an empty selector {}, no pools are selected, which is equivalent
to not matching any MachineConfigPool.
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
Expand Down Expand Up @@ -110,9 +125,9 @@ spec:
x-kubernetes-map-type: atomic
tlsSecurityProfile:
description: |-
If unset, the default is based on the apiservers.config.openshift.io/cluster resource.
Note that only Old and Intermediate profiles are currently supported, and
the maximum available minTLSVersion is VersionTLS12.
tlsSecurityProfile configures TLS settings for the kubelet.
When omitted, the TLS configuration defaults to the value from apiservers.config.openshift.io/cluster.
When specified, the type field can be set to either "Old", "Intermediate", "Modern", "Custom" or omitted for backward compatibility.
properties:
custom:
description: |-
Expand Down Expand Up @@ -241,6 +256,11 @@ spec:
- Custom
type: string
type: object
x-kubernetes-validations:
- message: only Old, Intermediate, Modern and Custom TLS profiles
are supported for kubelet
rule: '!has(self.type) || self.type == ''Old'' || self.type == ''Intermediate''
|| self.type == ''Modern'' || self.type == ''Custom'''
type: object
status:
description: status contains observed information about the kubelet configuration.
Expand Down
Loading