Skip to content

Commit

Permalink
Patch the fix Selenium Grid scaler on KEDA core 2.16
Browse files Browse the repository at this point in the history
Signed-off-by: Viet Nguyen Duc <[email protected]>
  • Loading branch information
VietND96 committed Nov 26, 2024
1 parent 5c52d03 commit 2c7c5e2
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 24 deletions.
109 changes: 109 additions & 0 deletions .github/workflows/release-patch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: release-patch
on:
push:
tags:
- 'v*'
jobs:
build:
name: Push Release
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
id-token: write # needed for signing the images with GitHub OIDC Token **not production ready**

# keda-tools is built from github.com/test-tools/tools/Dockerfile
container: ghcr.io/kedacore/keda-tools:1.23.3
steps:
- name: Check out code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
fetch-depth: 1

- name: Register workspace path
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- id: go-paths
run: |
echo "mod_cache=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT
echo "build_cache=$(go env GOCACHE)" >> $GITHUB_OUTPUT
- name: Go modules cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ steps.go-paths.outputs.mod_cache }}
key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }}

- name: Go build cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ steps.go-paths.outputs.build_cache }}
key: ${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}

- name: Go modules sync
run: go mod tidy -compat=1.23

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
# Username used to log in to a Docker registry. If not set then no login will occur
username: ${{secrets.DOCKER_USERNAME}}
# Password or personal access token used to log in to a Docker registry. If not set then no login will occur
password: ${{secrets.DOCKER_PASSWORD}}
# Server address of Docker registry. If not set then will default to Docker Hub
registry: docker.io

