Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
- **General**: Fix ScaledObject admission webhook to return validation error from `verifyReplicaCount`, preventing invalid ScaledObjects from being created ([#5954](https://github.com/kedacore/keda/issues/5954))
- **General**: Fix ScaledObject Ready condition not reflecting HPA status ([#7649](https://github.com/kedacore/keda/issues/7649))
- **General**: Handle paused scaling directly in reconciler ([#7663](https://github.com/kedacore/keda/issues/7663))
- **General**: Reject ScaledObject creation when name exceeds 54 characters to keep the generated `keda-hpa-` HPA name within the 63-character Kubernetes label value limit ([#6998](https://github.com/kedacore/keda/issues/6998))
- **Azure Data Explorer Scaler**: Remove clientSecretFromEnv support ([#7554](https://github.com/kedacore/keda/pull/7554))
- **Azure Event Hub Scaler**: Reject non-positive `unprocessedEventThreshold` to prevent integer division by zero when computing lag ([#7732](https://github.com/kedacore/keda/issues/7732))
- **Cron Scaler**: Fix metric name generation so cron expressions with comma-separated values no longer produce invalid metric names ([#7448](https://github.com/kedacore/keda/issues/7448))
Expand Down
17 changes: 17 additions & 0 deletions apis/keda/v1alpha1/scaledobject_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ var restMapper meta.RESTMapper
var memoryString = "memory"
var cpuString = "cpu"

// maxScaledObjectNameLength is 63 (the Kubernetes label value limit) minus the length of the "keda-hpa-" prefix that KEDA prepends when generating the HPA name from the ScaledObject name.
const maxScaledObjectNameLength = 54

func (so *ScaledObject) SetupWebhookWithManager(mgr ctrl.Manager, cacheMissFallback bool) error {
err := setupKubernetesClients(mgr, cacheMissFallback)
if err != nil {
Expand Down Expand Up @@ -164,6 +167,7 @@ func validateWorkload(so *ScaledObject, action string, dryRun bool) (admission.W
"verifyHpas": verifyHpas,
"verifyReplicaCount": verifyReplicaCount,
"verifyFallback": verifyFallback,
"verifyName": verifyName,
}

for functionName, function := range verifyFunctions {
Expand Down Expand Up @@ -199,6 +203,19 @@ func verifyReplicaCount(incomingSo *ScaledObject, action string, _ bool) error {
return err
}

func verifyName(incomingSo *ScaledObject, action string, _ bool) error {
if action != "create" {
return nil
}
if len(incomingSo.Name) > maxScaledObjectNameLength {
Comment thread
JorTurFer marked this conversation as resolved.
Outdated
err := fmt.Errorf("scaledobject name %q is %d characters long; must be no more than %d characters to leave room for the %q HPA name prefix within the Kubernetes 63-character label limit", incomingSo.Name, len(incomingSo.Name), maxScaledObjectNameLength, "keda-hpa-")
scaledobjectlog.WithValues("name", incomingSo.Name).Error(err, "validation error")
metricscollector.RecordScaledObjectValidatingErrors(incomingSo.Namespace, action, "name-too-long")
return err
}
return nil
}

func verifyFallback(incomingSo *ScaledObject, action string, _ bool) error {
err := CheckFallbackValid(incomingSo)
if err != nil {
Expand Down
31 changes: 31 additions & 0 deletions apis/keda/v1alpha1/scaledobject_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package v1alpha1

import (
"context"
"strings"
"time"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -732,6 +733,36 @@ var _ = It("should validate the so update if it's removing the finalizer even if
}).ShouldNot(HaveOccurred())
})

var _ = It("shouldn't validate the so creation when the name exceeds 54 characters", func() {

namespaceName := "so-name-too-long"
namespace := createNamespace(namespaceName)
longName := strings.Repeat("a", maxScaledObjectNameLength+1)
so := createScaledObject(longName, namespaceName, workloadName, "apps/v1", "Deployment", false, map[string]string{}, "")

err := k8sClient.Create(context.Background(), namespace)
Expect(err).ToNot(HaveOccurred())

Eventually(func() error {
return k8sClient.Create(context.Background(), so)
}).Should(HaveOccurred())
})

var _ = It("should validate the so creation when the name is exactly 54 characters", func() {

namespaceName := "so-name-max-length"
namespace := createNamespace(namespaceName)
maxName := strings.Repeat("a", maxScaledObjectNameLength)
so := createScaledObject(maxName, namespaceName, workloadName, "apps/v1", "Deployment", false, map[string]string{}, "")

err := k8sClient.Create(context.Background(), namespace)
Expect(err).ToNot(HaveOccurred())

Eventually(func() error {
return k8sClient.Create(context.Background(), so)
}).ShouldNot(HaveOccurred())
})

var _ = It("shouldn't create so when stabilizationWindowSeconds exceeds 3600", func() {

namespaceName := "fail-so-creation"
Expand Down
Loading