From a9cc37f0fcd5c9d0d83825db313034c194deb2f8 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 05:42:19 +0000 Subject: [PATCH 01/13] add sessionsPerNode and setSessionsFromHub parameters to selenium-grid scaler, add tests and changelog Signed-off-by: Hanzlik, Robert (MONETA) --- CHANGELOG.md | 2 +- pkg/scalers/selenium_grid_scaler.go | 62 +++++++++- pkg/scalers/selenium_grid_scaler_test.go | 144 ++++++++++++++++++++++- 3 files changed, 200 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7fedce792a..e828918c2ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Here is an overview of all new **experimental** features: ### Improvements -- TODO ([#XXX](https://github.com/kedacore/keda/issues/XXX)) +- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. They will allow to scale up based on real browser node settings (slots / node). When sesSessionsFromHub is set, KEDA will look for existing browser nodes with browserName, browserVersion and platformName same as scaledObject / scaledJob, get maxSessions and calculate how much nodes it needs. When no existing browser node matches, it uses sessionsPerNode value for calculation. ### Fixes diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index 4e1f75667ad..7f8d6944699 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -36,6 +36,8 @@ type seleniumGridScalerMetadata struct { 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"` + SessionsPerNode int64 `keda:"name=sessionsPerNode, order=triggerMetadata, optional, default=1"` + SetSessionsFromHub bool `keda:"name=setSessionsFromHub, order=triggerMetadata, optional, default=false"` TargetValue int64 } @@ -46,6 +48,7 @@ type seleniumResponse struct { type data struct { Grid grid `json:"grid"` + NodesInfo nodesInfo `json:"nodesInfo"` SessionsInfo sessionsInfo `json:"sessionsInfo"` } @@ -71,6 +74,19 @@ type capability struct { PlatformName string `json:"platformName"` } +type nodesInfo struct { + Nodes []nodes `json:"nodes"` +} + +type nodes struct { + Stereotypes string `json:"stereotypes"` +} + +type stereotype struct { + Slots int64 `json:"slots"` + Stereotype capability `json:"stereotype"` +} + const ( DefaultBrowserVersion string = "latest" DefaultPlatformName string = "linux" @@ -152,7 +168,7 @@ func (s *seleniumGridScaler) GetMetricSpecForScaling(context.Context) []v2.Metri func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.Logger) (int64, error) { body, err := json.Marshal(map[string]string{ - "query": "{ grid { maxSession, nodeCount }, sessionsInfo { sessionQueueRequests, sessions { id, capabilities, nodeId } } }", + "query": "{ grid { maxSession, nodeCount }, nodesInfo { nodes { stereotypes } }, sessionsInfo { sessionQueueRequests, sessions { id, capabilities, nodeId } } }", }) if err != nil { @@ -179,21 +195,46 @@ func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.L if err != nil { return -1, err } - v, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, logger) + v, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, s.metadata.SessionsPerNode, s.metadata.SetSessionsFromHub, logger) if err != nil { return -1, err } return v, nil } -func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, logger logr.Logger) (int64, error) { +func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, sessionsPerNode int64, setSessionsFromHub bool, logger logr.Logger) (int64, error) { var count int64 + var slots int64 var seleniumResponse = seleniumResponse{} if err := json.Unmarshal(b, &seleniumResponse); err != nil { return 0, err } + if setSessionsFromHub { + var nodes = seleniumResponse.Data.NodesInfo.Nodes + slots: + for _, node := range nodes { + var stereotypes = []stereotype{} + if err := json.Unmarshal([]byte(node.Stereotypes), &stereotypes); err == nil { + for _, stereotype := range stereotypes { + if stereotype.Stereotype.BrowserName == browserName { + var platformNameMatches = stereotype.Stereotype.PlatformName == "" || strings.EqualFold(stereotype.Stereotype.PlatformName, platformName) + if strings.HasPrefix(stereotype.Stereotype.BrowserVersion, browserVersion) && platformNameMatches { + slots = stereotype.Slots + break slots + } else if len(strings.TrimSpace(stereotype.Stereotype.BrowserVersion)) == 0 && browserVersion == DefaultBrowserVersion && platformNameMatches { + slots = stereotype.Slots + break slots + } + } + } + } else { + logger.Error(err, fmt.Sprintf("Error when unmarshalling stereotypes: %s", err)) + } + } + } + var sessionQueueRequests = seleniumResponse.Data.SessionsInfo.SessionQueueRequests for _, sessionQueueRequest := range sessionQueueRequests { var capability = capability{} @@ -231,10 +272,19 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s var gridMaxSession = int64(seleniumResponse.Data.Grid.MaxSession) var gridNodeCount = int64(seleniumResponse.Data.Grid.NodeCount) - if gridMaxSession > 0 && gridNodeCount > 0 { - // Get count, convert count to next highest int64 - var floatCount = float64(count) / (float64(gridMaxSession) / float64(gridNodeCount)) + if setSessionsFromHub { + if slots == 0 { + slots = sessionsPerNode + } + var floatCount = float64(count) / float64(slots) count = int64(math.Ceil(floatCount)) + } else { + if gridMaxSession > 0 && gridNodeCount > 0 { + // Get count, convert count to next highest int64 + var floatCount = float64(count) / (float64(gridMaxSession) / float64(gridNodeCount)) + count = int64(math.Ceil(floatCount)) + } } + return count, nil } diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 95e24743c1e..56361325d0d 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -16,6 +16,8 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { sessionBrowserName string browserVersion string platformName string + sessionsPerNode int64 + setSessionsFromHub bool } tests := []struct { name string @@ -50,6 +52,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 0, "nodeCount": 0 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": [], "sessions": [] @@ -70,6 +75,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -99,6 +107,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [] @@ -122,6 +133,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 4, "nodeCount": 2 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"] } @@ -144,6 +158,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 4, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -178,6 +195,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 3, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -212,6 +232,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 2, "nodeCount": 2 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}"], "sessions": [ @@ -246,6 +269,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 2, "nodeCount": 2 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}"], "sessions": [ @@ -280,6 +306,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 2, "nodeCount": 2 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"}","{\n \"browserName\": \"chrome\"}","{\n \"browserName\": \"chrome\"}"], "sessions": [ @@ -314,6 +343,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -343,6 +375,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"MicrosoftEdge\",\n \"browserVersion\": \"91.0\"\n}","{\n \"browserName\": \"MicrosoftEdge\",\n \"browserVersion\": \"91.0\"\n}"], "sessions": [ @@ -372,6 +407,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -401,6 +439,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 3, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\"\n}"], "sessions": [ @@ -430,6 +471,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], "sessions": [] @@ -453,6 +497,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], "sessions": [] @@ -467,6 +514,98 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { want: 1, wantErr: false, }, + { + name: "sessions requests with matching browsername and platformName when setSessionsFromHub turned on and node with 2 slots matches should return count as 1", + args: args{ + b: []byte(`{ + "data": { + "grid":{ + "maxSession": 1, + "nodeCount": 1 + }, + "nodesInfo": { + "nodes": [ + { + "stereotypes": "[\n {\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\",\n \"se:downloadsEnabled\": true,\n \"se:webDriverExecutable\": \"\\u002fopt + \\u002fchromedriver\"\n }\n }\n]", + } + ] + }, + "sessionsInfo": { + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], + "sessions": [] + } + } + }`), + browserName: "chrome", + sessionBrowserName: "chrome", + browserVersion: "latest", + platformName: "linux", + setSessionsFromHub: true, + }, + want: 1, + 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", + args: args{ + b: []byte(`{ + "data": { + "grid":{ + "maxSession": 1, + "nodeCount": 1 + }, + "nodesInfo": { + "nodes": [ + { + "stereotypes": "[\n {\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\",\n \"se:downloadsEnabled\": true,\n \"se:webDriverExecutable\": \"\\u002fopt + \\u002fchromedriver\"\n }\n }\n]", + } + ] + }, + "sessionsInfo": { + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], + "sessions": [] + } + } + }`), + browserName: "chrome", + sessionBrowserName: "chrome", + browserVersion: "latest", + platformName: "linux", + setSessionsFromHub: true, + }, + want: 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", + args: args{ + b: []byte(`{ + "data": { + "grid":{ + "maxSession": 1, + "nodeCount": 1 + }, + "nodesInfo": { + "nodes": [] + }, + "sessionsInfo": { + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], + "sessions": [] + } + } + }`), + browserName: "chrome", + sessionBrowserName: "chrome", + browserVersion: "latest", + platformName: "linux", + setSessionsFromHub: true, + sessionsPerNode: 2, + }, + want: 2, + wantErr: false, + }, { name: "sessions requests and active sessions with matching browsername and platformName should return count as 2", args: args{ @@ -476,6 +615,9 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "maxSession": 1, "nodeCount": 1 }, + "nodesInfo": { + "nodes": [] + }, "sessionsInfo": { "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\",\n \"browserVersion\": \"91.0\"\n}"], "sessions": [ @@ -504,7 +646,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { } 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, logr.Discard()) + got, err := getCountFromSeleniumResponse(tt.args.b, tt.args.browserName, tt.args.browserVersion, tt.args.sessionBrowserName, tt.args.platformName, tt.args.sessionsPerNode, tt.args.setSessionsFromHub, logr.Discard()) if (err != nil) != tt.wantErr { t.Errorf("getCountFromSeleniumResponse() error = %v, wantErr %v", err, tt.wantErr) return From d28661bd2463e8ad2ca19284d5c4a9ad522f0548 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 06:17:09 +0000 Subject: [PATCH 02/13] fix tests Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 56361325d0d..455bcb0e1fa 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -526,8 +526,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": "[\n {\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\",\n \"se:downloadsEnabled\": true,\n \"se:webDriverExecutable\": \"\\u002fopt - \\u002fchromedriver\"\n }\n }\n]", + "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"], } ] }, @@ -558,8 +557,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": "[\n {\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\",\n \"se:downloadsEnabled\": true,\n \"se:webDriverExecutable\": \"\\u002fopt - \\u002fchromedriver\"\n }\n }\n]", + "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"], } ] }, From 08b81d08cbec3e4f0a26a6bc3e23a71c7cd75b7f Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 06:44:35 +0000 Subject: [PATCH 03/13] fix json Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 455bcb0e1fa..75f7bca0ecc 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -526,7 +526,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"], + "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"] } ] }, @@ -557,7 +557,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"], + "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"] } ] }, From d8ce29a562c2502fe1a11aa1da8c8a54340211ee Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 07:17:34 +0000 Subject: [PATCH 04/13] fix json Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 75f7bca0ecc..646be742da1 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -526,7 +526,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"] + "stereotypes":"[{\"slots\":1,\"stereotype\":{\"browserName\":\"chrome\",\"platformName\":\"linux\"}}]" } ] }, @@ -557,7 +557,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes": ["{\n \"slots\": 2,\n \"stereotype\": {\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}\n }\n"] + "stereotypes":"[{\"slots\":1,\"stereotype\":{\"browserName\":\"chrome\",\"platformName\":\"linux\"}}]" } ] }, From a1ecf6b401e189c3064c5b0c0268c95a19fc05c5 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 08:18:29 +0000 Subject: [PATCH 05/13] fix tests Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 646be742da1..e576f812d22 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -557,12 +557,12 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodesInfo": { "nodes": [ { - "stereotypes":"[{\"slots\":1,\"stereotype\":{\"browserName\":\"chrome\",\"platformName\":\"linux\"}}]" + "stereotypes":"[{\"slots\":2,\"stereotype\":{\"browserName\":\"chrome\",\"platformName\":\"linux\"}}]" } ] }, "sessionsInfo": { - "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], "sessions": [] } } @@ -589,7 +589,7 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { "nodes": [] }, "sessionsInfo": { - "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}",{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\"\n}"], "sessions": [] } } From e7faa05045bd63b132a87e3c81a5b9dc3a3c9bc1 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 08:42:32 +0000 Subject: [PATCH 06/13] fix metadata tests Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index e576f812d22..166ad2d8421 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -704,6 +704,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { TargetValue: 1, BrowserVersion: "latest", PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -725,6 +726,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { TargetValue: 1, BrowserVersion: "latest", PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -748,6 +750,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { TargetValue: 1, BrowserVersion: "latest", PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -771,6 +774,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { BrowserVersion: "91.0", UnsafeSsl: false, PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -796,6 +800,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { BrowserVersion: "91.0", UnsafeSsl: true, PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -836,6 +841,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { BrowserVersion: "91.0", UnsafeSsl: true, PlatformName: "linux", + SessionsPerNode: 1, }, }, { @@ -862,6 +868,7 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { BrowserVersion: "91.0", UnsafeSsl: true, PlatformName: "Windows 11", + SessionsPerNode: 1, }, }, } From 698ffc8ee136b702933306293af736174112fa2e Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 9 Aug 2024 09:01:28 +0000 Subject: [PATCH 07/13] fix syntax Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index 7f8d6944699..dca7abcff1f 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -278,12 +278,10 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s } var floatCount = float64(count) / float64(slots) count = int64(math.Ceil(floatCount)) - } else { - if gridMaxSession > 0 && gridNodeCount > 0 { - // Get count, convert count to next highest int64 - var floatCount = float64(count) / (float64(gridMaxSession) / float64(gridNodeCount)) - count = int64(math.Ceil(floatCount)) - } + } else if gridMaxSession > 0 && gridNodeCount > 0 { + // Get count, convert count to next highest int64 + var floatCount = float64(count) / (float64(gridMaxSession) / float64(gridNodeCount)) + count = int64(math.Ceil(floatCount)) } return count, nil From 6ab849199038139f2b4227c80e020cda2503b151 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Thu, 15 Aug 2024 05:38:26 +0000 Subject: [PATCH 08/13] link Issue to Changelog Signed-off-by: Hanzlik, Robert (MONETA) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e828918c2ed..0094e9d4af6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Here is an overview of all new **experimental** features: ### Improvements -- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. They will allow to scale up based on real browser node settings (slots / node). When sesSessionsFromHub is set, KEDA will look for existing browser nodes with browserName, browserVersion and platformName same as scaledObject / scaledJob, get maxSessions and calculate how much nodes it needs. When no existing browser node matches, it uses sessionsPerNode value for calculation. +- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. (https://github.com/kedacore/keda/issues/6080) ### Fixes From c9636b640fc5e5997bbd63f1a9f928ede0898ff1 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Thu, 15 Aug 2024 06:23:52 +0000 Subject: [PATCH 09/13] fix link to issue Signed-off-by: Hanzlik, Robert (MONETA) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0094e9d4af6..093816565f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Here is an overview of all new **experimental** features: ### Improvements -- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. (https://github.com/kedacore/keda/issues/6080) +- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. ([#6080](https://github.com/kedacore/keda/issues/6080)) ### Fixes From fe910043d37c7fb6c11ae20003ee9f1a8c4ccf3c Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 16 Aug 2024 12:02:33 +0000 Subject: [PATCH 10/13] add sessionBrowserVersion and tests Signed-off-by: Hanzlik, Robert (MONETA) --- CHANGELOG.md | 2 +- pkg/scalers/selenium_grid_scaler.go | 28 ++++++------ pkg/scalers/selenium_grid_scaler_test.go | 54 ++++++++++++++++++++---- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 093816565f3..f64faf28a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Here is an overview of all new **experimental** features: ### Improvements -- selenium-grid: introduce new parameters setSessionsFromHub and sessionsPerNode. ([#6080](https://github.com/kedacore/keda/issues/6080)) +- selenium-grid: introduce new parameters setSessionsFromHub, sessionsPerNode and sessionBrowserVersion. ([#6080](https://github.com/kedacore/keda/issues/6080)) ### Fixes diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index dca7abcff1f..79831540592 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -29,15 +29,16 @@ type seleniumGridScaler struct { type seleniumGridScalerMetadata struct { triggerIndex int - URL string `keda:"name=url, order=triggerMetadata;authParams"` - 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"` - SessionsPerNode int64 `keda:"name=sessionsPerNode, order=triggerMetadata, optional, default=1"` - SetSessionsFromHub bool `keda:"name=setSessionsFromHub, order=triggerMetadata, optional, default=false"` + URL string `keda:"name=url, order=triggerMetadata;authParams"` + 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"` + SessionsPerNode int64 `keda:"name=sessionsPerNode, order=triggerMetadata, optional, default=1"` + SetSessionsFromHub bool `keda:"name=setSessionsFromHub, order=triggerMetadata, optional, default=false"` + SessionBrowserVersion string `keda:"name=sessionBrowserVersion, order=triggerMetadata, optional"` TargetValue int64 } @@ -130,6 +131,9 @@ func parseSeleniumGridScalerMetadata(config *scalersconfig.ScalerConfig) (*selen if meta.SessionBrowserName == "" { meta.SessionBrowserName = meta.BrowserName } + if meta.SessionBrowserVersion == "" { + meta.SessionBrowserVersion = meta.BrowserVersion + } return meta, nil } @@ -195,14 +199,14 @@ func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.L if err != nil { return -1, err } - v, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, s.metadata.SessionsPerNode, s.metadata.SetSessionsFromHub, logger) + v, err := getCountFromSeleniumResponse(b, s.metadata.BrowserName, s.metadata.BrowserVersion, s.metadata.SessionBrowserName, s.metadata.PlatformName, s.metadata.SessionsPerNode, s.metadata.SetSessionsFromHub, s.metadata.SessionBrowserVersion, logger) if err != nil { return -1, err } return v, nil } -func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, sessionsPerNode int64, setSessionsFromHub bool, logger logr.Logger) (int64, error) { +func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion string, sessionBrowserName string, platformName string, sessionsPerNode int64, setSessionsFromHub bool, sessionBrowserVersion string, logger logr.Logger) (int64, error) { var count int64 var slots int64 var seleniumResponse = seleniumResponse{} @@ -258,7 +262,7 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s if err := json.Unmarshal([]byte(session.Capabilities), &capability); err == nil { var platformNameMatches = capability.PlatformName == "" || strings.EqualFold(capability.PlatformName, platformName) if capability.BrowserName == sessionBrowserName { - if strings.HasPrefix(capability.BrowserVersion, browserVersion) && platformNameMatches { + if strings.HasPrefix(capability.BrowserVersion, sessionBrowserVersion) && platformNameMatches { count++ } else if browserVersion == DefaultBrowserVersion && platformNameMatches { count++ diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 166ad2d8421..18790ec5f75 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -11,13 +11,14 @@ import ( func Test_getCountFromSeleniumResponse(t *testing.T) { type args struct { - b []byte - browserName string - sessionBrowserName string - browserVersion string - platformName string - sessionsPerNode int64 - setSessionsFromHub bool + b []byte + browserName string + sessionBrowserName string + browserVersion string + platformName string + sessionsPerNode int64 + setSessionsFromHub bool + sessionBrowserVersion string } tests := []struct { name string @@ -641,10 +642,47 @@ func Test_getCountFromSeleniumResponse(t *testing.T) { want: 2, wantErr: false, }, + { + name: "sessions requests and active sessions with matching browsername, platformName and sessionBrowserVersion should return count as 3", + args: args{ + b: []byte(`{ + "data": { + "grid":{ + "maxSession": 1, + "nodeCount": 1 + }, + "nodesInfo": { + "nodes": [] + }, + "sessionsInfo": { + "sessionQueueRequests": ["{\n \"browserName\": \"chrome\",\n \"platformName\": \"linux\"\n}","{\n \"browserName\": \"chrome\",\n \"platformName\": \"Windows 11\",\n \"browserVersion\": \"91.0\"\n}"], + "sessions": [ + { + "id": "0f9c5a941aa4d755a54b84be1f6535b1", + "capabilities": "{\n \"acceptInsecureCerts\": false,\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0.4472.114\",\n \"chrome\": {\n \"chromedriverVersion\": \"91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs\\u002fbranch-heads\\u002f4472@{#1462})\",\n \"userDataDir\": \"\\u002ftmp\\u002f.com.google.Chrome.DMqx9m\"\n },\n \"goog:chromeOptions\": {\n \"debuggerAddress\": \"localhost:35839\"\n },\n \"networkConnectionEnabled\": false,\n \"pageLoadStrategy\": \"normal\",\n \"platformName\": \"linux\",\n \"proxy\": {\n },\n \"se:cdp\": \"http:\\u002f\\u002flocalhost:35839\",\n \"se:cdpVersion\": \"91.0.4472.114\",\n \"se:vncEnabled\": true,\n \"se:vncLocalAddress\": \"ws:\\u002f\\u002flocalhost:7900\\u002fwebsockify\",\n \"setWindowRect\": true,\n \"strictFileInteractability\": false,\n \"timeouts\": {\n \"implicit\": 0,\n \"pageLoad\": 300000,\n \"script\": 30000\n },\n \"unhandledPromptBehavior\": \"dismiss and notify\",\n \"webauthn:extension:largeBlob\": true,\n \"webauthn:virtualAuthenticators\": true\n}", + "nodeId": "d44dcbc5-0b2c-4d5e-abf4-6f6aa5e0983c" + }, + { + "id": "0f9c5a941aa4d755a54b84be1f6535b1", + "capabilities": "{\n \"acceptInsecureCerts\": false,\n \"browserName\": \"chrome\",\n \"browserVersion\": \"91.0.4472.114\",\n \"chrome\": {\n \"chromedriverVersion\": \"91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs\\u002fbranch-heads\\u002f4472@{#1462})\",\n \"userDataDir\": \"\\u002ftmp\\u002f.com.google.Chrome.DMqx9m\"\n },\n \"goog:chromeOptions\": {\n \"debuggerAddress\": \"localhost:35839\"\n },\n \"networkConnectionEnabled\": false,\n \"pageLoadStrategy\": \"normal\",\n \"platformName\": \"linux\",\n \"proxy\": {\n },\n \"se:cdp\": \"http:\\u002f\\u002flocalhost:35839\",\n \"se:cdpVersion\": \"91.0.4472.114\",\n \"se:vncEnabled\": true,\n \"se:vncLocalAddress\": \"ws:\\u002f\\u002flocalhost:7900\\u002fwebsockify\",\n \"setWindowRect\": true,\n \"strictFileInteractability\": false,\n \"timeouts\": {\n \"implicit\": 0,\n \"pageLoad\": 300000,\n \"script\": 30000\n },\n \"unhandledPromptBehavior\": \"dismiss and notify\",\n \"webauthn:extension:largeBlob\": true,\n \"webauthn:virtualAuthenticators\": true\n}", + "nodeId": "d44dcbc5-0b2c-4d5e-abf4-6f6aa5e0983c" + } + ] + } + } + }`), + browserName: "chrome", + sessionBrowserName: "chrome", + sessionBrowserVersion: "91.0.4472.114", + platformName: "linux", + }, + want: 3, + 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.sessionsPerNode, tt.args.setSessionsFromHub, logr.Discard()) + got, err := getCountFromSeleniumResponse(tt.args.b, tt.args.browserName, tt.args.browserVersion, tt.args.sessionBrowserName, tt.args.platformName, tt.args.sessionsPerNode, tt.args.setSessionsFromHub, tt.args.sessionBrowserVersion, logr.Discard()) if (err != nil) != tt.wantErr { t.Errorf("getCountFromSeleniumResponse() error = %v, wantErr %v", err, tt.wantErr) return From 1a7eab52abc14dbbd29b178e13ac485d28394e28 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Fri, 16 Aug 2024 12:24:20 +0000 Subject: [PATCH 11/13] add metadata tests Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler_test.go | 119 ++++++++++++----------- 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index 18790ec5f75..4797cc2cb8d 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -736,13 +736,14 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "chrome", - SessionBrowserName: "chrome", - TargetValue: 1, - BrowserVersion: "latest", - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + BrowserVersion: "latest", + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "latest", }, }, { @@ -758,13 +759,14 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "MicrosoftEdge", - SessionBrowserName: "msedge", - TargetValue: 1, - BrowserVersion: "latest", - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "MicrosoftEdge", + SessionBrowserName: "msedge", + TargetValue: 1, + BrowserVersion: "latest", + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "latest", }, }, { @@ -782,13 +784,14 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://user:password@selenium-hub:4444/graphql", - BrowserName: "MicrosoftEdge", - SessionBrowserName: "msedge", - TargetValue: 1, - BrowserVersion: "latest", - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://user:password@selenium-hub:4444/graphql", + BrowserName: "MicrosoftEdge", + SessionBrowserName: "msedge", + TargetValue: 1, + BrowserVersion: "latest", + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "latest", }, }, { @@ -805,14 +808,15 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "chrome", - SessionBrowserName: "chrome", - TargetValue: 1, - BrowserVersion: "91.0", - UnsafeSsl: false, - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + BrowserVersion: "91.0", + UnsafeSsl: false, + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "91.0", }, }, { @@ -830,15 +834,16 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "chrome", - SessionBrowserName: "chrome", - TargetValue: 1, - ActivationThreshold: 10, - BrowserVersion: "91.0", - UnsafeSsl: true, - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "91.0", }, }, { @@ -871,15 +876,16 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "chrome", - SessionBrowserName: "chrome", - TargetValue: 1, - ActivationThreshold: 10, - BrowserVersion: "91.0", - UnsafeSsl: true, - PlatformName: "linux", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "linux", + SessionsPerNode: 1, + SessionBrowserVersion: "91.0", }, }, { @@ -898,15 +904,16 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, wantErr: false, want: &seleniumGridScalerMetadata{ - URL: "http://selenium-hub:4444/graphql", - BrowserName: "chrome", - SessionBrowserName: "chrome", - TargetValue: 1, - ActivationThreshold: 10, - BrowserVersion: "91.0", - UnsafeSsl: true, - PlatformName: "Windows 11", - SessionsPerNode: 1, + URL: "http://selenium-hub:4444/graphql", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "Windows 11", + SessionsPerNode: 1, + SessionBrowserVersion: "91.0", }, }, } From 4e22dea90c13b340a5de4d2da63d17b5562c1dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Hanzl=C3=ADk?= Date: Tue, 20 Aug 2024 08:58:38 +0200 Subject: [PATCH 12/13] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jorge Turrado Ferrero Signed-off-by: Robert Hanzlík Signed-off-by: Hanzlik, Robert (MONETA) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f64faf28a1e..e44cb02e638 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Here is an overview of all new **experimental** features: ### Improvements -- selenium-grid: introduce new parameters setSessionsFromHub, sessionsPerNode and sessionBrowserVersion. ([#6080](https://github.com/kedacore/keda/issues/6080)) +- **Selenium Scaler**: introduce new parameters setSessionsFromHub, sessionsPerNode and sessionBrowserVersion. ([#6080](https://github.com/kedacore/keda/issues/6080)) ### Fixes From be8ea507e276a97171cf7abecbdca72ef14cd0c7 Mon Sep 17 00:00:00 2001 From: "Hanzlik, Robert (MONETA)" Date: Tue, 20 Aug 2024 08:15:50 +0000 Subject: [PATCH 13/13] make cyclomatic complexity smaller Signed-off-by: Hanzlik, Robert (MONETA) --- pkg/scalers/selenium_grid_scaler.go | 49 ++++++++++++++++------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index 79831540592..044874d5125 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -216,27 +216,7 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s } if setSessionsFromHub { - var nodes = seleniumResponse.Data.NodesInfo.Nodes - slots: - for _, node := range nodes { - var stereotypes = []stereotype{} - if err := json.Unmarshal([]byte(node.Stereotypes), &stereotypes); err == nil { - for _, stereotype := range stereotypes { - if stereotype.Stereotype.BrowserName == browserName { - var platformNameMatches = stereotype.Stereotype.PlatformName == "" || strings.EqualFold(stereotype.Stereotype.PlatformName, platformName) - if strings.HasPrefix(stereotype.Stereotype.BrowserVersion, browserVersion) && platformNameMatches { - slots = stereotype.Slots - break slots - } else if len(strings.TrimSpace(stereotype.Stereotype.BrowserVersion)) == 0 && browserVersion == DefaultBrowserVersion && platformNameMatches { - slots = stereotype.Slots - break slots - } - } - } - } else { - logger.Error(err, fmt.Sprintf("Error when unmarshalling stereotypes: %s", err)) - } - } + slots = getSlotsFromSeleniumResponse(seleniumResponse, browserName, browserVersion, platformName, logger) } var sessionQueueRequests = seleniumResponse.Data.SessionsInfo.SessionQueueRequests @@ -290,3 +270,30 @@ func getCountFromSeleniumResponse(b []byte, browserName string, browserVersion s return count, nil } + +func getSlotsFromSeleniumResponse(seleniumResponse seleniumResponse, browserName string, browserVersion string, platformName string, logger logr.Logger) int64 { + var slots int64 + + var nodes = seleniumResponse.Data.NodesInfo.Nodes +slots: + for _, node := range nodes { + var stereotypes = []stereotype{} + if err := json.Unmarshal([]byte(node.Stereotypes), &stereotypes); err == nil { + for _, stereotype := range stereotypes { + if stereotype.Stereotype.BrowserName == browserName { + var platformNameMatches = stereotype.Stereotype.PlatformName == "" || strings.EqualFold(stereotype.Stereotype.PlatformName, platformName) + if strings.HasPrefix(stereotype.Stereotype.BrowserVersion, browserVersion) && platformNameMatches { + slots = stereotype.Slots + break slots + } else if len(strings.TrimSpace(stereotype.Stereotype.BrowserVersion)) == 0 && browserVersion == DefaultBrowserVersion && platformNameMatches { + slots = stereotype.Slots + break slots + } + } + } + } else { + logger.Error(err, fmt.Sprintf("Error when unmarshalling stereotypes: %s", err)) + } + } + return slots +}