From dcdb283b5a5302a0977cf4292404d088ef54eaad Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 2 Dec 2024 01:43:29 +0700 Subject: [PATCH 1/2] fix: Selenium Grid scaler exposes sum of pending and ongoing sessions to KDEA Signed-off-by: Viet Nguyen Duc --- pkg/scalers/selenium_grid_scaler.go | 95 +++++++------ pkg/scalers/selenium_grid_scaler_test.go | 168 +++++++++++++---------- 2 files changed, 139 insertions(+), 124 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index 057181c87e7..bb18d7c9762 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -36,10 +36,10 @@ type seleniumGridScalerMetadata struct { BrowserName string `keda:"name=browserName, order=triggerMetadata"` SessionBrowserName string `keda:"name=sessionBrowserName, order=triggerMetadata, optional"` ActivationThreshold int64 `keda:"name=activationThreshold, order=triggerMetadata, optional"` - BrowserVersion string `keda:"name=browserVersion, order=triggerMetadata, optional, default=latest"` - 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"` + BrowserVersion string `keda:"name=browserVersion, order=triggerMetadata, default=latest"` + UnsafeSsl bool `keda:"name=unsafeSsl, order=triggerMetadata, default=false"` + PlatformName string `keda:"name=platformName, order=triggerMetadata, default=linux"` + NodeMaxSessions int64 `keda:"name=nodeMaxSessions, order=triggerMetadata, default=1"` TargetValue int64 } @@ -55,9 +55,9 @@ type Data struct { } type Grid struct { - SessionCount int `json:"sessionCount"` - MaxSession int `json:"maxSession"` - TotalSlots int `json:"totalSlots"` + SessionCount int64 `json:"sessionCount"` + MaxSession int64 `json:"maxSession"` + TotalSlots int64 `json:"totalSlots"` } type NodesInfo struct { @@ -71,17 +71,17 @@ type SessionsInfo struct { type Nodes []struct { ID string `json:"id"` Status string `json:"status"` - SessionCount int `json:"sessionCount"` - MaxSession int `json:"maxSession"` - SlotCount int `json:"slotCount"` + SessionCount int64 `json:"sessionCount"` + MaxSession int64 `json:"maxSession"` + SlotCount int64 `json:"slotCount"` Stereotypes string `json:"stereotypes"` Sessions Sessions `json:"sessions"` } type ReservedNodes struct { ID string `json:"id"` - MaxSession int `json:"maxSession"` - SlotCount int `json:"slotCount"` + MaxSession int64 `json:"maxSession"` + SlotCount int64 `json:"slotCount"` } type Sessions []struct { @@ -102,7 +102,7 @@ type Capability struct { } type Stereotypes []struct { - Slots int `json:"slots"` + Slots int64 `json:"slots"` Stereotype Capability `json:"stereotype"` } @@ -148,6 +148,7 @@ func parseSeleniumGridScalerMetadata(config *scalersconfig.ScalerConfig) (*selen if meta.SessionBrowserName == "" { meta.SessionBrowserName = meta.BrowserName } + return meta, nil } @@ -160,18 +161,18 @@ 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) + newRequestNodes, onGoingSessions, 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(newRequestNodes+onGoingSessions)) - return []external_metrics.ExternalMetricValue{metric}, sessions > s.metadata.ActivationThreshold, nil + return []external_metrics.ExternalMetricValue{metric}, (newRequestNodes + onGoingSessions) > s.metadata.ActivationThreshold, 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), @@ -184,18 +185,18 @@ func (s *seleniumGridScaler) GetMetricSpecForScaling(context.Context) []v2.Metri 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, 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 } }", }) if err != nil { - return -1, err + return -1, -1, err } req, err := http.NewRequestWithContext(ctx, "POST", s.metadata.URL, bytes.NewBuffer(body)) if err != nil { - return -1, err + return -1, -1, err } if (s.metadata.AuthType == "" || strings.EqualFold(s.metadata.AuthType, "Basic")) && s.metadata.Username != "" && s.metadata.Password != "" { @@ -206,28 +207,28 @@ func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.L res, err := s.httpClient.Do(req) if err != nil { - return -1, err + return -1, -1, err } if res.StatusCode != http.StatusOK { msg := fmt.Sprintf("selenium grid returned %d", res.StatusCode) - return -1, errors.New(msg) + return -1, -1, errors.New(msg) } defer res.Body.Close() b, err := io.ReadAll(res.Body) if err != nil { - return -1, err + return -1, -1, err } - v, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, s.metadata.NodeMaxSessions, logger) + newRequestNodes, onGoingSession, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, s.metadata.NodeMaxSessions, logger) if err != nil { - return -1, err + return -1, -1, err } - return v, nil + return newRequestNodes, onGoingSession, nil } -func countMatchingSlotsStereotypes(stereotypes Stereotypes, request Capability, browserName string, browserVersion string, sessionBrowserName string, platformName string) int { - var matchingSlots int +func countMatchingSlotsStereotypes(stereotypes Stereotypes, request Capability, browserName string, browserVersion string, sessionBrowserName string, platformName string) int64 { + var matchingSlots int64 for _, stereotype := range stereotypes { if checkCapabilitiesMatch(stereotype.Stereotype, request, browserName, browserVersion, sessionBrowserName, platformName) { matchingSlots += stereotype.Slots @@ -236,8 +237,8 @@ func countMatchingSlotsStereotypes(stereotypes Stereotypes, request Capability, return matchingSlots } -func countMatchingSessions(sessions Sessions, request Capability, browserName string, browserVersion string, sessionBrowserName string, platformName string, logger logr.Logger) int { - var matchingSessions int +func countMatchingSessions(sessions Sessions, request Capability, browserName string, browserVersion string, sessionBrowserName string, platformName string, logger logr.Logger) int64 { + var matchingSessions int64 for _, session := range sessions { var capability = Capability{} if err := json.Unmarshal([]byte(session.Capabilities), &capability); err == nil { @@ -274,7 +275,7 @@ func checkCapabilitiesMatch(capability Capability, requestCapability Capability, return browserNameMatches && browserVersionMatches && platformNameMatches } -func checkNodeReservedSlots(reservedNodes []ReservedNodes, nodeID string, availableSlots int) int { +func checkNodeReservedSlots(reservedNodes []ReservedNodes, nodeID string, availableSlots int64) int64 { for _, reservedNode := range reservedNodes { if strings.EqualFold(reservedNode.ID, nodeID) { return reservedNode.SlotCount @@ -283,7 +284,7 @@ func checkNodeReservedSlots(reservedNodes []ReservedNodes, nodeID string, availa return availableSlots } -func updateOrAddReservedNode(reservedNodes []ReservedNodes, nodeID string, slotCount int, maxSession int) []ReservedNodes { +func updateOrAddReservedNode(reservedNodes []ReservedNodes, nodeID string, slotCount int64, maxSession int64) []ReservedNodes { for i, reservedNode := range reservedNodes { if strings.EqualFold(reservedNode.ID, nodeID) { // Update remaining available slots for the reserved node @@ -295,17 +296,15 @@ func updateOrAddReservedNode(reservedNodes []ReservedNodes, nodeID string, slotC return append(reservedNodes, ReservedNodes{ID: nodeID, SlotCount: slotCount, MaxSession: maxSession}) } -func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, nodeMaxSessions int, logger logr.Logger) (int64, error) { - // The returned count of the number of new Nodes will be scaled up - var count int64 +func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, nodeMaxSessions int64, logger logr.Logger) (int64, int64, error) { // Track number of available slots of existing Nodes in the Grid can be reserved for the matched requests - var availableSlots int + var availableSlots int64 // Track number of matched requests in the sessions queue will be served by this scaler - var queueSlots int + var queueSlots int64 var seleniumResponse = SeleniumResponse{} if err := json.Unmarshal(b, &seleniumResponse); err != nil { - return 0, err + return 0, 0, err } var sessionQueueRequests = seleniumResponse.Data.SessionsInfo.SessionQueueRequests @@ -314,6 +313,7 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s var reservedNodes []ReservedNodes // Track list of new Nodes will be scaled up with number of available slots following scaler parameter `nodeMaxSessions` var newRequestNodes []ReservedNodes + var onGoingSessions int64 for requestIndex, sessionQueueRequest := range sessionQueueRequests { var isRequestMatched bool var requestCapability = Capability{} @@ -332,20 +332,22 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s } var isRequestReserved bool + var sumOfCurrentSessionsMatch int64 // Check if the matched request can be assigned to available slots of existing Nodes in the Grid for _, node := range nodes { + // Count ongoing sessions that match the request capability and scaler metadata + var currentSessionsMatch = countMatchingSessions(node.Sessions, requestCapability, browserName, browserVersion, sessionBrowserName, platformName, logger) + sumOfCurrentSessionsMatch += currentSessionsMatch // Check if node is UP and has available slots (maxSession > sessionCount) if strings.EqualFold(node.Status, "UP") && checkNodeReservedSlots(reservedNodes, node.ID, node.MaxSession-node.SessionCount) > 0 { var stereotypes = Stereotypes{} - var availableSlotsMatch int + var availableSlotsMatch int64 if err := json.Unmarshal([]byte(node.Stereotypes), &stereotypes); err == nil { // Count available slots that match the request capability and scaler metadata availableSlotsMatch += countMatchingSlotsStereotypes(stereotypes, requestCapability, browserName, browserVersion, sessionBrowserName, platformName) } else { logger.Error(err, fmt.Sprintf("Error when unmarshaling node stereotypes: %s", err)) } - // Count ongoing sessions that match the request capability and scaler metadata - var currentSessionsMatch = countMatchingSessions(node.Sessions, requestCapability, browserName, browserVersion, sessionBrowserName, platformName, logger) // Count remaining available slots can be reserved for this request var availableSlotsCanBeReserved = checkNodeReservedSlots(reservedNodes, node.ID, node.MaxSession-node.SessionCount) // Reserve one available slot for the request if available slots match is greater than current sessions match @@ -357,6 +359,9 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s } } } + if sumOfCurrentSessionsMatch > onGoingSessions { + onGoingSessions = sumOfCurrentSessionsMatch + } // Check if the matched request can be assigned to available slots of new Nodes will be scaled up, since the scaler parameter `nodeMaxSessions` can be greater than 1 if !isRequestReserved { for _, newRequestNode := range newRequestNodes { @@ -373,11 +378,5 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s } } - if queueSlots > availableSlots { - count = int64(len(newRequestNodes)) - } else { - count = 0 - } - - return count, nil + return int64(len(newRequestNodes)), onGoingSessions, nil } diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index b92936cbe7f..6613be242ca 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -16,13 +16,14 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { sessionBrowserName string browserVersion string platformName string - nodeMaxSessions int + nodeMaxSessions int64 } tests := []struct { - name string - args args - want int64 - wantErr bool + name string + args args + wantNewRequestNodes int64 + wantOnGoingSessions int64 + wantErr bool }{ { name: "nil response body should throw error", @@ -61,8 +62,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { `), browserName: "", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "12 sessionQueueRequests with 4 requests matching browserName chrome should return count as 4", @@ -101,8 +102,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 4, - wantErr: false, + wantNewRequestNodes: 4, + wantErr: false, }, { name: "2 sessionQueueRequests and 1 available nodeStereotypes with matching browserName firefox should return count as 1", @@ -276,8 +277,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 4, + wantErr: false, }, { name: "1 sessionQueueRequests and 1 available nodeStereotypes with matching browserName chrome should return count as 0", @@ -325,8 +327,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "1 sessionQueueRequests Linux and 1 available nodeStereotypes Windows with matching browserName chrome should return count as 1", @@ -374,8 +376,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantErr: false, }, { name: "scaler browserVersion is latest, 2 sessionQueueRequests wihtout browserVersion, 2 available nodeStereotypes with different versions and platforms, should return count as 1", @@ -422,8 +424,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantErr: false, }, { name: "scaler browserVersion is latest, 5 sessionQueueRequests wihtout browserVersion also 1 different platformName, 1 available nodeStereotypes with 3 slots Linux and 1 node Windows, should return count as 1", @@ -473,8 +475,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantErr: false, }, { name: "queue request with browserName browserVersion and browserVersion but no available nodes should return count as 1", @@ -516,8 +518,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantErr: false, }, { name: "1 queue request with browserName browserVersion and browserVersion but 2 nodes without available slots should return count as 1", @@ -573,8 +575,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "2 session queue with matching browsername and browserversion of 2 available slots should return count as 0", @@ -621,8 +624,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "2 queue requests with browserName browserVersion and platformName matching 2 available slots on 2 different nodes should return count as 0", @@ -679,8 +682,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "1 queue request with browserName browserVersion and platformName matching 1 available slot on node has 3 max sessions should return count as 0", @@ -726,8 +730,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "3 queue requests with browserName browserVersion and platformName but 2 running nodes are busy should return count as 3", @@ -785,8 +790,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 3, - wantErr: false, + wantNewRequestNodes: 3, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "3 queue requests with browserName browserVersion and platformName but 2 running nodes are busy with different versions should return count as 3", @@ -844,8 +850,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 3, - wantErr: false, + wantNewRequestNodes: 3, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "3 queue requests with browserName and platformName but 2 running nodes are busy with different versions should return count as 3", @@ -903,8 +910,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 3, - wantErr: false, + wantNewRequestNodes: 3, + wantOnGoingSessions: 2, + wantErr: false, }, { name: "1 active session with matching browsername and version should return count as 2", @@ -947,8 +955,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "1 request without browserName and browserVersion stable can be match any available node should return count as 0", @@ -985,8 +994,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "1 request without browserName and browserVersion stable should return count as 1", @@ -1028,8 +1037,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "2 queue requests with browserName in string match node stereotype and scaler metadata browserVersion should return count as 1", @@ -1072,8 +1082,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "dev", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "2 queue requests with matching browsername/sessionBrowserName but 1 node is busy should return count as 2", @@ -1116,8 +1127,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "2 queue requests with matching browsername/sessionBrowserName and 1 node is is available should return count as 1", @@ -1155,8 +1167,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantErr: false, }, { name: "2 queue requests with platformName and without platformName and node with 1 slot available should return count as 1", args: args{ @@ -1198,8 +1210,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "Windows 11", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "1 active msedge session while asking for 2 chrome sessions should return a count of 2", @@ -1242,8 +1255,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantErr: false, }, { name: "3 queue requests browserName chrome platformName linux but 1 node has maxSessions=3 with browserName msedge should return a count of 3", @@ -1287,8 +1300,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 3, - wantErr: false, + wantNewRequestNodes: 3, + wantErr: false, }, { name: "session request with matching browsername and no specific platformName should return count as 2", @@ -1316,8 +1329,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "", }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantErr: false, }, { name: "2 queue requests with 1 matching browsername and platformName and 1 existing slot is available should return count as 0", @@ -1355,8 +1368,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "Windows 11", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "2 queue requests with 1 request matching browserName and platformName but 1 existing node is busy should return count as 1", @@ -1403,8 +1416,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0", platformName: "Windows 11", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 1, + wantErr: false, }, { name: "5 queue requests with scaler parameter nodeMaxSessions is 2 should return count as 3", @@ -1437,8 +1451,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { platformName: "linux", nodeMaxSessions: 2, }, - want: 3, - wantErr: false, + wantNewRequestNodes: 3, + wantErr: false, }, { name: "5 queue requests with scaler parameter nodeMaxSessions is 3 should return count as 2", @@ -1471,8 +1485,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { platformName: "linux", nodeMaxSessions: 3, }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantErr: false, }, { name: "5 queue requests with request matching browserName and platformName and scaler param nodeMaxSessions is 3 and existing node with 1 available slot should return count as 2", @@ -1523,8 +1537,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { platformName: "linux", nodeMaxSessions: 3, }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantOnGoingSessions: 2, + wantErr: false, }, // Tests from PR: https://github.com/kedacore/keda/pull/6055 { @@ -1563,8 +1578,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 0, - wantErr: false, + wantNewRequestNodes: 0, + wantErr: false, }, { name: "4 sessions requests with matching browsername and platformName when setSessionsFromHub turned on and node with 2 slots matches should return count as 2", @@ -1605,8 +1620,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "latest", platformName: "linux", }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantErr: false, }, { name: "4 sessions requests with matching browsername and platformName when setSessionsFromHub turned on, no nodes and sessionsPerNode=2 matches should return count as 2", @@ -1637,8 +1652,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { platformName: "linux", nodeMaxSessions: 2, }, - want: 2, - wantErr: false, + wantNewRequestNodes: 2, + wantErr: false, }, { name: "sessions requests and active sessions with 1 matching browsername, platformName and sessionBrowserVersion should return count as 1", @@ -1687,19 +1702,20 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { browserVersion: "91.0.4472.114", platformName: "linux", }, - want: 1, - wantErr: false, + wantNewRequestNodes: 1, + wantOnGoingSessions: 2, + wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := getCountFromSeleniumResponse(tt.args.b, tt.args.browserName, tt.args.browserVersion, tt.args.sessionBrowserName, tt.args.platformName, tt.args.nodeMaxSessions, logr.Discard()) + newRequestNodes, onGoingSessions, err := getCountFromSeleniumResponse(tt.args.b, tt.args.browserName, tt.args.browserVersion, tt.args.sessionBrowserName, tt.args.platformName, tt.args.nodeMaxSessions, logr.Discard()) if (err != nil) != tt.wantErr { t.Errorf("getCountFromSeleniumResponse() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("getCountFromSeleniumResponse() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(newRequestNodes, tt.wantNewRequestNodes) || !reflect.DeepEqual(onGoingSessions, tt.wantOnGoingSessions) { + t.Errorf("getCountFromSeleniumResponse() = [%v, %v], want [%v, %v]", newRequestNodes, onGoingSessions, tt.wantNewRequestNodes, tt.wantOnGoingSessions) } }) } From 9e6e5c33bef10217df1cbbe82b2a358dd5a10af5 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 2 Dec 2024 17:37:56 +0700 Subject: [PATCH 2/2] Update CHANGELOG Signed-off-by: Viet Nguyen Duc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8660a1b2123..8e5643a6a05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ Here is an overview of all new **experimental** features: - **General**: Centralize and improve automaxprocs configuration with proper structured logging ([#5970](https://github.com/kedacore/keda/issues/5970)) - **General**: Paused ScaledObject count is reported correctly after operator restart ([#6321](https://github.com/kedacore/keda/issues/6321)) - **General**: ScaledJobs ready status set to true when recoverred problem ([#6329](https://github.com/kedacore/keda/pull/6329)) +- **Selenium Grid Scaler**: Exposes sum of pending and ongoing sessions to KDEA ([#6368](https://github.com/kedacore/keda/pull/6368)) ### Deprecations