From b3937bc083764dfcf0dfac0b0636c46084a28a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Wed, 21 Jan 2026 10:36:30 +0100 Subject: [PATCH 01/12] Add Keda Deployer --- cmd/client.go | 16 +- cmd/completion_util.go | 2 + cmd/deploy.go | 7 +- go.mod | 42 +-- go.sum | 214 +++++++++--- hack/cluster.sh | 28 ++ hack/component-versions.sh | 2 + .../testing/integration_test_helper.go | 52 +++ pkg/keda/client.go | 18 ++ pkg/keda/deployer.go | 306 ++++++++++++++++++ pkg/keda/deployer_int_test.go | 62 ++++ pkg/keda/describer.go | 110 +++++++ pkg/keda/describer_int_test.go | 19 ++ pkg/keda/lister.go | 93 ++++++ pkg/keda/lister_int_test.go | 20 ++ pkg/keda/remover.go | 67 ++++ pkg/keda/remover_int_test.go | 20 ++ pkg/keda/wait.go | 30 ++ 18 files changed, 1035 insertions(+), 73 deletions(-) create mode 100644 pkg/keda/client.go create mode 100644 pkg/keda/deployer.go create mode 100644 pkg/keda/deployer_int_test.go create mode 100644 pkg/keda/describer.go create mode 100644 pkg/keda/describer_int_test.go create mode 100644 pkg/keda/lister.go create mode 100644 pkg/keda/lister_int_test.go create mode 100644 pkg/keda/remover.go create mode 100644 pkg/keda/remover_int_test.go create mode 100644 pkg/keda/wait.go diff --git a/cmd/client.go b/cmd/client.go index 9dea30f629..3c3a1761a6 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -6,6 +6,7 @@ import ( "os" "github.com/ory/viper" + "knative.dev/func/pkg/keda" "knative.dev/func/cmd/prompt" "knative.dev/func/pkg/buildpacks" @@ -68,9 +69,9 @@ func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) { fn.WithRepositoriesPath(config.RepositoriesPath()), fn.WithScaffolder(buildpacks.NewScaffolder(cfg.Verbose)), fn.WithBuilder(buildpacks.NewBuilder(buildpacks.WithVerbose(cfg.Verbose))), - fn.WithRemovers(knative.NewRemover(cfg.Verbose), k8s.NewRemover(cfg.Verbose)), - fn.WithDescribers(knative.NewDescriber(cfg.Verbose), k8s.NewDescriber(cfg.Verbose)), - fn.WithListers(knative.NewLister(cfg.Verbose), k8s.NewLister(cfg.Verbose)), + fn.WithRemovers(knative.NewRemover(cfg.Verbose), k8s.NewRemover(cfg.Verbose), keda.NewRemover(cfg.Verbose)), + fn.WithDescribers(knative.NewDescriber(cfg.Verbose), k8s.NewDescriber(cfg.Verbose), keda.NewDescriber(cfg.Verbose)), + fn.WithListers(knative.NewLister(cfg.Verbose), k8s.NewLister(cfg.Verbose), keda.NewLister(cfg.Verbose)), fn.WithDeployer(d), fn.WithPipelinesProvider(pp), fn.WithPusher(docker.NewPusher( @@ -170,6 +171,15 @@ func newK8sDeployer(verbose bool) fn.Deployer { return k8s.NewDeployer(options...) } +func newKedaDeployer(verbose bool) fn.Deployer { + options := []keda.DeployerOpt{ + keda.WithDeployerVerbose(verbose), + keda.WithDeployerDecorator(deployDecorator{}), + } + + return keda.NewDeployer(options...) +} + type deployDecorator struct { oshDec k8s.OpenshiftMetadataDecorator } diff --git a/cmd/completion_util.go b/cmd/completion_util.go index 43294f111c..cffb092534 100644 --- a/cmd/completion_util.go +++ b/cmd/completion_util.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" fn "knative.dev/func/pkg/functions" "knative.dev/func/pkg/k8s" + "knative.dev/func/pkg/keda" "knative.dev/func/pkg/knative" ) @@ -170,6 +171,7 @@ func CompleteDeployerList(cmd *cobra.Command, args []string, complete string) (m deployers := []string{ knative.KnativeDeployerName, k8s.KubernetesDeployerName, + keda.KedaDeployerName, } d = cobra.ShellCompDirectiveNoFileComp diff --git a/cmd/deploy.go b/cmd/deploy.go index 772fd6162b..59ef85a032 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -18,6 +18,7 @@ import ( "knative.dev/func/pkg/config" fn "knative.dev/func/pkg/functions" "knative.dev/func/pkg/k8s" + "knative.dev/func/pkg/keda" "knative.dev/func/pkg/knative" "knative.dev/func/pkg/utils" ) @@ -195,7 +196,7 @@ EXAMPLES cmd.Flags().String("service-account", f.Deploy.ServiceAccountName, "Service account to be used in the deployed function ($FUNC_SERVICE_ACCOUNT)") cmd.Flags().String("deployer", f.Deploy.Deployer, - fmt.Sprintf("Type of deployment to use: '%s' for Knative Service (default) or '%s' for Kubernetes Deployment ($FUNC_DEPLOY_TYPE)", knative.KnativeDeployerName, k8s.KubernetesDeployerName)) + fmt.Sprintf("Type of deployment to use: '%s' for Knative Service (default), '%s' for Kubernetes Deployment or '%s' for Deployment with a Keda HTTP scaler ($FUNC_DEPLOY_TYPE)", knative.KnativeDeployerName, k8s.KubernetesDeployerName, keda.KedaDeployerName)) // Static Flags: // Options which have static defaults only (not globally configurable nor // persisted with the function) @@ -799,8 +800,10 @@ func (c deployConfig) clientOptions() ([]fn.Option, error) { o = append(o, fn.WithDeployer(newKnativeDeployer(c.Verbose))) case k8s.KubernetesDeployerName: o = append(o, fn.WithDeployer(newK8sDeployer(c.Verbose))) + case keda.KedaDeployerName: + o = append(o, fn.WithDeployer(newKedaDeployer(c.Verbose))) default: - return o, fmt.Errorf("unsupported deploy type: %s (supported: %s, %s)", deployer, knative.KnativeDeployerName, k8s.KubernetesDeployerName) + return o, fmt.Errorf("unsupported deploy type: %s (supported: %s, %s, %s)", deployer, knative.KnativeDeployerName, k8s.KubernetesDeployerName, keda.KedaDeployerName) } return o, nil diff --git a/go.mod b/go.mod index 0478a092d5..c528f548c7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module knative.dev/func -go 1.24.4 +go 1.24.7 // this is required bacause of bad dep in github.com/openshift-pipelines/pipelines-as-code replace github.com/imdario/mergo => dario.cat/mergo v1.0.1 @@ -9,6 +9,10 @@ replace github.com/imdario/mergo => dario.cat/mergo v1.0.1 // Issue: https://github.com/tektoncd/pipeline/issues/8969 replace knative.dev/pkg => knative.dev/pkg v0.0.0-20250716115900-19d3cc2da0b9 +// Override invalid k8s.io/client-go v1.5.2 requirement from keda http-add-on +// keda uses a replace directive internally, but those don't propagate to dependents +replace k8s.io/client-go => k8s.io/client-go v0.34.3 + require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/BurntSushi/toml v1.5.0 @@ -38,6 +42,7 @@ require ( github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/heroku/color v0.0.6 github.com/hinshun/vt10x v0.0.0-20220228203356-1ab2cad5fd82 + github.com/kedacore/http-add-on v0.11.1 github.com/manifestival/client-go-client v0.6.0 github.com/manifestival/manifestival v0.7.2 github.com/modelcontextprotocol/go-sdk v1.1.0 @@ -67,8 +72,9 @@ require ( gotest.tools/v3 v3.5.2 k8s.io/api v0.34.3 k8s.io/apimachinery v0.34.3 - k8s.io/client-go v0.34.3 + k8s.io/client-go v1.5.2 k8s.io/klog/v2 v2.130.1 + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 knative.dev/client/pkg v0.0.0-20260122022411-b55a7dbd440d knative.dev/eventing v0.47.1-0.20260120164810-71a6c9ffdee2 knative.dev/hack v0.0.0-20260120115810-bf6758cba446 @@ -93,7 +99,7 @@ require ( github.com/Azure/go-autorest/logger v0.2.2 // indirect github.com/Azure/go-autorest/tracing v0.6.1 // indirect github.com/GoogleContainerTools/kaniko v1.24.0 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/hcsshim v0.13.0 // indirect github.com/ProtonMail/go-crypto v1.2.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect @@ -148,20 +154,20 @@ require ( github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/gdamore/encoding v1.0.1 // indirect github.com/gdamore/tcell/v2 v2.8.1 // indirect - github.com/go-errors/errors v1.4.2 // indirect + github.com/go-errors/errors v1.5.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect + github.com/go-openapi/jsonpointer v0.21.2 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect @@ -178,6 +184,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b // indirect @@ -203,7 +210,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.9.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect @@ -231,7 +238,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/onsi/gomega v1.37.0 // indirect + github.com/onsi/gomega v1.38.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/runtime-spec v1.2.1 // indirect github.com/opencontainers/selinux v1.12.0 // indirect @@ -243,7 +250,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.4 // indirect + github.com/prometheus/common v1.20.99 // indirect github.com/prometheus/procfs v0.19.2 // indirect github.com/prometheus/statsd_exporter v0.28.0 // indirect github.com/rickb777/date v1.20.2 // indirect @@ -285,28 +292,27 @@ require ( go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect + golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b // indirect golang.org/x/text v0.33.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/time v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/api v0.233.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/grpc v1.77.0 // indirect google.golang.org/protobuf v1.36.10 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect k8s.io/apiextensions-apiserver v0.34.3 // indirect k8s.io/apiserver v0.34.3 // indirect k8s.io/cli-runtime v0.34.1 // indirect - k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 // indirect knative.dev/networking v0.0.0-20260120131110-a7cdca238a0d // indirect - sigs.k8s.io/controller-runtime v0.20.4 // indirect - sigs.k8s.io/gateway-api v1.1.0 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/controller-runtime v0.22.1 // indirect + sigs.k8s.io/gateway-api v1.4.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/kustomize/api v0.20.1 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/go.sum b/go.sum index 4419a0004c..57594f542c 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,7 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -70,11 +71,9 @@ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEK github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= github.com/Azure/go-autorest/autorest v0.11.30 h1:iaZ1RGz/ALZtN5eq4Nr1SOFSlf2E4pDI3Tcsl+dZPVE= github.com/Azure/go-autorest/autorest v0.11.30/go.mod h1:t1kpPIOpIVX7annvothKvb0stsrXa37i7b+xpmBW8Fs= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= github.com/Azure/go-autorest/autorest/adal v0.9.24 h1:BHZfgGsGwdkHDyZdtQRQk1WeUdW0m2WPAwuHZwUi5i4= @@ -104,8 +103,8 @@ github.com/GoogleContainerTools/kaniko v1.24.0 h1:PgzzuOwaraxC7UMw0F0YoxNHi+a6Ye github.com/GoogleContainerTools/kaniko v1.24.0/go.mod h1:hO9q9uGMwrItm4wGcX7E0cMJIw84NM6gPETIt6vkwAk= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -227,9 +226,15 @@ github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiw github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= @@ -341,8 +346,10 @@ github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVo github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -365,13 +372,11 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -391,8 +396,8 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= @@ -424,6 +429,8 @@ github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -434,14 +441,17 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA= +github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -452,6 +462,9 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -566,8 +579,12 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -588,7 +605,8 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -648,6 +666,7 @@ github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439Z github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -678,6 +697,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kedacore/http-add-on v0.11.1 h1:Fhucs6asxvVHWtR8JO/FZVQywbS2Jg8aFNMUV8GpsAo= +github.com/kedacore/http-add-on v0.11.1/go.mod h1:NHcmDJaTRiu7pubf+GnEIJrlyD3EZW4uMR5c/i2ul+g= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= @@ -705,6 +726,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ= github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -728,12 +750,11 @@ github.com/manifestival/manifestival v0.7.2/go.mod h1:nl3T6HlfHCeidooWVTMI9vYNTB github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -838,8 +859,16 @@ github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxm github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= +github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -857,8 +886,16 @@ github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557c github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= -github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= -github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -872,6 +909,7 @@ github.com/openshift-pipelines/pipelines-as-code v0.31.0/go.mod h1:74yRkJfqVzMp2 github.com/openshift/source-to-image v1.5.1 h1:mtV2Nh1jVeLg5S02HIbk3GmGYS912hWCCbASEadAS6M= github.com/openshift/source-to-image v1.5.1/go.mod h1:ZNfsBThrFHlIgkzqz2NyXqAsb8d7eESBiE73zR07BXo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE= github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM= github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M= @@ -932,8 +970,8 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= -github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= +github.com/prometheus/common v1.20.99 h1:vZEybF3CT0t6L0UjsOtHRML7vuIglHocmvJMMH/se4M= +github.com/prometheus/common v1.20.99/go.mod h1:VX44Tebe4qpuTK+MQWg25h4fJGKBqzObSdxuB7y8K/Y= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -971,6 +1009,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1060,6 +1099,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= @@ -1202,6 +1244,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -1219,8 +1263,10 @@ go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1232,19 +1278,27 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1257,8 +1311,9 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA= +golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1295,6 +1350,10 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1360,13 +1419,22 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1387,7 +1455,7 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1409,7 +1477,9 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1487,6 +1557,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1501,18 +1572,29 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1523,14 +1605,23 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1548,21 +1639,27 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1630,9 +1727,18 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1798,6 +1904,10 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1808,8 +1918,9 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -1849,7 +1960,6 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= k8s.io/api v0.27.7/go.mod h1:ZNExI/Lhrs9YrLgVWx6jjHZdoWCTXfBXuFjt1X6olro= -k8s.io/api v0.27.10/go.mod h1:cDmAF4GtSVRO0+5hOY/Vo3lLCQMOp6FfrXZ94/gQwC0= k8s.io/api v0.34.3 h1:D12sTP257/jSH2vHV2EDYrb16bS7ULlHpdNdNhEw2S4= k8s.io/api v0.34.3/go.mod h1:PyVQBF886Q5RSQZOim7DybQjAbVs8g7gwJNhGtY5MBk= k8s.io/apiextensions-apiserver v0.27.7/go.mod h1:x0p+b5a955lfPz9gaDeBy43obM12s+N9dNHK6+dUL+g= @@ -1865,9 +1975,6 @@ k8s.io/apiserver v0.34.3 h1:uGH1qpDvSiYG4HVFqc6A3L4CKiX+aBWDrrsxHYK0Bdo= k8s.io/apiserver v0.34.3/go.mod h1:QPnnahMO5C2m3lm6fPW3+JmyQbvHZQ8uudAu/493P2w= k8s.io/cli-runtime v0.34.1 h1:btlgAgTrYd4sk8vJTRG6zVtqBKt9ZMDeQZo2PIzbL7M= k8s.io/cli-runtime v0.34.1/go.mod h1:aVA65c+f0MZiMUPbseU/M9l1Wo2byeaGwUuQEQVVveE= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/client-go v0.27.7/go.mod h1:dZ2kqcalYp5YZ2EV12XIMc77G6PxHWOJp/kclZr4+5Q= -k8s.io/client-go v0.27.10/go.mod h1:PhrjLdIJNy7L8liOPEzm6wNlMjhIRJeVbfvksTxKNqI= k8s.io/client-go v0.34.3 h1:wtYtpzy/OPNYf7WyNBTj3iUA0XaBHVqhv4Iv3tbrF5A= k8s.io/client-go v0.34.3/go.mod h1:OxxeYagaP9Kdf78UrKLa3YZixMCfP6bgPwPwNBQBzpM= k8s.io/code-generator v0.27.7/go.mod h1:w1YF/xQcTg+d9Ag+04xuRqER+q8rDnJ70ynLql8/RLA= @@ -1875,6 +1982,7 @@ k8s.io/component-base v0.27.7/go.mod h1:YGjlCVL1oeKvG3HSciyPHFh+LCjIEqsxz4BDR3cf k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= @@ -1886,13 +1994,15 @@ k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kms v0.27.7/go.mod h1:JspOc8g6+cDlZfgW5GqnHS+OV6tAVyg4iXytCrqfNPw= k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaCjDbf07wVh6yaUlTpunnkE= +k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= knative.dev/client/pkg v0.0.0-20260122022411-b55a7dbd440d h1:ZJ1Q1ijysBKcJvgQ054u83xkKCbe9N4M2nG/2rfHyFA= knative.dev/client/pkg v0.0.0-20260122022411-b55a7dbd440d/go.mod h1:np5LglGW8pMJzgCefEIVPtI2wgJ9gKfI2CN/GQ5BaL0= knative.dev/eventing v0.47.1-0.20260120164810-71a6c9ffdee2 h1:Qr8E1wNCOs9gOW7fA1HiWI5j+uK5jgofG9A5rJg/3qY= @@ -1910,25 +2020,29 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= sigs.k8s.io/controller-runtime v0.15.3/go.mod h1:kp4jckA4vTx281S/0Yk2LFEEQe67mjg+ev/yknv47Ds= -sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= -sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= -sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= -sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= +sigs.k8s.io/controller-runtime v0.22.1 h1:Ah1T7I+0A7ize291nJZdS1CabF/lB4E++WizgV24Eqg= +sigs.k8s.io/controller-runtime v0.22.1/go.mod h1:FwiwRjkRPbiN+zp2QRp7wlTCzbUXxZ/D4OzuQUDwBHY= +sigs.k8s.io/gateway-api v1.4.0 h1:ZwlNM6zOHq0h3WUX2gfByPs2yAEsy/EenYJB78jpQfQ= +sigs.k8s.io/gateway-api v1.4.0/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v6 v6.2.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/cluster.sh b/hack/cluster.sh index f62579aee5..736b3ef8d2 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -81,6 +81,7 @@ allocate_cluster() { echo "reg: Local Registry" echo "dpr: Dapr Runtime" echo "tkt: Tekton Pipelines" + echo "keda: Keda" echo "" ( set -o pipefail; (serving && dns && networking) 2>&1 | sed -e 's/^/svr /')& @@ -88,6 +89,7 @@ allocate_cluster() { ( set -o pipefail; registry 2>&1 | sed -e 's/^/reg /') & ( set -o pipefail; dapr_runtime 2>&1 | sed -e 's/^/dpr /')& ( set -o pipefail; (tekton && pac) 2>&1 | sed -e 's/^/tkt /')& + ( set -o pipefail; (keda && keda_http_addon) 2>&1 | sed -e 's/^/keda /')& local job for job in $(jobs -p); do @@ -645,6 +647,32 @@ EOF echo "${green}✅ Magic DNS${reset}" } +keda() { + echo "${blue}Installing Keda${reset}" + echo "Version: ${keda_version}" + + $KUBECTL apply --server-side -f https://github.com/kedacore/keda/releases/download/${keda_version}/keda-${keda_version:1}.yaml + $KUBECTL apply --server-side -f https://github.com/kedacore/keda/releases/download/${keda_version}/keda-${keda_version:1}-core.yaml + echo "Waiting for Keda to become ready" + $KUBECTL wait deployment --all --timeout=-1s --for=condition=Available --namespace keda + + $KUBECTL get pod -n keda + echo "${green}✅ Keda${reset}" +} + +keda_http_addon() { + echo "${blue}Installing Keda HTTP add-on${reset}" + echo "Version: ${keda_http_addon_version}" + + $KUBECTL apply --server-side -f https://github.com/kedacore/http-add-on/releases/download/${keda_http_addon_version}/keda-add-ons-http-${keda_http_addon_version:1}-crds.yaml + $KUBECTL apply --server-side -f https://github.com/kedacore/http-add-on/releases/download/${keda_http_addon_version}/keda-add-ons-http-${keda_http_addon_version:1}.yaml + echo "Waiting for Keda HTTP add-on to become ready" + $KUBECTL wait deployment --all --timeout=-1s --for=condition=Available --namespace keda + + $KUBECTL get pod -n keda + echo "${green}✅ Keda HTTP add-on${reset}" +} + next_steps() { echo -e "" echo -e "${blue}Next Steps${reset}" diff --git a/hack/component-versions.sh b/hack/component-versions.sh index 8bc2ebeb96..311a0585c6 100644 --- a/hack/component-versions.sh +++ b/hack/component-versions.sh @@ -16,4 +16,6 @@ set_versions() { contour_version="v1.20.1" tekton_version="v1.1.0" pac_version="v0.35.2" + keda_version="v2.17.0" + keda_http_addon_version="v0.11.1" } diff --git a/pkg/deployer/testing/integration_test_helper.go b/pkg/deployer/testing/integration_test_helper.go index b3bae454ca..83f8286e92 100644 --- a/pkg/deployer/testing/integration_test_helper.go +++ b/pkg/deployer/testing/integration_test_helper.go @@ -18,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/wait" eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + "knative.dev/func/pkg/keda" "knative.dev/func/pkg/knative" "knative.dev/func/pkg/oci" . "knative.dev/func/pkg/testing" @@ -1137,6 +1138,30 @@ func ptr[T interface{}](s T) *T { return &s } +// kedaRoundTripper rewrites requests to go through the KEDA HTTP interceptor-proxy +// while preserving the original Host header for routing +type kedaRoundTripper struct { + transport http.RoundTripper +} + +func (k *kedaRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + // Preserve the original host from the URL + originalHost := req.URL.Host + if originalHost == "" { + originalHost = req.Host + } + + // Rewrite the URL to point to the KEDA interceptor-proxy + // TODO: maybe we can point to the ingress controller here instead + req.URL.Scheme = "http" + req.URL.Host = "keda-add-ons-http-interceptor-proxy.keda.svc:8080" + + // Set the Host header to the original host so KEDA routes correctly + req.Host = originalHost + + return k.transport.RoundTrip(req) +} + func getHttpClient(ctx context.Context, deployer string) (*http.Client, func(), error) { noopDeferFunc := func() {} @@ -1165,6 +1190,33 @@ func getHttpClient(ctx context.Context, deployer string) (*http.Client, func(), case knative.KnativeDeployerName: // For Knative deployments, use default client (service is externally accessible) return http.DefaultClient, noopDeferFunc, nil + case keda.KedaDeployerName: + // For KEDA deployments, route all requests through the KEDA HTTP interceptor-proxy + // The interceptor-proxy routes requests based on the Host header + + clientConfig := k8s.GetClientConfig() + dialer, err := k8s.NewInClusterDialer(ctx, clientConfig) + if err != nil { + return nil, noopDeferFunc, fmt.Errorf("failed to create in-cluster dialer: %w", err) + } + + baseTransport := &http.Transport{ + DialContext: dialer.DialContext, + } + + // Wrap with custom round tripper that rewrites URLs to interceptor-proxy + transport := &kedaRoundTripper{ + transport: baseTransport, + } + + deferFunc := func() { + _ = dialer.Close() + } + + return &http.Client{ + Transport: transport, + Timeout: time.Minute, + }, deferFunc, nil default: return nil, noopDeferFunc, fmt.Errorf("unknown deploy type: %s", deployer) } diff --git a/pkg/keda/client.go b/pkg/keda/client.go new file mode 100644 index 0000000000..06f94642f3 --- /dev/null +++ b/pkg/keda/client.go @@ -0,0 +1,18 @@ +package keda + +import ( + "fmt" + + httpv1alpha1 "github.com/kedacore/http-add-on/operator/generated/clientset/versioned" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "knative.dev/func/pkg/k8s" +) + +func NewHTTPScaledObjectClientset() (*httpv1alpha1.Clientset, error) { + restConfig, err := k8s.GetClientConfig().ClientConfig() + if err != nil { + return nil, fmt.Errorf("failed to create new kubernetes client: %w", err) + } + + return httpv1alpha1.NewForConfig(restConfig) +} diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go new file mode 100644 index 0000000000..6ca3343f1b --- /dev/null +++ b/pkg/keda/deployer.go @@ -0,0 +1,306 @@ +package keda + +import ( + "context" + "fmt" + "time" + + httpv1alpha1 "github.com/kedacore/http-add-on/operator/apis/http/v1alpha1" + "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" + "k8s.io/utils/pointer" + "knative.dev/func/pkg/deployer" + fn "knative.dev/func/pkg/functions" + "knative.dev/func/pkg/k8s" +) + +const ( + KedaDeployerName = "keda" +) + +type DeployerOpt func(*Deployer) + +type Deployer struct { + k8s.Deployer + + verbose bool + decorator deployer.DeployDecorator +} + +func NewDeployer(opts ...DeployerOpt) *Deployer { + d := &Deployer{ + Deployer: *k8s.NewDeployer( + // init with the kedaDeployerDecorator to have the correct deployer labels&annotations + k8s.WithDeployerDecorator(&kedaDeployerDecorator{}), + ), + } + + for _, opt := range opts { + opt(d) + } + return d +} + +func WithDeployerVerbose(verbose bool) DeployerOpt { + return func(d *Deployer) { + d.verbose = verbose + k8s.WithDeployerVerbose(verbose)(&d.Deployer) + } +} + +func WithDeployerDecorator(decorator deployer.DeployDecorator) DeployerOpt { + // use the custom keda decorator, which wrapps the given decorator, + // but with the keda specific annotations + kedaDecorator := &kedaDeployerDecorator{ + wrapper: decorator, + } + + return func(d *Deployer) { + d.decorator = kedaDecorator + k8s.WithDeployerDecorator(kedaDecorator)(&d.Deployer) + } +} + +var _ deployer.DeployDecorator = &kedaDeployerDecorator{} + +type kedaDeployerDecorator struct { + wrapper deployer.DeployDecorator +} + +func (k *kedaDeployerDecorator) UpdateAnnotations(function fn.Function, annotations map[string]string) map[string]string { + if k.wrapper != nil { + annotations = k.wrapper.UpdateAnnotations(function, annotations) + } + + // set correct deployer name + annotations[deployer.DeployerNameAnnotation] = KedaDeployerName + + return annotations +} + +func (k *kedaDeployerDecorator) UpdateLabels(function fn.Function, labels map[string]string) map[string]string { + if k.wrapper != nil { + labels = k.wrapper.UpdateLabels(function, labels) + } + + return labels +} + +func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResult, error) { + // execute raw deployment deployer + deployResult, err := d.Deployer.Deploy(ctx, f) + if err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to deploy function via raw deployer: %w", err) + } + + // create additional required keda resources + namespace := deployResult.Namespace + + k8sClientset, err := k8s.NewKubernetesClientset() + if err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to create K8sClientset: %v", err) + } + + deployment, err := k8sClientset.AppsV1().Deployments(namespace).Get(ctx, f.Name, metav1.GetOptions{}) + if err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to get deployment %s/%s: %v", namespace, f.Name, err) + } + + appService, err := k8sClientset.CoreV1().Services(namespace).Get(ctx, f.Name, metav1.GetOptions{}) + if err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to get service %s/%s: %v", namespace, f.Name, err) + } + + if err := d.ensureInterceptorProxyService(ctx, k8sClientset, f, namespace); err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to ensure proxy service exists: %w", err) + } + + hosts := []string{ + fmt.Sprintf("%s-interceptor-proxy.%s.svc", f.Name, namespace), + fmt.Sprintf("%s-interceptor-proxy", f.Name), + } + + if err := d.ensureHTTPScaledObject(ctx, f, namespace, deployment, appService, hosts); err != nil { + return fn.DeploymentResult{}, fmt.Errorf("failed to ensure http scaled object exists: %w", err) + } + + return fn.DeploymentResult{ + Status: deployResult.Status, + URL: fmt.Sprintf("http://%s:8080", hosts[0]), // TODO: check on HTTPS too + Namespace: deployResult.Namespace, + }, nil +} + +func (d *Deployer) httpScaledObject(f fn.Function, namespace string, deployment *v1.Deployment, service *corev1.Service, hosts []string) (*httpv1alpha1.HTTPScaledObject, error) { + labels, err := deployer.GenerateCommonLabels(f, d.decorator) + if err != nil { + return nil, fmt.Errorf("failed to generate common labels: %w", err) + } + + annotations := deployer.GenerateCommonAnnotations(f, d.decorator, false /*we don't care about dapr for the HttpScaledObject*/, KedaDeployerName) + + minScale := pointer.Int32(1) + maxScale := pointer.Int32(10) + if scaleOptions := f.Deploy.Options.Scale; scaleOptions != nil { + if scaleOptions.Min != nil { + minScale = pointer.Int32(int32(*scaleOptions.Min)) + } + if scaleOptions.Max != nil { + maxScale = pointer.Int32(int32(*scaleOptions.Max)) + } + } + + return &httpv1alpha1.HTTPScaledObject{ + ObjectMeta: metav1.ObjectMeta{ + Name: f.Name, + Namespace: namespace, + Labels: labels, + Annotations: annotations, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "apps/v1", + Kind: "Deployment", + Name: deployment.Name, + UID: deployment.UID, + Controller: pointer.Bool(true), + }, + }, + }, + Spec: httpv1alpha1.HTTPScaledObjectSpec{ + Hosts: hosts, + ScaleTargetRef: httpv1alpha1.ScaleTargetRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: deployment.Name, + Service: service.Name, + Port: service.Spec.Ports[0].Port, + }, + Replicas: &httpv1alpha1.ReplicaStruct{ + Min: minScale, + Max: maxScale, + }, + CooldownPeriod: pointer.Int32(300), + ScalingMetric: &httpv1alpha1.ScalingMetricSpec{ + Rate: &httpv1alpha1.RateMetricSpec{ + TargetValue: 100, + Window: metav1.Duration{ + Duration: time.Minute, + }, + Granularity: metav1.Duration{ + Duration: time.Second, + }, + }, + }, + }, + }, nil +} + +func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *corev1.Service { + return &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-interceptor-proxy", f.Name), + Namespace: namespace, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeExternalName, + ExternalName: fmt.Sprintf("keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local"), // TODO: check for real cluster domain + Ports: []corev1.ServicePort{ + { + Protocol: "TCP", + Port: 8080, // ExternalName services don't do port translation, so this must match kedas interceptors port + TargetPort: intstr.IntOrString{ + IntVal: 8080, + }, + }, + }, + }, + } +} + +func (d *Deployer) ensureInterceptorProxyService(ctx context.Context, clientset *kubernetes.Clientset, f fn.Function, namespace string) error { + expected := d.interceptorProxyService(f, namespace) + existing, err := clientset.CoreV1().Services(expected.Namespace).Get(ctx, expected.Name, metav1.GetOptions{}) + if err != nil { + if k8serrors.IsNotFound(err) { + if _, err := clientset.CoreV1().Services(expected.Namespace).Create(ctx, expected, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create interceptor bridge service: %w", err) + } + + return nil + } + + return fmt.Errorf("failed to get interceptor bridge service: %w", err) + } + + // check if we need to update + if !equality.Semantic.DeepEqual(existing.Spec, expected.Spec) { + // Preserve resource version for update + expected.ResourceVersion = existing.ResourceVersion + + if _, err = clientset.CoreV1().Services(namespace).Update(ctx, expected, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update bridge service: %w", err) + } + + return nil + } + + return nil +} + +func (d *Deployer) ensureHTTPScaledObject(ctx context.Context, f fn.Function, namespace string, deployment *v1.Deployment, service *corev1.Service, hosts []string) error { + expected, err := d.httpScaledObject(f, namespace, deployment, service, hosts) + if err != nil { + return fmt.Errorf("failed to generate http scaled object: %w", err) + } + + httpScaledObjectClientset, err := NewHTTPScaledObjectClientset() + if err != nil { + fmt.Errorf("failed to create HTTPScaledObject clientset: %v", err) + } + + existing, err := httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(expected.Namespace).Get(ctx, expected.Name, metav1.GetOptions{}) + if err != nil { + if k8serrors.IsNotFound(err) { + if _, err := httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(expected.Namespace).Create(ctx, expected, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create HTTPScaledObject: %w", err) + } + + if err := WaitForHTTPScaledObjectAvailable(ctx, httpScaledObjectClientset, namespace, expected.Name, k8s.DefaultWaitingTimeout); err != nil { + return fmt.Errorf("HTTPScaledObject did not become ready: %w", err) + } + + return nil + } + + return fmt.Errorf("failed to get HTTPScaledObject: %w", err) + } + + // check if we need to update + if !equality.Semantic.DeepEqual(existing.Spec, expected.Spec) { + // Preserve resource version for update + expected.ResourceVersion = existing.ResourceVersion + + if _, err = httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(expected.Namespace).Update(ctx, expected, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update HTTPScaledObject: %w", err) + } + + if err := WaitForHTTPScaledObjectAvailable(ctx, httpScaledObjectClientset, namespace, expected.Name, k8s.DefaultWaitingTimeout); err != nil { + return fmt.Errorf("HTTPScaledObject did not become ready: %w", err) + } + + return nil + } + + return nil +} + +func UsesKedaDeployer(annotations map[string]string) bool { + deployer, ok := annotations[deployer.DeployerNameAnnotation] + + return ok && deployer == KedaDeployerName +} diff --git a/pkg/keda/deployer_int_test.go b/pkg/keda/deployer_int_test.go new file mode 100644 index 0000000000..5d7881bef3 --- /dev/null +++ b/pkg/keda/deployer_int_test.go @@ -0,0 +1,62 @@ +//go:build integration +// +build integration + +package keda_test + +import ( + "testing" + + deployertesting "knative.dev/func/pkg/deployer/testing" + "knative.dev/func/pkg/keda" +) + +func TestInt_FullPath(t *testing.T) { + deployertesting.TestInt_FullPath(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewLister(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} + +func TestInt_Deploy(t *testing.T) { + deployertesting.TestInt_Deploy(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} + +func TestInt_Metadata(t *testing.T) { + deployertesting.TestInt_Metadata(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} + +func TestInt_Events(t *testing.T) { + t.Skip("Keda deployer does not support func subscribe yet") + + deployertesting.TestInt_Events(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} + +func TestInt_Scale(t *testing.T) { + deployertesting.TestInt_Scale(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} + +func TestInt_EnvsUpdate(t *testing.T) { + deployertesting.TestInt_EnvsUpdate(t, + keda.NewDeployer(keda.WithDeployerVerbose(false)), + keda.NewRemover(false), + keda.NewDescriber(false), + keda.KedaDeployerName) +} diff --git a/pkg/keda/describer.go b/pkg/keda/describer.go new file mode 100644 index 0000000000..30ffb97899 --- /dev/null +++ b/pkg/keda/describer.go @@ -0,0 +1,110 @@ +package keda + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fn "knative.dev/func/pkg/functions" + "knative.dev/func/pkg/k8s" +) + +type Describer struct { + verbose bool +} + +func NewDescriber(verbose bool) *Describer { + return &Describer{ + verbose: verbose, + } +} + +// Describe a function by name. +func (d *Describer) Describe(ctx context.Context, name, namespace string) (fn.Instance, error) { + if namespace == "" { + return fn.Instance{}, fmt.Errorf("function namespace is required when describing %q", name) + } + + clientset, err := k8s.NewKubernetesClientset() + if err != nil { + return fn.Instance{}, fmt.Errorf("unable to create k8s client: %v", err) + } + + serviceClient := clientset.CoreV1().Services(namespace) + + service, err := serviceClient.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + // Service doesn't exist - we don't handle this + return fn.Instance{}, fn.ErrNotHandled + } + + // Other errors (permissions, network, etc.) - real error + return fn.Instance{}, fmt.Errorf("failed to check if service uses keda deployer: %w", err) + } + + if !UsesKedaDeployer(service.Annotations) { + return fn.Instance{}, fn.ErrNotHandled + } + + // We're responsible, for this function --> proceed... + + httpScaledObjectClientset, err := NewHTTPScaledObjectClientset() + if err != nil { + return fn.Instance{}, fmt.Errorf("unable to create HTTPScaledObject client: %v", err) + } + + httpScaledObject, err := httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return fn.Instance{}, fmt.Errorf("unable to get HTTPScaledObject: %w", err) + } + + if len(httpScaledObject.Spec.Hosts) == 0 { + return fn.Instance{}, fmt.Errorf("HTTPScaledObject %q does not have any hosts", name) + } + + routes := make([]string, 0, len(httpScaledObject.Spec.Hosts)) + for _, host := range httpScaledObject.Spec.Hosts { + routes = append(routes, fmt.Sprintf("http://%s:8080", host)) + } + primaryRouteURL := routes[0] + + deploymentClient := clientset.AppsV1().Deployments(namespace) + deployment, err := deploymentClient.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return fn.Instance{}, fmt.Errorf("unable to get deployment %q: %v", name, err) + } + + // get image + image := "" + for _, container := range deployment.Spec.Template.Spec.Containers { + if container.Name == "user-container" { + image = container.Image + } + } + + middlewareVersion := "" + if image != "" { + v, err := fn.MiddlewareVersion(image) + if err == nil { + // don't fail on errors + middlewareVersion = v + } + } + + description := fn.Instance{ + Name: name, + Namespace: namespace, + Deployer: KedaDeployerName, + Labels: deployment.Labels, + Route: primaryRouteURL, + Routes: routes, + Image: image, + Middleware: fn.Middleware{ + Version: middlewareVersion, + }, + } + + return description, nil +} diff --git a/pkg/keda/describer_int_test.go b/pkg/keda/describer_int_test.go new file mode 100644 index 0000000000..3e90e8df2a --- /dev/null +++ b/pkg/keda/describer_int_test.go @@ -0,0 +1,19 @@ +//go:build integration +// +build integration + +package keda_test + +import ( + "testing" + + describertesting "knative.dev/func/pkg/describer/testing" + keda "knative.dev/func/pkg/keda" +) + +func TestInt_Describe(t *testing.T) { + describertesting.TestInt_Describe(t, + keda.NewDescriber(true), + keda.NewDeployer(keda.WithDeployerVerbose(true)), + keda.NewRemover(true), + keda.KedaDeployerName) +} diff --git a/pkg/keda/lister.go b/pkg/keda/lister.go new file mode 100644 index 0000000000..25bff5d9b2 --- /dev/null +++ b/pkg/keda/lister.go @@ -0,0 +1,93 @@ +package keda + +import ( + "context" + "fmt" + + "github.com/kedacore/http-add-on/operator/generated/clientset/versioned" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fn "knative.dev/func/pkg/functions" + "knative.dev/func/pkg/k8s" +) + +type Lister struct { + verbose bool +} + +func NewLister(verbose bool) fn.Lister { + return &Lister{ + verbose: verbose, + } +} + +func (l *Lister) List(ctx context.Context, namespace string) ([]fn.ListItem, error) { + clientset, err := k8s.NewKubernetesClientset() + if err != nil { + return nil, fmt.Errorf("unable to create k8s client: %v", err) + } + + httpScaledObjectClientset, err := NewHTTPScaledObjectClientset() + if err != nil { + return nil, fmt.Errorf("unable to create HTTPScaledObject client: %v", err) + } + + serviceClient := clientset.CoreV1().Services(namespace) + + services, err := serviceClient.List(ctx, metav1.ListOptions{ + LabelSelector: "function.knative.dev/name", + }) + if err != nil { + return nil, fmt.Errorf("unable to list services: %v", err) + } + + listItems := make([]fn.ListItem, 0, len(services.Items)) + for _, service := range services.Items { + if !UsesKedaDeployer(service.Annotations) { + continue + } + + item, err := l.get(ctx, httpScaledObjectClientset, service.Name, namespace) + if err != nil { + return nil, fmt.Errorf("unable to get details about function: %v", err) + } + + listItems = append(listItems, item) + } + + return listItems, nil +} + +// Get a function, optionally specifying a namespace. +func (l *Lister) get(ctx context.Context, httpScaledObjectClientset *versioned.Clientset, name, namespace string) (fn.ListItem, error) { + httpScaledObject, err := httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return fn.ListItem{}, fmt.Errorf("unable to get HTTPScaledObject: %v", err) + } + + ready := v1.ConditionUnknown + // HTTPScaledObject may have multiple Ready conditions, we need to find one that is True + // TODO: use Status.Conditions.GetReadyCondition() as soon as this is fixed in http-add-on + for _, condition := range httpScaledObject.Status.Conditions { + if condition.Type == "Ready" && condition.Status == "True" { + ready = v1.ConditionTrue + } + } + + url := "" + if len(httpScaledObject.Spec.Hosts) > 0 { + url = fmt.Sprintf("http://%s:8080", httpScaledObject.Spec.Hosts[0]) + } + + runtimeLabel := "" + listItem := fn.ListItem{ + Name: name, + Namespace: namespace, + Runtime: runtimeLabel, + URL: url, + Ready: string(ready), + Deployer: KedaDeployerName, + } + + return listItem, nil +} diff --git a/pkg/keda/lister_int_test.go b/pkg/keda/lister_int_test.go new file mode 100644 index 0000000000..2a83d3daac --- /dev/null +++ b/pkg/keda/lister_int_test.go @@ -0,0 +1,20 @@ +//go:build integration +// +build integration + +package keda_test + +import ( + "testing" + + "knative.dev/func/pkg/keda" + listertesting "knative.dev/func/pkg/lister/testing" +) + +func TestInt_List(t *testing.T) { + listertesting.TestInt_List(t, + keda.NewLister(true), + keda.NewDeployer(keda.WithDeployerVerbose(true)), + keda.NewDescriber(true), + keda.NewRemover(true), + keda.KedaDeployerName) +} diff --git a/pkg/keda/remover.go b/pkg/keda/remover.go new file mode 100644 index 0000000000..097d020856 --- /dev/null +++ b/pkg/keda/remover.go @@ -0,0 +1,67 @@ +package keda + +import ( + "context" + "fmt" + "os" + + apiErrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + fn "knative.dev/func/pkg/functions" + "knative.dev/func/pkg/k8s" +) + +func NewRemover(verbose bool) *Remover { + return &Remover{ + verbose: verbose, + } +} + +type Remover struct { + verbose bool +} + +func (remover *Remover) Remove(ctx context.Context, name, ns string) error { + if ns == "" { + fmt.Fprintf(os.Stderr, "no namespace defined when trying to delete a function in keda remover\n") + return fn.ErrNamespaceRequired + } + + clientset, err := k8s.NewKubernetesClientset() + if err != nil { + return fmt.Errorf("could not setup kubernetes clientset: %w", err) + } + + serviceClient := clientset.CoreV1().Services(ns) + svc, err := serviceClient.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + if apiErrors.IsNotFound(err) { + // Service doesn't exist - we don't handle this + return fn.ErrNotHandled + } + return err + } + + if !UsesKedaDeployer(svc.Annotations) { + return fn.ErrNotHandled + } + + // We're responsible, for this function --> proceed... + + deploymentClient := clientset.AppsV1().Deployments(ns) + + // delete only the deployment and let the api server handle the others via the owner reference + err = deploymentClient.Delete(ctx, name, metav1.DeleteOptions{}) + if err != nil { + if apiErrors.IsNotFound(err) { + return fn.ErrFunctionNotFound + } + return fmt.Errorf("keda remover failed to delete the deployment: %v", err) + } + + if err := k8s.WaitForServiceRemoved(ctx, clientset, ns, name, k8s.DefaultWaitingTimeout); err != nil { + return fmt.Errorf("k8s remover failed to propagate service deletion: %v", err) + } + + return nil +} diff --git a/pkg/keda/remover_int_test.go b/pkg/keda/remover_int_test.go new file mode 100644 index 0000000000..7d52b39e86 --- /dev/null +++ b/pkg/keda/remover_int_test.go @@ -0,0 +1,20 @@ +//go:build integration +// +build integration + +package keda_test + +import ( + "testing" + + "knative.dev/func/pkg/keda" + removertesting "knative.dev/func/pkg/remover/testing" +) + +func TestInt_Remove(t *testing.T) { + removertesting.TestInt_Remove(t, + keda.NewRemover(true), + keda.NewDeployer(keda.WithDeployerVerbose(true)), + keda.NewDescriber(true), + keda.NewLister(true), + keda.KedaDeployerName) +} diff --git a/pkg/keda/wait.go b/pkg/keda/wait.go new file mode 100644 index 0000000000..a4f1a4673e --- /dev/null +++ b/pkg/keda/wait.go @@ -0,0 +1,30 @@ +package keda + +import ( + "context" + "fmt" + "time" + + "github.com/kedacore/http-add-on/operator/generated/clientset/versioned" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +func WaitForHTTPScaledObjectAvailable(ctx context.Context, clientset *versioned.Clientset, namespace string, name string, timeout time.Duration) error { + return wait.PollUntilContextTimeout(ctx, 1*time.Second, timeout, true, func(ctx context.Context) (bool, error) { + httpScaledObject, err := clientset.HttpV1alpha1().HTTPScaledObjects(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return false, fmt.Errorf("error getting http scaled object: %w", err) + } + + // Check if any Ready condition has status True + // HTTPScaledObject may have multiple Ready conditions, we need to find one that is True + // TODO: use Status.Conditions.GetReadyCondition() as soon as this is fixed in http-add-on + for _, condition := range httpScaledObject.Status.Conditions { + if condition.Type == "Ready" && condition.Status == "True" { + return true, nil + } + } + return false, nil + }) +} From e0fcca97ac0351e65be78f338ed8648617088704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Thu, 22 Jan 2026 14:56:18 +0100 Subject: [PATCH 02/12] Run hack/update-codegen.sh --- docs/reference/func_deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/func_deploy.md b/docs/reference/func_deploy.md index 2769a21fd8..5fd45cbfde 100644 --- a/docs/reference/func_deploy.md +++ b/docs/reference/func_deploy.md @@ -119,7 +119,7 @@ func deploy -b, --builder string Builder to use when creating the function's container. Currently supported builders are "host", "pack" and "s2i". (default "pack") --builder-image string Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) -c, --confirm Prompt to confirm options interactively ($FUNC_CONFIRM) - --deployer string Type of deployment to use: 'knative' for Knative Service (default) or 'raw' for Kubernetes Deployment ($FUNC_DEPLOY_TYPE) + --deployer string Type of deployment to use: 'knative' for Knative Service (default), 'raw' for Kubernetes Deployment or 'keda' for Deployment with a Keda HTTP scaler ($FUNC_DEPLOY_TYPE) --domain string Domain to use for the function's route. Cluster must be configured with domain matching for the given domain (ignored if unrecognized) ($FUNC_DOMAIN) -e, --env stringArray Environment variable to set in the form NAME=VALUE. You may provide this flag multiple times for setting multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-). -t, --git-branch string Git revision (branch) to be used when deploying via the Git repository ($FUNC_GIT_BRANCH) From a12ae9082456eaaf684cb21a7ac03900b57a1431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Thu, 22 Jan 2026 14:57:01 +0100 Subject: [PATCH 03/12] Fix linter issues --- pkg/keda/deployer.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index 6ca3343f1b..3cec6b7d96 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -6,14 +6,14 @@ import ( "time" httpv1alpha1 "github.com/kedacore/http-add-on/operator/apis/http/v1alpha1" - "k8s.io/api/apps/v1" + v1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" "knative.dev/func/pkg/deployer" fn "knative.dev/func/pkg/functions" "knative.dev/func/pkg/k8s" @@ -144,14 +144,14 @@ func (d *Deployer) httpScaledObject(f fn.Function, namespace string, deployment annotations := deployer.GenerateCommonAnnotations(f, d.decorator, false /*we don't care about dapr for the HttpScaledObject*/, KedaDeployerName) - minScale := pointer.Int32(1) - maxScale := pointer.Int32(10) + minScale := int32(1) + maxScale := int32(10) if scaleOptions := f.Deploy.Options.Scale; scaleOptions != nil { if scaleOptions.Min != nil { - minScale = pointer.Int32(int32(*scaleOptions.Min)) + minScale = int32(*scaleOptions.Min) } if scaleOptions.Max != nil { - maxScale = pointer.Int32(int32(*scaleOptions.Max)) + maxScale = int32(*scaleOptions.Max) } } @@ -167,7 +167,7 @@ func (d *Deployer) httpScaledObject(f fn.Function, namespace string, deployment Kind: "Deployment", Name: deployment.Name, UID: deployment.UID, - Controller: pointer.Bool(true), + Controller: ptr.To(true), }, }, }, @@ -181,10 +181,10 @@ func (d *Deployer) httpScaledObject(f fn.Function, namespace string, deployment Port: service.Spec.Ports[0].Port, }, Replicas: &httpv1alpha1.ReplicaStruct{ - Min: minScale, - Max: maxScale, + Min: &minScale, + Max: &maxScale, }, - CooldownPeriod: pointer.Int32(300), + CooldownPeriod: ptr.To(int32(300)), ScalingMetric: &httpv1alpha1.ScalingMetricSpec{ Rate: &httpv1alpha1.RateMetricSpec{ TargetValue: 100, @@ -208,7 +208,7 @@ func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *cor }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, - ExternalName: fmt.Sprintf("keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local"), // TODO: check for real cluster domain + ExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local", // TODO: check for real cluster domain Ports: []corev1.ServicePort{ { Protocol: "TCP", @@ -260,7 +260,7 @@ func (d *Deployer) ensureHTTPScaledObject(ctx context.Context, f fn.Function, na httpScaledObjectClientset, err := NewHTTPScaledObjectClientset() if err != nil { - fmt.Errorf("failed to create HTTPScaledObject clientset: %v", err) + return fmt.Errorf("failed to create HTTPScaledObject clientset: %v", err) } existing, err := httpScaledObjectClientset.HttpV1alpha1().HTTPScaledObjects(expected.Namespace).Get(ctx, expected.Name, metav1.GetOptions{}) From 2896fff60da4892dee1ae359bc155edc0dd062b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Thu, 22 Jan 2026 17:41:16 +0100 Subject: [PATCH 04/12] Scale down keda-http-add-on to only one replica in CI to save resources --- hack/cluster.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hack/cluster.sh b/hack/cluster.sh index 736b3ef8d2..40d39cc533 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -669,6 +669,17 @@ keda_http_addon() { echo "Waiting for Keda HTTP add-on to become ready" $KUBECTL wait deployment --all --timeout=-1s --for=condition=Available --namespace keda + # Reduce resource requests for CI environments + if [ "${GITHUB_ACTIONS:-false}" = "true" ]; then + echo "${blue}Reducing KEDA HTTP add-on resource requests for CI${reset}" + + # Reduce replica counts for CI (3 replicas is overkill for testing) + $KUBECTL scale deployment keda-add-ons-http-interceptor -n keda --replicas=1 || echo "Warning: Failed to scale keda-add-ons-http-interceptor" + $KUBECTL scale deployment keda-add-ons-http-scaler -n keda --replicas=1 || echo "Warning: Failed to scale keda-add-ons-http-scaler" + + echo "${green}✅ Resource requests reduced for CI${reset}" + fi + $KUBECTL get pod -n keda echo "${green}✅ Keda HTTP add-on${reset}" } From 8206b24e93c1eb0f4b184c397254cdf5a078e1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 11:40:03 +0100 Subject: [PATCH 05/12] Allow to specify the cluster-domain --- cmd/deploy.go | 9 ++++++++- docs/reference/func_deploy.md | 1 + pkg/functions/function.go | 3 +++ pkg/k8s/deployer.go | 11 ++++++++++- pkg/keda/deployer.go | 2 +- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 59ef85a032..0cf938f3f0 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -132,7 +132,7 @@ EXAMPLES PreRunE: bindEnv("build", "build-timestamp", "builder", "builder-image", "base-image", "confirm", "domain", "env", "git-branch", "git-dir", "git-url", "image", "namespace", "path", "platform", "push", "pvc-size", - "service-account", "deployer", "registry", "registry-insecure", + "service-account", "deployer", "cluster-domain", "registry", "registry-insecure", "registry-authfile", "remote", "username", "password", "token", "verbose", "remote-storage-class"), RunE: func(cmd *cobra.Command, args []string) error { @@ -197,6 +197,8 @@ EXAMPLES "Service account to be used in the deployed function ($FUNC_SERVICE_ACCOUNT)") cmd.Flags().String("deployer", f.Deploy.Deployer, fmt.Sprintf("Type of deployment to use: '%s' for Knative Service (default), '%s' for Kubernetes Deployment or '%s' for Deployment with a Keda HTTP scaler ($FUNC_DEPLOY_TYPE)", knative.KnativeDeployerName, k8s.KubernetesDeployerName, keda.KedaDeployerName)) + cmd.Flags().String("cluster-domain", f.Deploy.ClusterDomain, + "Kubernetes cluster domain for service DNS resolution. Defaults to 'cluster.local' ($FUNC_CLUSTER_DOMAIN)") // Static Flags: // Options which have static defaults only (not globally configurable nor // persisted with the function) @@ -535,6 +537,9 @@ type deployConfig struct { // Deployer specifies the type of deployment: "knative" or "raw" Deployer string + // ClusterDomain specifies the Kubernetes cluster domain for service DNS resolution + ClusterDomain string + // Remote indicates the deployment (and possibly build) process are to // be triggered in a remote environment rather than run locally. Remote bool @@ -569,6 +574,7 @@ func newDeployConfig(cmd *cobra.Command) deployConfig { Timestamp: viper.GetBool("build-timestamp"), ServiceAccountName: viper.GetString("service-account"), Deployer: viper.GetString("deployer"), + ClusterDomain: viper.GetString("cluster-domain"), } // NOTE: .Env should be viper.GetStringSlice, but this returns unparsed // results and appears to be an open issue since 2017: @@ -604,6 +610,7 @@ func (c deployConfig) Configure(f fn.Function) (fn.Function, error) { f.Build.RemoteStorageClass = c.RemoteStorageClass f.Deploy.ServiceAccountName = c.ServiceAccountName f.Deploy.Deployer = c.Deployer + f.Deploy.ClusterDomain = c.ClusterDomain f.Local.Remote = c.Remote // PVCSize diff --git a/docs/reference/func_deploy.md b/docs/reference/func_deploy.md index 5fd45cbfde..1d9cf4f6f1 100644 --- a/docs/reference/func_deploy.md +++ b/docs/reference/func_deploy.md @@ -118,6 +118,7 @@ func deploy --build-timestamp Use the actual time as the created time for the docker image. This is only useful for buildpacks builder. -b, --builder string Builder to use when creating the function's container. Currently supported builders are "host", "pack" and "s2i". (default "pack") --builder-image string Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) + --cluster-domain string Kubernetes cluster domain for service DNS resolution. Defaults to 'cluster.local' ($FUNC_CLUSTER_DOMAIN) -c, --confirm Prompt to confirm options interactively ($FUNC_CONFIRM) --deployer string Type of deployment to use: 'knative' for Knative Service (default), 'raw' for Kubernetes Deployment or 'keda' for Deployment with a Keda HTTP scaler ($FUNC_DEPLOY_TYPE) --domain string Domain to use for the function's route. Cluster must be configured with domain matching for the given domain (ignored if unrecognized) ($FUNC_DOMAIN) diff --git a/pkg/functions/function.go b/pkg/functions/function.go index cc11bea760..3731af017a 100644 --- a/pkg/functions/function.go +++ b/pkg/functions/function.go @@ -212,6 +212,9 @@ type DeploySpec struct { // Defaults to "knative" for backwards compatibility Deployer string `yaml:"deployer,omitempty" jsonschema:"enum=knative,enum=raw"` + // ClusterDomain specifies the Kubernetes cluster domain for service DNS resolution + ClusterDomain string `yaml:"clusterDomain,omitempty"` + Subscriptions []KnativeSubscription `yaml:"subscriptions,omitempty"` } diff --git a/pkg/k8s/deployer.go b/pkg/k8s/deployer.go index de048034cb..4ed6ca97c0 100644 --- a/pkg/k8s/deployer.go +++ b/pkg/k8s/deployer.go @@ -26,6 +26,8 @@ const ( DefaultLivenessEndpoint = "/health/liveness" DefaultReadinessEndpoint = "/health/readiness" DefaultHTTPPort = 8080 + + DefaultClusterDomain = "cluster.local" ) type DeployerOpt func(*Deployer) @@ -188,7 +190,7 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResu return fn.DeploymentResult{}, fmt.Errorf("deployment did not become ready: %w", err) } - url := fmt.Sprintf("http://%s.%s.svc.cluster.local", f.Name, namespace) + url := fmt.Sprintf("http://%s.%s.svc.%s", f.Name, namespace, GetClusterDomain(f)) return fn.DeploymentResult{ Status: status, @@ -750,3 +752,10 @@ func UsesRawDeployer(annotations map[string]string) bool { return ok && deployer == KubernetesDeployerName } + +func GetClusterDomain(f fn.Function) string { + if f.Deploy.ClusterDomain != "" { + return f.Deploy.ClusterDomain + } + return DefaultClusterDomain +} diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index 3cec6b7d96..bcefb55ccf 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -208,7 +208,7 @@ func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *cor }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, - ExternalName: "keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local", // TODO: check for real cluster domain + ExternalName: fmt.Sprintf("keda-add-ons-http-interceptor-proxy.keda.svc.%s", k8s.GetClusterDomain(f)), Ports: []corev1.ServicePort{ { Protocol: "TCP", From 5fceb4d3fcaf36fd7b6c5b074be07f8fc017feda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 11:43:34 +0100 Subject: [PATCH 06/12] Remove outdated comment --- pkg/deployer/testing/integration_test_helper.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/deployer/testing/integration_test_helper.go b/pkg/deployer/testing/integration_test_helper.go index 83f8286e92..f753558c26 100644 --- a/pkg/deployer/testing/integration_test_helper.go +++ b/pkg/deployer/testing/integration_test_helper.go @@ -1152,7 +1152,6 @@ func (k *kedaRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) } // Rewrite the URL to point to the KEDA interceptor-proxy - // TODO: maybe we can point to the ingress controller here instead req.URL.Scheme = "http" req.URL.Host = "keda-add-ons-http-interceptor-proxy.keda.svc:8080" From 9b8b61ad6af7f550051936855f9ba2a086cda57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 11:46:20 +0100 Subject: [PATCH 07/12] Update comment --- pkg/keda/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/keda/client.go b/pkg/keda/client.go index 06f94642f3..c35bef5ba5 100644 --- a/pkg/keda/client.go +++ b/pkg/keda/client.go @@ -11,7 +11,7 @@ import ( func NewHTTPScaledObjectClientset() (*httpv1alpha1.Clientset, error) { restConfig, err := k8s.GetClientConfig().ClientConfig() if err != nil { - return nil, fmt.Errorf("failed to create new kubernetes client: %w", err) + return nil, fmt.Errorf("failed to get clientconfig: %w", err) } return httpv1alpha1.NewForConfig(restConfig) From d4dc779dbdfd8ef2dc119445801f40e01f7fb784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 11:46:53 +0100 Subject: [PATCH 08/12] Remove port section in external name service --- pkg/keda/deployer.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index bcefb55ccf..651921fb5d 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -11,7 +11,6 @@ import ( "k8s.io/apimachinery/pkg/api/equality" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" "k8s.io/utils/ptr" "knative.dev/func/pkg/deployer" @@ -209,15 +208,6 @@ func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *cor Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, ExternalName: fmt.Sprintf("keda-add-ons-http-interceptor-proxy.keda.svc.%s", k8s.GetClusterDomain(f)), - Ports: []corev1.ServicePort{ - { - Protocol: "TCP", - Port: 8080, // ExternalName services don't do port translation, so this must match kedas interceptors port - TargetPort: intstr.IntOrString{ - IntVal: 8080, - }, - }, - }, }, } } From d9a04eec1f4154b0eef922029068382917305a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 11:58:27 +0100 Subject: [PATCH 09/12] Rename interceptor-proxy service to interceptor-bridge service --- pkg/keda/deployer.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index 651921fb5d..e7fd345fb7 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -115,13 +115,13 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResu return fn.DeploymentResult{}, fmt.Errorf("failed to get service %s/%s: %v", namespace, f.Name, err) } - if err := d.ensureInterceptorProxyService(ctx, k8sClientset, f, namespace); err != nil { + if err := d.ensureInterceptorBridgeService(ctx, k8sClientset, f, namespace); err != nil { return fn.DeploymentResult{}, fmt.Errorf("failed to ensure proxy service exists: %w", err) } hosts := []string{ - fmt.Sprintf("%s-interceptor-proxy.%s.svc", f.Name, namespace), - fmt.Sprintf("%s-interceptor-proxy", f.Name), + fmt.Sprintf("%s.%s.svc", d.interceptorBridgeServiceName(f), namespace), + fmt.Sprintf("%s", d.interceptorBridgeServiceName(f)), } if err := d.ensureHTTPScaledObject(ctx, f, namespace, deployment, appService, hosts); err != nil { @@ -199,10 +199,14 @@ func (d *Deployer) httpScaledObject(f fn.Function, namespace string, deployment }, nil } -func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *corev1.Service { +func (d *Deployer) interceptorBridgeServiceName(f fn.Function) string { + return fmt.Sprintf("%s-interceptor-bridge", f.Name) +} + +func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string) *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-interceptor-proxy", f.Name), + Name: d.interceptorBridgeServiceName(f), Namespace: namespace, }, Spec: corev1.ServiceSpec{ @@ -212,19 +216,23 @@ func (d *Deployer) interceptorProxyService(f fn.Function, namespace string) *cor } } -func (d *Deployer) ensureInterceptorProxyService(ctx context.Context, clientset *kubernetes.Clientset, f fn.Function, namespace string) error { - expected := d.interceptorProxyService(f, namespace) +// ensureInterceptorBridgeService makes sure to create the service which serves as the entrypoint to the function +// this service will server as an external-name service and forward the request to the keda interceptor-proxy by +// preserving the host name. This service name is also used in the HTTPScaledObject as host name to allow the +// interceptor to match the request with the correct target/scaledObject. +func (d *Deployer) ensureInterceptorBridgeService(ctx context.Context, clientset *kubernetes.Clientset, f fn.Function, namespace string) error { + expected := d.interceptorBridgeService(f, namespace) existing, err := clientset.CoreV1().Services(expected.Namespace).Get(ctx, expected.Name, metav1.GetOptions{}) if err != nil { if k8serrors.IsNotFound(err) { if _, err := clientset.CoreV1().Services(expected.Namespace).Create(ctx, expected, metav1.CreateOptions{}); err != nil { - return fmt.Errorf("failed to create interceptor bridge service: %w", err) + return fmt.Errorf("failed to create service to interceptor proxy: %w", err) } return nil } - return fmt.Errorf("failed to get interceptor bridge service: %w", err) + return fmt.Errorf("failed to get service to interceptor proxy: %w", err) } // check if we need to update @@ -233,7 +241,7 @@ func (d *Deployer) ensureInterceptorProxyService(ctx context.Context, clientset expected.ResourceVersion = existing.ResourceVersion if _, err = clientset.CoreV1().Services(namespace).Update(ctx, expected, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("failed to update bridge service: %w", err) + return fmt.Errorf("failed to update service to interceptor proxy: %w", err) } return nil From ea2966e2b1457ee55442bed207643ca6c5867dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 12:00:36 +0100 Subject: [PATCH 10/12] Fix: add owner reference in bridge service too --- pkg/keda/deployer.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pkg/keda/deployer.go b/pkg/keda/deployer.go index e7fd345fb7..0156e8b2d3 100644 --- a/pkg/keda/deployer.go +++ b/pkg/keda/deployer.go @@ -115,13 +115,13 @@ func (d *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResu return fn.DeploymentResult{}, fmt.Errorf("failed to get service %s/%s: %v", namespace, f.Name, err) } - if err := d.ensureInterceptorBridgeService(ctx, k8sClientset, f, namespace); err != nil { + if err := d.ensureInterceptorBridgeService(ctx, k8sClientset, f, namespace, deployment); err != nil { return fn.DeploymentResult{}, fmt.Errorf("failed to ensure proxy service exists: %w", err) } hosts := []string{ fmt.Sprintf("%s.%s.svc", d.interceptorBridgeServiceName(f), namespace), - fmt.Sprintf("%s", d.interceptorBridgeServiceName(f)), + d.interceptorBridgeServiceName(f), } if err := d.ensureHTTPScaledObject(ctx, f, namespace, deployment, appService, hosts); err != nil { @@ -203,11 +203,20 @@ func (d *Deployer) interceptorBridgeServiceName(f fn.Function) string { return fmt.Sprintf("%s-interceptor-bridge", f.Name) } -func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string) *corev1.Service { +func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string, deployment *v1.Deployment) *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: d.interceptorBridgeServiceName(f), Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "apps/v1", + Kind: "Deployment", + Name: deployment.Name, + UID: deployment.UID, + Controller: ptr.To(true), + }, + }, }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeExternalName, @@ -220,8 +229,8 @@ func (d *Deployer) interceptorBridgeService(f fn.Function, namespace string) *co // this service will server as an external-name service and forward the request to the keda interceptor-proxy by // preserving the host name. This service name is also used in the HTTPScaledObject as host name to allow the // interceptor to match the request with the correct target/scaledObject. -func (d *Deployer) ensureInterceptorBridgeService(ctx context.Context, clientset *kubernetes.Clientset, f fn.Function, namespace string) error { - expected := d.interceptorBridgeService(f, namespace) +func (d *Deployer) ensureInterceptorBridgeService(ctx context.Context, clientset *kubernetes.Clientset, f fn.Function, namespace string, deployment *v1.Deployment) error { + expected := d.interceptorBridgeService(f, namespace, deployment) existing, err := clientset.CoreV1().Services(expected.Namespace).Get(ctx, expected.Name, metav1.GetOptions{}) if err != nil { if k8serrors.IsNotFound(err) { From f3f5b874754531fdd4d07361559e30728959aa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Fri, 23 Jan 2026 12:22:14 +0100 Subject: [PATCH 11/12] Run `make schema-generate` --- schema/func_yaml-schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/schema/func_yaml-schema.json b/schema/func_yaml-schema.json index eb8b637826..8da558aad9 100644 --- a/schema/func_yaml-schema.json +++ b/schema/func_yaml-schema.json @@ -115,6 +115,10 @@ "type": "string", "description": "Deployer specifies the type of deployment to use: \"knative\" or \"raw\"\nDefaults to \"knative\" for backwards compatibility" }, + "clusterDomain": { + "type": "string", + "description": "ClusterDomain specifies the Kubernetes cluster domain for service DNS resolution" + }, "subscriptions": { "items": { "$schema": "http://json-schema.org/draft-04/schema#", From e22bfe8f519268e9208b28eeb145cd6179a2ee83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Mon, 26 Jan 2026 20:06:47 +0100 Subject: [PATCH 12/12] Update component-versions via component-versions.json --- hack/cmd/components/main.go | 2 ++ hack/component-versions.json | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/hack/cmd/components/main.go b/hack/cmd/components/main.go index dd711e7523..e31ee3cfb4 100644 --- a/hack/cmd/components/main.go +++ b/hack/cmd/components/main.go @@ -56,6 +56,8 @@ set_versions() { contour_version="{{.Contour.Version}}" tekton_version="{{.Tekton.Version}}" pac_version="{{.Pac.Version}}" + keda_version="{{.Keda.Version}}" + keda_http_addon_version="{{.KedaHTTPAddOn.Version}}" } ` ) diff --git a/hack/component-versions.json b/hack/component-versions.json index 3e8b82d06d..815576bd81 100644 --- a/hack/component-versions.json +++ b/hack/component-versions.json @@ -22,5 +22,11 @@ }, "Tekton": { "version": "v1.1.0" + }, + "Keda": { + "version": "v2.17.0" + }, + "KedaHTTPAddOn": { + "version": "v0.11.1" } }