- name: Get the version
id: get_version
run: |
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Release Deployment YAML file
run: IMAGE_REPO=${IMAGE_REPO} IMAGE_REGISTRY=${IMAGE_REGISTRY} make release
env:
IMAGE_REPO: ${{ vars.DOCKER_NAMESPACE || 'selenium' }}
IMAGE_REGISTRY: docker.io
VERSION: ${{ steps.get_version.outputs.VERSION }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Publish KEDA images on GitHub Container Registry
run: IMAGE_REPO=${IMAGE_REPO} IMAGE_REGISTRY=${IMAGE_REGISTRY} make publish-multiarch
env:
IMAGE_REPO: ${{ vars.DOCKER_NAMESPACE || 'selenium' }}
IMAGE_REGISTRY: docker.io
VERSION: ${{ steps.get_version.outputs.VERSION }}

# https://github.com/sigstore/cosign-installer
- name: Install Cosign
uses: sigstore/cosign-installer@v3

- name: Check Cosign install!
run: cosign version

- name: Sign KEDA images published on GitHub Container Registry
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: IMAGE_REPO=${IMAGE_REPO} IMAGE_REGISTRY=${IMAGE_REGISTRY} make sign-images
env:
IMAGE_REPO: ${{ vars.DOCKER_NAMESPACE || 'selenium' }}
IMAGE_REGISTRY: docker.io
VERSION: ${{ steps.get_version.outputs.VERSION }}

- name: Create Release
id: create_release
uses: softprops/action-gh-release@master
with:
token: "${{ secrets.GITHUB_TOKEN }}"
tag_name: "${{ steps.get_version.outputs.TAG_NAME }}"
name: "${{ steps.get_version.outputs.TAG_NAME }}"
generate_release_notes: true
prerelease: false
draft: false
append_body: false
files: |
keda-${{ steps.get_version.outputs.VERSION }}.yaml
keda-${{ steps.get_version.outputs.VERSION }}-core.yaml
keda-${{ steps.get_version.outputs.VERSION }}-crds.yaml
27 changes: 15 additions & 12 deletions pkg/scalers/selenium_grid_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ type seleniumGridScalerMetadata struct {
UnsafeSsl bool `keda:"name=unsafeSsl, order=triggerMetadata, optional, default=false"`
PlatformName string `keda:"name=platformName, order=triggerMetadata, optional, default=linux"`
NodeMaxSessions int `keda:"name=nodeMaxSessions, order=triggerMetadata, optional, default=1"`

TargetValue int64
TargetQueueLength int64 `keda:"name=targetQueueLength, order=triggerMetadata;resolvedEnv, optional, default=1"`
}

type SeleniumResponse struct {
Expand Down Expand Up @@ -107,7 +106,8 @@ type Stereotypes []struct {
}

const (
DefaultBrowserVersion string = "latest"
DefaultBrowserVersion string = "latest"
DefaultTargetQueueLength int64 = 1
)

func NewSeleniumGridScaler(config *scalersconfig.ScalerConfig) (Scaler, error) {
Expand Down Expand Up @@ -135,9 +135,7 @@ func NewSeleniumGridScaler(config *scalersconfig.ScalerConfig) (Scaler, error) {
}

func parseSeleniumGridScalerMetadata(config *scalersconfig.ScalerConfig) (*seleniumGridScalerMetadata, error) {
meta := &seleniumGridScalerMetadata{
TargetValue: 1,
}
meta := &seleniumGridScalerMetadata{}

if err := config.TypedConfig(meta); err != nil {
return nil, fmt.Errorf("error parsing prometheus metadata: %w", err)
Expand All @@ -148,6 +146,10 @@ func parseSeleniumGridScalerMetadata(config *scalersconfig.ScalerConfig) (*selen
if meta.SessionBrowserName == "" {
meta.SessionBrowserName = meta.BrowserName
}

if meta.TargetQueueLength < 1 {
meta.TargetQueueLength = DefaultTargetQueueLength
}
return meta, nil
}

Expand All @@ -160,31 +162,32 @@ func (s *seleniumGridScaler) Close(context.Context) error {
}

func (s *seleniumGridScaler) GetMetricsAndActivity(ctx context.Context, metricName string) ([]external_metrics.ExternalMetricValue, bool, error) {
sessions, err := s.getSessionsCount(ctx, s.logger)
queueLen, err := s.getSessionsQueueLength(ctx, s.logger)
if err != nil {
return []external_metrics.ExternalMetricValue{}, false, fmt.Errorf("error requesting selenium grid endpoint: %w", err)
}

metric := GenerateMetricInMili(metricName, float64(sessions))
metric := GenerateMetricInMili(metricName, float64(queueLen))

return []external_metrics.ExternalMetricValue{metric}, sessions > s.metadata.ActivationThreshold, nil
// If the number of sessions queued is equal to or greater than the targetQueueLength, the scaler will scale up.
return []external_metrics.ExternalMetricValue{metric}, queueLen >= s.metadata.TargetQueueLength, nil
}

func (s *seleniumGridScaler) GetMetricSpecForScaling(context.Context) []v2.MetricSpec {
metricName := kedautil.NormalizeString(fmt.Sprintf("seleniumgrid-%s", s.metadata.BrowserName))
metricName := kedautil.NormalizeString(fmt.Sprintf("selenium-grid-%s-%s-%s", s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.PlatformName))
externalMetric := &v2.ExternalMetricSource{
Metric: v2.MetricIdentifier{
Name: GenerateMetricNameWithIndex(s.metadata.triggerIndex, metricName),
},
Target: GetMetricTarget(s.metricType, s.metadata.TargetValue),
Target: GetMetricTarget(s.metricType, s.metadata.TargetQueueLength),
}
metricSpec := v2.MetricSpec{
External: externalMetric, Type: externalMetricType,
}
return []v2.MetricSpec{metricSpec}
}

func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.Logger) (int64, error) {
func (s *seleniumGridScaler) getSessionsQueueLength(ctx context.Context, logger logr.Logger) (int64, error) {
body, err := json.Marshal(map[string]string{
"query": "{ grid { sessionCount, maxSession, totalSlots }, nodesInfo { nodes { id, status, sessionCount, maxSession, slotCount, stereotypes, sessions { id, capabilities, slot { id, stereotype } } } }, sessionsInfo { sessionQueueRequests } }",
})
Expand Down
24 changes: 12 additions & 12 deletions pkg/scalers/selenium_grid_scaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1750,7 +1750,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
BrowserVersion: "latest",
PlatformName: "linux",
NodeMaxSessions: 1,
Expand All @@ -1772,7 +1772,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "MicrosoftEdge",
SessionBrowserName: "msedge",
TargetValue: 1,
TargetQueueLength: 1,
BrowserVersion: "latest",
PlatformName: "linux",
NodeMaxSessions: 1,
Expand Down Expand Up @@ -1800,7 +1800,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
Password: "password",
BrowserName: "MicrosoftEdge",
SessionBrowserName: "msedge",
TargetValue: 1,
TargetQueueLength: 1,
BrowserVersion: "latest",
PlatformName: "linux",
NodeMaxSessions: 1,
Expand All @@ -1826,7 +1826,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "MicrosoftEdge",
SessionBrowserName: "msedge",
TargetValue: 1,
TargetQueueLength: 1,
BrowserVersion: "latest",
PlatformName: "linux",
Username: "username",
Expand All @@ -1851,7 +1851,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
BrowserVersion: "91.0",
UnsafeSsl: false,
PlatformName: "linux",
Expand All @@ -1876,7 +1876,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down Expand Up @@ -1917,7 +1917,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand All @@ -1944,7 +1944,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
URL: "http://selenium-hub:4444/graphql",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down Expand Up @@ -1978,7 +1978,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
Password: "password",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down Expand Up @@ -2013,7 +2013,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
Password: "password",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down Expand Up @@ -2048,7 +2048,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
AccessToken: "my-access-token",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down Expand Up @@ -2082,7 +2082,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) {
AccessToken: "my-access-token",
BrowserName: "chrome",
SessionBrowserName: "chrome",
TargetValue: 1,
TargetQueueLength: 1,
ActivationThreshold: 10,
BrowserVersion: "91.0",
UnsafeSsl: true,
Expand Down

0 comments on commit 2c7c5e2

Please sign in to comment.