From d01f5a21ee415bd1212407a7c5191af94ffc4c74 Mon Sep 17 00:00:00 2001 From: Dhruv Gautam Date: Mon, 24 Aug 2026 19:52:42 +0530 Subject: [PATCH] feat(operator-config): OCPSTRAT-3156 add per-component configurable log levels Introduce OperatorConfiguration in the HostedCluster API so operators can set per-component log verbosity for the control plane components, replacing hardcoded verbosity flags. - Add ComponentLogLevelSpec and LogLevel (Normal/Debug/Trace/TraceAll) with CEL validation and godocs. etcd log levels are restricted to Normal and Debug. - Wire log-level configuration through kube-apiserver, kube-controller-manager, kube-scheduler, openshift-apiserver, openshift-controller-manager, openshift-oauth-apiserver, oauth-server, and etcd deployments. - For kube-apiserver, fall back to the existing verbosity annotation when the API field is unset; the API field takes precedence when both are set. - Add unit tests covering log-level resolution for all components. --- .../featureGate-Hypershift-Default.yaml | 3 + ...eGate-Hypershift-TechPreviewNoUpgrade.yaml | 3 + .../featureGate-SelfManagedHA-Default.yaml | 3 + ...te-SelfManagedHA-TechPreviewNoUpgrade.yaml | 3 + api/hypershift/v1beta1/hostedcluster_types.go | 77 + api/hypershift/v1beta1/operator.go | 68 +- .../v1beta1/zz_generated.deepcopy.go | 151 + ..._generated.featuregated-crd-manifests.yaml | 2 + .../ClusterVersionOperatorConfiguration.yaml | 1 - .../HCPUserFacingOperatorLogs.yaml | 8377 +++++++++++++++++ .../ClusterVersionOperatorConfiguration.yaml | 1 - .../HCPUserFacingOperatorLogs.yaml | 8210 ++++++++++++++++ .../v1beta1/componentloglevelspec.go | 42 + .../hypershift/v1beta1/etcdoperatorspec.go | 42 + .../v1beta1/kubeapiserveroperatorspec.go | 42 + .../kubecontrollermanageroperatorspec.go | 42 + .../v1beta1/kubescheduleroperatorspec.go | 42 + .../v1beta1/oauthserveroperatorspec.go | 42 + .../v1beta1/openshiftapiserveroperatorspec.go | 42 + .../openshiftcontrollermanageroperatorspec.go | 42 + .../openshiftoauthapiserveroperatorspec.go | 42 + .../v1beta1/operatorconfiguration.go | 78 +- client/applyconfiguration/utils.go | 18 + .../featureGate-Hypershift-Default.yaml | 3 + ...eGate-Hypershift-TechPreviewNoUpgrade.yaml | 3 + .../featureGate-SelfManagedHA-Default.yaml | 3 + ...te-SelfManagedHA-TechPreviewNoUpgrade.yaml | 3 + ...sters.operatorconfiguration.testsuite.yaml | 4031 ++++++++ ...usters-Hypershift-CustomNoUpgrade.crd.yaml | 248 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 248 +- ...planes-Hypershift-CustomNoUpgrade.crd.yaml | 248 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 248 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ntrolPlaneComponents_etcd_statefulset.yaml | 4 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...ts_kube_controller_manager_deployment.yaml | 3 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...eComponents_kube_scheduler_deployment.yaml | 4 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...Components_oauth_openshift_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...onents_openshift_apiserver_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ...enshift_controller_manager_deployment.yaml | 3 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- ..._openshift_oauth_apiserver_deployment.yaml | 4 +- .../v2/assets/kube-scheduler/deployment.yaml | 1 - .../openshift-oauth-apiserver/deployment.yaml | 1 - .../hostedcontrolplane/v2/etcd/etcd_test.go | 122 + .../hostedcontrolplane/v2/etcd/statefulset.go | 9 + .../hostedcontrolplane/v2/kas/deployment.go | 32 +- .../v2/kas/deployment_test.go | 209 +- .../hostedcontrolplane/v2/kcm/deployment.go | 9 + .../v2/kcm/deployment_test.go | 156 + .../v2/kube_scheduler/deployment.go | 9 + .../v2/kube_scheduler/deployment_test.go | 174 + .../hostedcontrolplane/v2/oapi/deployment.go | 9 + .../v2/oapi/deployment_test.go | 140 + .../hostedcontrolplane/v2/oauth/deployment.go | 10 + .../v2/oauth/deployment_test.go | 139 + .../v2/oauth_apiserver/deployment.go | 11 + .../v2/oauth_apiserver/deployment_test.go | 136 + .../hostedcontrolplane/v2/ocm/component.go | 1 + .../hostedcontrolplane/v2/ocm/deployment.go | 28 + .../v2/ocm/deployment_test.go | 140 + docs/content/reference/aggregated-docs.md | 461 +- docs/content/reference/api.md | 461 +- support/util/loglevel.go | 42 + support/util/loglevel_test.go | 107 + .../hypershift/v1beta1/hostedcluster_types.go | 77 + .../api/hypershift/v1beta1/operator.go | 68 +- .../v1beta1/zz_generated.deepcopy.go | 151 + ..._generated.featuregated-crd-manifests.yaml | 2 + 101 files changed, 25163 insertions(+), 94 deletions(-) create mode 100644 api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPUserFacingOperatorLogs.yaml create mode 100644 api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HCPUserFacingOperatorLogs.yaml create mode 100644 client/applyconfiguration/hypershift/v1beta1/componentloglevelspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/etcdoperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/kubeapiserveroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/kubecontrollermanageroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/kubescheduleroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/oauthserveroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/openshiftapiserveroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/openshiftcontrollermanageroperatorspec.go create mode 100644 client/applyconfiguration/hypershift/v1beta1/openshiftoauthapiserveroperatorspec.go create mode 100644 cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/featuregated.hostedclusters.operatorconfiguration.testsuite.yaml create mode 100644 control-plane-operator/controllers/hostedcontrolplane/v2/kube_scheduler/deployment_test.go create mode 100644 control-plane-operator/controllers/hostedcontrolplane/v2/ocm/deployment.go create mode 100644 control-plane-operator/controllers/hostedcontrolplane/v2/ocm/deployment_test.go create mode 100644 support/util/loglevel.go create mode 100644 support/util/loglevel_test.go diff --git a/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-Default.yaml b/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-Default.yaml index ed6fe5dc246d..235b43b3b360 100644 --- a/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-Default.yaml +++ b/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-Default.yaml @@ -35,6 +35,9 @@ }, { "name": "EtcdSharding" + }, + { + "name": "HCPUserFacingOperatorLogs" } ], "enabled": [ diff --git a/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml b/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml index 087183961cdf..562d145d958f 100644 --- a/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml +++ b/api/hypershift/v1beta1/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml @@ -54,6 +54,9 @@ }, { "name": "TLSAdherence" + }, + { + "name": "HCPUserFacingOperatorLogs" } ], "version": "" diff --git a/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-Default.yaml b/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-Default.yaml index 9970329f3b4e..32e42f00a53a 100644 --- a/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-Default.yaml +++ b/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-Default.yaml @@ -35,6 +35,9 @@ }, { "name": "EtcdSharding" + }, + { + "name": "HCPUserFacingOperatorLogs" } ], "enabled": [ diff --git a/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml b/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml index 8bd932a41aa2..390c4f924acf 100644 --- a/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml +++ b/api/hypershift/v1beta1/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml @@ -51,6 +51,9 @@ }, { "name": "EtcdSharding" + }, + { + "name": "HCPUserFacingOperatorLogs" } ], "version": "" diff --git a/api/hypershift/v1beta1/hostedcluster_types.go b/api/hypershift/v1beta1/hostedcluster_types.go index b20ea6f8d498..0d303e4767de 100644 --- a/api/hypershift/v1beta1/hostedcluster_types.go +++ b/api/hypershift/v1beta1/hostedcluster_types.go @@ -388,6 +388,9 @@ const ( RecommendedClusterSizeAnnotation = "hypershift.openshift.io/recommended-cluster-size" // KubeAPIServerVerbosityLevelAnnotation allows specifying the log verbosity of kube-apiserver. + // Deprecated: Use spec.operatorConfiguration.kubeAPIServer.logLevel instead. + // When both are set, the OperatorConfiguration field takes precedence. + // This annotation will be removed in a future release. KubeAPIServerVerbosityLevelAnnotation = "hypershift.openshift.io/kube-apiserver-verbosity-level" // NodePoolSupportsKubevirtTopologySpreadConstraintsAnnotation indicates if the NodePool currently supports @@ -2895,6 +2898,80 @@ type OperatorConfiguration struct { // // +optional IngressOperator *IngressOperatorSpec `json:"ingressOperator,omitempty"` + + // kubeAPIServer configures the kube-apiserver component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + KubeAPIServer KubeAPIServerOperatorSpec `json:"kubeAPIServer,omitzero"` + + // etcd configures the etcd component. + // Setting the logLevel field triggers a rolling restart of the component. + // Note: etcd supports fewer log levels than klog-based components, + // etcd supports only Normal and Debug log levels. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + Etcd EtcdOperatorSpec `json:"etcd,omitzero"` + + // kubeControllerManager configures the kube-controller-manager component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + KubeControllerManager KubeControllerManagerOperatorSpec `json:"kubeControllerManager,omitzero"` + + // kubeScheduler configures the kube-scheduler component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + KubeScheduler KubeSchedulerOperatorSpec `json:"kubeScheduler,omitzero"` + + // openShiftControllerManager configures the openshift-controller-manager component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + OpenShiftControllerManager OpenShiftControllerManagerOperatorSpec `json:"openShiftControllerManager,omitzero"` + + // openShiftAPIServer configures the openshift-apiserver component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + OpenShiftAPIServer OpenShiftAPIServerOperatorSpec `json:"openShiftAPIServer,omitzero"` + + // openShiftOAuthAPIServer configures the openshift-oauth-apiserver component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + OpenShiftOAuthAPIServer OpenShiftOAuthAPIServerOperatorSpec `json:"openShiftOAuthAPIServer,omitzero"` + + // oauthServer configures the oauth-server component. + // Setting the logLevel field triggers a rolling restart of the component. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + // +openshift:enable:FeatureGate=HCPUserFacingOperatorLogs + OAuthServer OAuthServerOperatorSpec `json:"oauthServer,omitzero"` } // +genclient diff --git a/api/hypershift/v1beta1/operator.go b/api/hypershift/v1beta1/operator.go index 5c4160fb257a..3980fa37ffc0 100644 --- a/api/hypershift/v1beta1/operator.go +++ b/api/hypershift/v1beta1/operator.go @@ -18,7 +18,7 @@ const ( KubevirtDefaultV4InternalSubnet = "100.66.0.0/16" ) -// +kubebuilder:validation:Enum="";Normal;Debug;Trace;TraceAll +// +kubebuilder:validation:Enum=Normal;Debug;Trace;TraceAll type LogLevel string var ( @@ -40,6 +40,72 @@ var ( TraceAll LogLevel = "TraceAll" ) +// ComponentLogLevelSpec configures the log verbosity for a hosted control plane component. +// +kubebuilder:validation:MinProperties=1 +type ComponentLogLevelSpec struct { + // logLevel sets the log verbosity for the component. + // Valid values are: "Normal", "Debug", "Trace", "TraceAll". + // When set to Normal, standard operational log messages are produced for auditing and common operations. + // When set to Debug, more verbose logging is enabled for diagnosing problems. + // When set to Trace, very verbose logging is enabled including function-level tracing. + // When set to TraceAll, the most verbose logging is used, including full API body content, + // this can cause significant performance impact and produce large volumes of logs. + // When omitted, this means the user has no opinion and the platform + // chooses a reasonable default, which is subject to change over time. + // The current default log level is Normal. + // +optional + LogLevel LogLevel `json:"logLevel,omitempty"` +} + +// KubeAPIServerOperatorSpec specifies the configuration for the Kube API Server. +// +kubebuilder:validation:MinProperties=1 +type KubeAPIServerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// EtcdOperatorSpec specifies the configuration for the etcd. +// +kubebuilder:validation:MinProperties=1 +// +kubebuilder:validation:XValidation:rule="!has(self.logLevel) || self.logLevel in ['Normal', 'Debug']",message="etcd only supports Normal and Debug log levels; Trace and TraceAll are not valid for etcd" +type EtcdOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// KubeControllerManagerOperatorSpec specifies the configuration for the Kube Controller Manager. +// +kubebuilder:validation:MinProperties=1 +type KubeControllerManagerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// KubeSchedulerOperatorSpec specifies the configuration for the Kube Scheduler. +// +kubebuilder:validation:MinProperties=1 +type KubeSchedulerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// OpenShiftControllerManagerOperatorSpec specifies the configuration for the OpenShift Controller Manager. +// +kubebuilder:validation:MinProperties=1 +type OpenShiftControllerManagerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// OpenShiftAPIServerOperatorSpec specifies the configuration for the OpenShift API Server. +// +kubebuilder:validation:MinProperties=1 +type OpenShiftAPIServerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// OpenShiftOAuthAPIServerOperatorSpec specifies the configuration for the OpenShift OAuth API Server. +// +kubebuilder:validation:MinProperties=1 +type OpenShiftOAuthAPIServerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + +// OAuthServerOperatorSpec specifies the configuration for the OAuth Server. +// +kubebuilder:validation:MinProperties=1 +type OAuthServerOperatorSpec struct { + ComponentLogLevelSpec `json:",inline"` +} + // ClusterVersionOperatorSpec is the specification of the desired behavior of the Cluster Version Operator. type ClusterVersionOperatorSpec struct { // operatorLogLevel is an intent based logging for the operator itself. It does not give fine-grained control, diff --git a/api/hypershift/v1beta1/zz_generated.deepcopy.go b/api/hypershift/v1beta1/zz_generated.deepcopy.go index 702745ff3476..ecac3db738d4 100644 --- a/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -1438,6 +1438,21 @@ func (in *ClusterVersionStatus) DeepCopy() *ClusterVersionStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentLogLevelSpec) DeepCopyInto(out *ComponentLogLevelSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentLogLevelSpec. +func (in *ComponentLogLevelSpec) DeepCopy() *ComponentLogLevelSpec { + if in == nil { + return nil + } + out := new(ComponentLogLevelSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentResource) DeepCopyInto(out *ComponentResource) { *out = *in @@ -1743,6 +1758,22 @@ func (in *EncryptionMigrationHistory) DeepCopy() *EncryptionMigrationHistory { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EtcdOperatorSpec) DeepCopyInto(out *EtcdOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EtcdOperatorSpec. +func (in *EtcdOperatorSpec) DeepCopy() *EtcdOperatorSpec { + if in == nil { + return nil + } + out := new(EtcdOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EtcdShardResource) DeepCopyInto(out *EtcdShardResource) { *out = *in @@ -3118,6 +3149,54 @@ func (in *KarpenterConfig) DeepCopy() *KarpenterConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeAPIServerOperatorSpec) DeepCopyInto(out *KubeAPIServerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeAPIServerOperatorSpec. +func (in *KubeAPIServerOperatorSpec) DeepCopy() *KubeAPIServerOperatorSpec { + if in == nil { + return nil + } + out := new(KubeAPIServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeControllerManagerOperatorSpec) DeepCopyInto(out *KubeControllerManagerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeControllerManagerOperatorSpec. +func (in *KubeControllerManagerOperatorSpec) DeepCopy() *KubeControllerManagerOperatorSpec { + if in == nil { + return nil + } + out := new(KubeControllerManagerOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeSchedulerOperatorSpec) DeepCopyInto(out *KubeSchedulerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeSchedulerOperatorSpec. +func (in *KubeSchedulerOperatorSpec) DeepCopy() *KubeSchedulerOperatorSpec { + if in == nil { + return nil + } + out := new(KubeSchedulerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubeVirtNodePoolStatus) DeepCopyInto(out *KubeVirtNodePoolStatus) { *out = *in @@ -4096,6 +4175,22 @@ func (in *NodeVersion) DeepCopy() *NodeVersion { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OAuthServerOperatorSpec) DeepCopyInto(out *OAuthServerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAuthServerOperatorSpec. +func (in *OAuthServerOperatorSpec) DeepCopy() *OAuthServerOperatorSpec { + if in == nil { + return nil + } + out := new(OAuthServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OSImageStreamReference) DeepCopyInto(out *OSImageStreamReference) { *out = *in @@ -4162,6 +4257,54 @@ func (in *OVNKubernetesConfig) DeepCopy() *OVNKubernetesConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftAPIServerOperatorSpec) DeepCopyInto(out *OpenShiftAPIServerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftAPIServerOperatorSpec. +func (in *OpenShiftAPIServerOperatorSpec) DeepCopy() *OpenShiftAPIServerOperatorSpec { + if in == nil { + return nil + } + out := new(OpenShiftAPIServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftControllerManagerOperatorSpec) DeepCopyInto(out *OpenShiftControllerManagerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftControllerManagerOperatorSpec. +func (in *OpenShiftControllerManagerOperatorSpec) DeepCopy() *OpenShiftControllerManagerOperatorSpec { + if in == nil { + return nil + } + out := new(OpenShiftControllerManagerOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftOAuthAPIServerOperatorSpec) DeepCopyInto(out *OpenShiftOAuthAPIServerOperatorSpec) { + *out = *in + out.ComponentLogLevelSpec = in.ComponentLogLevelSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftOAuthAPIServerOperatorSpec. +func (in *OpenShiftOAuthAPIServerOperatorSpec) DeepCopy() *OpenShiftOAuthAPIServerOperatorSpec { + if in == nil { + return nil + } + out := new(OpenShiftOAuthAPIServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenStackIdentityReference) DeepCopyInto(out *OpenStackIdentityReference) { *out = *in @@ -4277,6 +4420,14 @@ func (in *OperatorConfiguration) DeepCopyInto(out *OperatorConfiguration) { *out = new(IngressOperatorSpec) (*in).DeepCopyInto(*out) } + out.KubeAPIServer = in.KubeAPIServer + out.Etcd = in.Etcd + out.KubeControllerManager = in.KubeControllerManager + out.KubeScheduler = in.KubeScheduler + out.OpenShiftControllerManager = in.OpenShiftControllerManager + out.OpenShiftAPIServer = in.OpenShiftAPIServer + out.OpenShiftOAuthAPIServer = in.OpenShiftOAuthAPIServer + out.OAuthServer = in.OAuthServer } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorConfiguration. diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml index 7537bc7ec496..539c03e31904 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml @@ -213,6 +213,7 @@ hostedclusters.hypershift.openshift.io: - ExternalOIDCWithUpstreamParity - GCPPlatform - HCPEtcdBackup + - HCPUserFacingOperatorLogs - HyperShiftOnlyDynamicResourceAllocation - ImageStreamImportMode - IngressComponentRouteLabels @@ -291,6 +292,7 @@ hostedcontrolplanes.hypershift.openshift.io: - ExternalOIDCWithUpstreamParity - GCPPlatform - HCPEtcdBackup + - HCPUserFacingOperatorLogs - HyperShiftOnlyDynamicResourceAllocation - ImageStreamImportMode - IngressComponentRouteLabels diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml index 11ce8337b3c8..7bcf137f3316 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml @@ -3514,7 +3514,6 @@ spec: Valid values are: "Normal", "Debug", "Trace", "TraceAll". Defaults to "Normal". enum: - - "" - Normal - Debug - Trace diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPUserFacingOperatorLogs.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPUserFacingOperatorLogs.yaml new file mode 100644 index 000000000000..790fb5b62c64 --- /dev/null +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPUserFacingOperatorLogs.yaml @@ -0,0 +1,8377 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + feature-gate.release.openshift.io/HCPUserFacingOperatorLogs: "true" + name: hostedclusters.hypershift.openshift.io +spec: + group: hypershift.openshift.io + names: + kind: HostedCluster + listKind: HostedClusterList + plural: hostedclusters + shortNames: + - hc + - hcs + singular: hostedcluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Version + jsonPath: .status.version.history[?(@.state=="Completed")].version + name: Version + type: string + - description: Control Plane Version + jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version + name: CP Version + type: string + - description: KubeConfig Secret + jsonPath: .status.kubeconfig.name + name: KubeConfig + type: string + - description: Progress + jsonPath: .status.version.history[?(@.state!="")].state + name: Progress + type: string + - description: Available + jsonPath: .status.conditions[?(@.type=="Available")].status + name: Available + type: string + - description: Progressing + jsonPath: .status.conditions[?(@.type=="Progressing")].status + name: Progressing + type: string + - description: Message + jsonPath: .status.conditions[?(@.type=="Available")].message + name: Message + type: string + - description: Control Plane Progress + jsonPath: .status.controlPlaneVersion.history[0].state + name: CP Progress + priority: 1 + type: string + - description: Data Plane Progress + jsonPath: .status.version.history[0].state + name: DP Progress + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + HostedCluster is the primary representation of a HyperShift cluster and encapsulates + the control plane and common data plane configuration. Creating a HostedCluster + results in a fully functional OpenShift control plane with no attached nodes. + To support workloads (e.g. pods), a HostedCluster may have one or more associated + NodePool resources. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec is the desired behavior of the HostedCluster. + properties: + additionalTrustBundle: + description: |- + additionalTrustBundle is a local reference to a ConfigMap that must have a "ca-bundle.crt" key + whose content must be a PEM-encoded X.509 certificate bundle that will be added to the hosted controlplane and nodes + If the reference is set but none of the above requirements are met, the HostedCluster will enter a degraded state. + This will be part of every payload generated by the controllers for any NodePool of the HostedCluster. + Changing this value will trigger a rollout for all existing NodePools in the cluster. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + auditWebhook: + description: |- + auditWebhook contains metadata for configuring an audit webhook endpoint + for a cluster to process cluster audit events. It references a secret that + contains the webhook information for the audit webhook endpoint. It is a + secret because if the endpoint has mTLS the kubeconfig will contain client + keys. The kubeconfig needs to be stored in the secret with a secret key + name that corresponds to the constant AuditWebhookKubeconfigKey. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + autoNode: + description: |- + autoNode specifies the configuration for automatic node provisioning and lifecycle management. + When set, the provisioner(e.g. Karpenter) will be used to provision nodes for targeted workloads. + properties: + provisionerConfig: + description: provisionerConfig specifies the provisioner used + for automatic node management. + properties: + karpenter: + description: karpenter specifies the configuration for the + Karpenter provisioner. + properties: + aws: + description: aws specifies the AWS-specific configuration + for Karpenter. + properties: + roleARN: + description: "roleARN specifies the ARN of the IAM + role that Karpenter assumes to provision\nand manage + EC2 instances in the hosted cluster's AWS account.\n\nThe + referenced role must have a trust relationship that + allows it to be assumed\nby the karpenter service + account in the hosted cluster via OIDC.\nExample:\n{\n\t\"Version\": + \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Principal\": {\n\t\t\t\t\"Federated\": + \"\"\n\t\t\t},\n\t\t\t\"Action\": + \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\":sub\": + \"system:serviceaccount:kube-system:karpenter\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n\nThe + following is an example of the policy document for + this role.\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": + [\n\t\t{\n\t\t\t\"Sid\": \"AllowScopedEC2InstanceAccessActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": [\n\t\t\t\t\"arn:*:ec2:*::image/*\",\n\t\t\t\t\"arn:*:ec2:*::snapshot/*\",\n\t\t\t\t\"arn:*:ec2:*:*:security-group/*\",\n\t\t\t\t\"arn:*:ec2:*:*:subnet/*\"\n\t\t\t],\n\t\t\t\"Action\": + [\n\t\t\t\t\"ec2:RunInstances\",\n\t\t\t\t\"ec2:CreateFleet\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedEC2LaunchTemplateAccessActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:ec2:*:*:launch-template/*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"ec2:RunInstances\",\n\t\t\t\t\"ec2:CreateFleet\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedEC2InstanceActionsWithTags\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": [\n\t\t\t\t\"arn:*:ec2:*:*:fleet/*\",\n\t\t\t\t\"arn:*:ec2:*:*:instance/*\",\n\t\t\t\t\"arn:*:ec2:*:*:volume/*\",\n\t\t\t\t\"arn:*:ec2:*:*:network-interface/*\",\n\t\t\t\t\"arn:*:ec2:*:*:launch-template/*\",\n\t\t\t\t\"arn:*:ec2:*:*:spot-instances-request/*\"\n\t\t\t],\n\t\t\t\"Action\": + [\n\t\t\t\t\"ec2:RunInstances\",\n\t\t\t\t\"ec2:CreateFleet\",\n\t\t\t\t\"ec2:CreateLaunchTemplate\"\n\t\t\t],\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringLike\": {\n\t\t\t\t\t\"aws:RequestTag/karpenter.sh/nodepool\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedResourceCreationTagging\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": [\n\t\t\t\t\"arn:*:ec2:*:*:fleet/*\",\n\t\t\t\t\"arn:*:ec2:*:*:instance/*\",\n\t\t\t\t\"arn:*:ec2:*:*:volume/*\",\n\t\t\t\t\"arn:*:ec2:*:*:network-interface/*\",\n\t\t\t\t\"arn:*:ec2:*:*:launch-template/*\",\n\t\t\t\t\"arn:*:ec2:*:*:spot-instances-request/*\"\n\t\t\t],\n\t\t\t\"Action\": + \"ec2:CreateTags\",\n\t\t\t\"Condition\": {\n\t\t\t\t\"StringEquals\": + {\n\t\t\t\t\t\"ec2:CreateAction\": [\n\t\t\t\t\t\t\"RunInstances\",\n\t\t\t\t\t\t\"CreateFleet\",\n\t\t\t\t\t\t\"CreateLaunchTemplate\"\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"StringLike\": + {\n\t\t\t\t\t\"aws:RequestTag/karpenter.sh/nodepool\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedResourceTagging\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:ec2:*:*:instance/*\",\n\t\t\t\"Action\": + \"ec2:CreateTags\",\n\t\t\t\"Condition\": {\n\t\t\t\t\"StringLike\": + {\n\t\t\t\t\t\"aws:ResourceTag/karpenter.sh/nodepool\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedDeletion\",\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Resource\": + [\n\t\t\t\t\"arn:*:ec2:*:*:instance/*\",\n\t\t\t\t\"arn:*:ec2:*:*:launch-template/*\"\n\t\t\t],\n\t\t\t\"Action\": + [\n\t\t\t\t\"ec2:TerminateInstances\",\n\t\t\t\t\"ec2:DeleteLaunchTemplate\"\n\t\t\t],\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringLike\": {\n\t\t\t\t\t\"aws:ResourceTag/karpenter.sh/nodepool\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowRegionalReadActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"ec2:DescribeImages\",\n\t\t\t\t\"ec2:DescribeInstances\",\n\t\t\t\t\"ec2:DescribeInstanceTypeOfferings\",\n\t\t\t\t\"ec2:DescribeInstanceTypes\",\n\t\t\t\t\"ec2:DescribeLaunchTemplates\",\n\t\t\t\t\"ec2:DescribeSecurityGroups\",\n\t\t\t\t\"ec2:DescribeSpotPriceHistory\",\n\t\t\t\t\"ec2:DescribeSubnets\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowSSMReadActions\",\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Resource\": + \"arn:*:ssm:*::parameter/aws/service/*\",\n\t\t\t\"Action\": + \"ssm:GetParameter\"\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowPricingReadActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"*\",\n\t\t\t\"Action\": + \"pricing:GetProducts\"\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowInterruptionQueueActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"sqs:DeleteMessage\",\n\t\t\t\t\"sqs:GetQueueUrl\",\n\t\t\t\t\"sqs:ReceiveMessage\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowPassingInstanceRole\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:iam::*:role/*\",\n\t\t\t\"Action\": + \"iam:PassRole\",\n\t\t\t\"Condition\": {\n\t\t\t\t\"StringEquals\": + {\n\t\t\t\t\t\"iam:PassedToService\": [\n\t\t\t\t\t\t\"ec2.amazonaws.com\",\n\t\t\t\t\t\t\"ec2.amazonaws.com.cn\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedInstanceProfileCreationActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:iam::*:instance-profile/*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"iam:CreateInstanceProfile\"\n\t\t\t],\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringLike\": {\n\t\t\t\t\t\"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedInstanceProfileTagActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:iam::*:instance-profile/*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"iam:TagInstanceProfile\"\n\t\t\t],\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringLike\": {\n\t\t\t\t\t\"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass\": + \"*\",\n\t\t\t\t\t\"aws:RequestTag/karpenter.k8s.aws/ec2nodeclass\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowScopedInstanceProfileActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:iam::*:instance-profile/*\",\n\t\t\t\"Action\": + [\n\t\t\t\t\"iam:AddRoleToInstanceProfile\",\n\t\t\t\t\"iam:RemoveRoleFromInstanceProfile\",\n\t\t\t\t\"iam:DeleteInstanceProfile\"\n\t\t\t],\n\t\t\t\"Condition\": + {\n\t\t\t\t\"StringLike\": {\n\t\t\t\t\t\"aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass\": + \"*\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowInstanceProfileReadActions\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"arn:*:iam::*:instance-profile/*\",\n\t\t\t\"Action\": + \"iam:GetInstanceProfile\"\n\t\t},\n\t\t{\n\t\t\t\"Sid\": + \"AllowUnscopedInstanceProfileListAction\",\n\t\t\t\"Effect\": + \"Allow\",\n\t\t\t\"Resource\": \"*\",\n\t\t\t\"Action\": + \"iam:ListInstanceProfiles\"\n\t\t}\n\t]\n}" + maxLength: 2048 + type: string + x-kubernetes-validations: + - message: roleARN must be a valid AWS IAM role ARN + (e.g. arn:aws:iam::123456789012:role/MyRole) + rule: self.matches('^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role/.+$') + required: + - roleARN + type: object + platform: + description: platform specifies the infrastructure platform + that Karpenter should provision nodes on. + enum: + - AWS + maxLength: 100 + type: string + required: + - platform + type: object + x-kubernetes-validations: + - message: aws is required when platform is AWS, and forbidden + otherwise + rule: 'self.platform == ''AWS'' ? has(self.aws) : !has(self.aws)' + name: + description: name specifies the name of the provisioner to + use for automatic node management. + enum: + - Karpenter + type: string + required: + - name + type: object + x-kubernetes-validations: + - message: karpenter is required when name is Karpenter, and forbidden + otherwise + rule: 'self.name == ''Karpenter'' ? has(self.karpenter) : !has(self.karpenter)' + required: + - provisionerConfig + type: object + autoscaling: + description: |- + autoscaling specifies auto-scaling behavior that applies to all NodePools + associated with this HostedCluster. + properties: + balancingIgnoredLabels: + description: |- + balancingIgnoredLabels sets "--balancing-ignore-label