2020-06-27 17:26:46 +09:00
package controllers
import (
2021-06-23 20:25:03 +09:00
"context"
2020-06-27 17:26:46 +09:00
"fmt"
2020-10-07 17:00:44 -07:00
"net/http/httptest"
"net/url"
"testing"
2021-06-22 17:55:06 +09:00
"github.com/actions-runner-controller/actions-runner-controller/api/v1alpha1"
"github.com/actions-runner-controller/actions-runner-controller/github"
"github.com/actions-runner-controller/actions-runner-controller/github/fake"
2020-06-27 17:26:46 +09:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)
func newGithubClient ( server * httptest . Server ) * github . Client {
2020-10-28 15:15:53 +02:00
c := github . Config {
Token : "token" ,
}
client , err := c . NewClient ( )
2020-06-27 17:26:46 +09:00
if err != nil {
panic ( err )
}
baseURL , err := url . Parse ( server . URL + "/" )
if err != nil {
panic ( err )
}
client . Client . BaseURL = baseURL
return client
}
func TestDetermineDesiredReplicas_RepositoryRunner ( t * testing . T ) {
intPtr := func ( v int ) * int {
return & v
}
metav1Now := metav1 . Now ( )
testcases := [ ] struct {
2022-04-24 14:41:34 +09:00
description string
repo string
org string
labels [ ] string
2021-02-16 18:55:55 +09:00
fixed * int
max * int
min * int
sReplicas * int
sTime * metav1 . Time
workflowRuns string
workflowRuns_queued string
workflowRuns_in_progress string
2020-10-07 17:00:44 -07:00
workflowJobs map [ int ] string
2020-06-27 17:26:46 +09:00
want int
err string
} {
2020-10-07 17:00:44 -07:00
// Legacy functionality
2020-06-27 17:26:46 +09:00
// 3 demanded, max at 3
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-06-27 17:26:46 +09:00
} ,
2022-04-24 14:41:34 +09:00
// Explicitly speified the default `self-hosted` label which is ignored by the simulator,
// as we assume that GitHub Actions automatically associates the `self-hosted` label to every self-hosted runner.
// 3 demanded, max at 3
{
repo : "test/valid" ,
labels : [ ] string { "self-hosted" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
} ,
2020-06-27 17:26:46 +09:00
// 2 demanded, max at 3, currently 3, delay scaling down due to grace period
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
sReplicas : intPtr ( 3 ) ,
sTime : & metav1Now ,
workflowRuns : ` { "total_count": 3, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-06-27 17:26:46 +09:00
} ,
// 3 demanded, max at 2
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 2 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-06-27 17:26:46 +09:00
} ,
// 2 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 3, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-06-27 17:26:46 +09:00
} ,
// 1 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"queued"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 0, "workflow_runs":[]}" ` ,
want : 2 ,
2020-06-27 17:26:46 +09:00
} ,
// 1 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-06-27 17:26:46 +09:00
} ,
// 1 demanded, min at 1
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"queued"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 0, "workflow_runs":[]}" ` ,
want : 1 ,
2020-06-27 17:26:46 +09:00
} ,
// 1 demanded, min at 1
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 1 ,
2020-06-27 17:26:46 +09:00
} ,
// fixed at 3
{
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
fixed : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 3, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-06-27 17:26:46 +09:00
} ,
2020-10-07 17:00:44 -07:00
{
2022-04-28 00:24:21 +09:00
description : "Job-level autoscaling with no explicit runner label (runners have implicit self-hosted, requested self-hosted, 5 jobs from 3 workflows)" ,
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"completed", "labels":["self-hosted"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
} ,
want : 5 ,
} ,
{
description : "Skipped job-level autoscaling with no explicit runner label (runners have implicit self-hosted, requested self-hosted+custom, 0 jobs from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
2022-04-28 00:24:21 +09:00
want : 2 ,
2022-04-24 14:41:34 +09:00
} ,
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling with no label (runners have implicit self-hosted, jobs had no labels, 0 jobs from 3 workflows)" ,
2021-02-16 18:55:55 +09:00
repo : "test/valid" ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
2020-10-07 17:00:44 -07:00
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued"}, { "status":"queued"}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress"}, { "status":"completed"}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress"}, { "status":"queued"}]} ` ,
} ,
2022-04-24 14:41:34 +09:00
want : 2 ,
} ,
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling with default runner label (runners have self-hosted only, requested self-hosted+custom, 0 jobs from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
labels : [ ] string { "self-hosted" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
2022-04-28 00:24:21 +09:00
want : 2 ,
2022-04-24 14:41:34 +09:00
} ,
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling with custom runner label (runners have custom2, requested self-hosted+custom, 0 jobs from 5 workflows" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
labels : [ ] string { "custom2" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
want : 2 ,
} ,
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling with default runner label (runners have self-hosted, requested managed-runner-label, 0 jobs from 3 runs)" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
labels : [ ] string { "self-hosted" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["managed-runner-label"]}, { "status":"queued", "labels":["managed-runner-label"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["managed-runner-label"]}, { "status":"completed", "labels":["managed-runner-label"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["managed-runner-label"]}, { "status":"queued", "labels":["managed-runner-label"]}]} ` ,
} ,
want : 2 ,
} ,
{
2022-04-28 00:24:21 +09:00
description : "Job-level autoscaling with default + custom runner label (runners have self-hosted+custom, requested self-hosted+custom, 5 jobs from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
labels : [ ] string { "self-hosted" , "custom" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
want : 5 ,
} ,
{
2022-04-28 00:24:21 +09:00
description : "Job-level autoscaling with custom runner label (runners have custom, requested self-hosted+custom, 5 jobs from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
repo : "test/valid" ,
labels : [ ] string { "custom" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
2020-10-07 17:00:44 -07:00
want : 5 ,
} ,
2020-07-03 09:05:46 +09:00
}
for i := range testcases {
tc := testcases [ i ]
log := zap . New ( func ( o * zap . Options ) {
o . Development = true
} )
scheme := runtime . NewScheme ( )
_ = clientgoscheme . AddToScheme ( scheme )
_ = v1alpha1 . AddToScheme ( scheme )
2022-04-24 14:41:34 +09:00
testName := fmt . Sprintf ( "case %d" , i )
if tc . description != "" {
testName = tc . description
}
t . Run ( testName , func ( t * testing . T ) {
2021-02-07 17:37:27 +09:00
server := fake . NewServer (
2021-02-16 18:55:55 +09:00
fake . WithListRepositoryWorkflowRunsResponse ( 200 , tc . workflowRuns , tc . workflowRuns_queued , tc . workflowRuns_in_progress ) ,
2021-02-07 17:37:27 +09:00
fake . WithListWorkflowJobsResponse ( 200 , tc . workflowJobs ) ,
fake . WithListRunnersResponse ( 200 , fake . RunnersListBody ) ,
)
2020-07-03 09:05:46 +09:00
defer server . Close ( )
client := newGithubClient ( server )
2020-07-19 18:42:06 +09:00
h := & HorizontalRunnerAutoscalerReconciler {
2022-04-20 03:09:09 +01:00
Log : log ,
Scheme : scheme ,
DefaultScaleDownDelay : DefaultScaleDownDelay ,
2020-07-03 09:05:46 +09:00
}
rd := v1alpha1 . RunnerDeployment {
TypeMeta : metav1 . TypeMeta { } ,
2020-07-19 18:42:06 +09:00
ObjectMeta : metav1 . ObjectMeta {
Name : "testrd" ,
} ,
2020-07-03 09:05:46 +09:00
Spec : v1alpha1 . RunnerDeploymentSpec {
Template : v1alpha1 . RunnerTemplate {
Spec : v1alpha1 . RunnerSpec {
2021-06-22 17:10:09 +09:00
RunnerConfig : v1alpha1 . RunnerConfig {
Repository : tc . repo ,
2022-04-24 14:41:34 +09:00
Labels : tc . labels ,
2021-06-22 17:10:09 +09:00
} ,
2020-07-03 09:05:46 +09:00
} ,
} ,
2020-07-19 18:42:06 +09:00
Replicas : tc . fixed ,
} ,
Status : v1alpha1 . RunnerDeploymentStatus {
2021-05-22 08:29:53 +09:00
DesiredReplicas : tc . sReplicas ,
2020-07-19 18:42:06 +09:00
} ,
}
hra := v1alpha1 . HorizontalRunnerAutoscaler {
Spec : v1alpha1 . HorizontalRunnerAutoscalerSpec {
2020-07-03 09:05:46 +09:00
MaxReplicas : tc . max ,
MinReplicas : tc . min ,
2022-04-24 13:36:42 +09:00
Metrics : [ ] v1alpha1 . MetricSpec {
{
Type : "TotalNumberOfQueuedAndInProgressWorkflowRuns" ,
} ,
} ,
2020-07-03 09:05:46 +09:00
} ,
2020-07-19 18:42:06 +09:00
Status : v1alpha1 . HorizontalRunnerAutoscalerStatus {
DesiredReplicas : tc . sReplicas ,
2020-07-03 09:05:46 +09:00
LastSuccessfulScaleOutTime : tc . sTime ,
} ,
}
2021-05-22 08:29:53 +09:00
minReplicas , _ , _ , err := h . getMinReplicas ( log , metav1Now . Time , hra )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2021-06-23 20:25:03 +09:00
st := h . scaleTargetFromRD ( context . Background ( ) , rd )
2022-07-12 09:45:00 +09:00
got , err := h . computeReplicasWithCache ( client , log , metav1Now . Time , st , hra , minReplicas )
2020-07-03 09:05:46 +09:00
if err != nil {
if tc . err == "" {
t . Fatalf ( "unexpected error: expected none, got %v" , err )
} else if err . Error ( ) != tc . err {
t . Fatalf ( "unexpected error: expected %v, got %v" , tc . err , err )
}
return
}
2021-03-19 12:58:02 +09:00
if got != tc . want {
t . Errorf ( "%d: incorrect desired replicas: want %d, got %d" , i , tc . want , got )
2020-07-03 09:05:46 +09:00
}
} )
}
}
func TestDetermineDesiredReplicas_OrganizationalRunner ( t * testing . T ) {
intPtr := func ( v int ) * int {
return & v
}
metav1Now := metav1 . Now ( )
testcases := [ ] struct {
2022-04-24 14:41:34 +09:00
description string
repos [ ] string
org string
labels [ ] string
2021-02-16 18:55:55 +09:00
fixed * int
max * int
min * int
sReplicas * int
sTime * metav1 . Time
workflowRuns string
workflowRuns_queued string
workflowRuns_in_progress string
2020-10-07 17:00:44 -07:00
workflowJobs map [ int ] string
2020-07-03 09:05:46 +09:00
want int
err string
} {
// 3 demanded, max at 3
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-07-03 09:05:46 +09:00
} ,
// 2 demanded, max at 3, currently 3, delay scaling down due to grace period
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
sReplicas : intPtr ( 3 ) ,
sTime : & metav1Now ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-07-03 09:05:46 +09:00
} ,
// 3 demanded, max at 2
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 2 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-07-03 09:05:46 +09:00
} ,
// 2 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 3, "workflow_runs":[ { "status":"queued"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-07-03 09:05:46 +09:00
} ,
// 1 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"queued"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 0, "workflow_runs":[]}" ` ,
want : 2 ,
2020-07-03 09:05:46 +09:00
} ,
// 1 demanded, min at 2
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 2 ,
2020-07-03 09:05:46 +09:00
} ,
// 1 demanded, min at 1
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"queued"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 0, "workflow_runs":[]}" ` ,
want : 1 ,
2020-07-03 09:05:46 +09:00
} ,
// 1 demanded, min at 1
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
want : 1 ,
2020-07-03 09:05:46 +09:00
} ,
// fixed at 3
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
fixed : intPtr ( 1 ) ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 3, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-07-03 09:05:46 +09:00
} ,
2020-06-27 17:26:46 +09:00
// org runner, fixed at 3
{
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
fixed : intPtr ( 1 ) ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 3, "workflow_runs":[ { "status":"in_progress"}, { "status":"in_progress"}, { "status":"in_progress"}]}" ` ,
want : 3 ,
2020-06-27 17:26:46 +09:00
} ,
2020-07-03 09:05:46 +09:00
// org runner, 1 demanded, min at 1, no repos
2020-06-27 17:26:46 +09:00
{
2021-02-16 18:55:55 +09:00
org : "test" ,
min : intPtr ( 1 ) ,
max : intPtr ( 3 ) ,
workflowRuns : ` { "total_count": 2, "workflow_runs":[ { "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 0, "workflow_runs":[]}" ` ,
workflowRuns_in_progress : ` { "total_count": 1, "workflow_runs":[ { "status":"in_progress"}]}" ` ,
err : "validating autoscaling metrics: spec.autoscaling.metrics[].repositoryNames is required and must have one more more entries for organizational runner deployment" ,
2020-06-27 17:26:46 +09:00
} ,
2020-10-07 17:00:44 -07:00
{
2022-04-28 00:24:21 +09:00
description : "Job-level autoscaling (runners have implicit self-hosted, requested self-hosted, 5 jobs from 3 runs)" ,
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"completed", "labels":["self-hosted"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
} ,
want : 5 ,
} ,
{
description : "Job-level autoscaling (runners have explicit self-hosted, requested self-hosted, 5 jobs from 3 runs)" ,
org : "test" ,
repos : [ ] string { "valid" } ,
labels : [ ] string { "self-hosted" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"completed", "labels":["self-hosted"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted"]}, { "status":"queued", "labels":["self-hosted"]}]} ` ,
} ,
want : 5 ,
} ,
{
description : "Skipped job-level autoscaling (jobs lack labels, 0 requested from 3 workflows)" ,
2021-02-16 18:55:55 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
2020-10-07 17:00:44 -07:00
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued"}, { "status":"queued"}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress"}, { "status":"completed"}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress"}, { "status":"queued"}]} ` ,
} ,
2022-04-24 14:41:34 +09:00
want : 2 ,
} ,
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling (runners have valid and implicit self-hosted, requested self-hosted+custom, 0 jobs from 3 runs)" ,
2022-04-24 14:41:34 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
2022-04-28 00:24:21 +09:00
want : 2 ,
2020-10-07 17:00:44 -07:00
} ,
2022-04-24 14:41:34 +09:00
{
2022-04-28 00:24:21 +09:00
description : "Skipped job-level autoscaling (runners have self-hosted, requested self-hosted+custom, 0 jobs from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
labels : [ ] string { "self-hosted" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
2022-04-28 00:24:21 +09:00
want : 2 ,
2022-04-24 14:41:34 +09:00
} ,
{
2022-04-28 00:24:21 +09:00
description : "Job-level autoscaling (runners have custom, requested self-hosted+custom, 5 requested from 3 workflows)" ,
2022-04-24 14:41:34 +09:00
org : "test" ,
repos : [ ] string { "valid" } ,
labels : [ ] string { "custom" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
want : 5 ,
} ,
2022-04-28 00:24:21 +09:00
{
description : "Job-level autoscaling (runners have custom, requested custom, 5 requested from 3 workflows)" ,
org : "test" ,
repos : [ ] string { "valid" } ,
labels : [ ] string { "custom" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["custom"]}, { "status":"queued", "labels":["custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["custom"]}, { "status":"completed", "labels":["custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["custom"]}, { "status":"queued", "labels":["custom"]}]} ` ,
} ,
want : 5 ,
} ,
2022-04-24 14:41:34 +09:00
{
description : "Skipped job-level autoscaling (specified custom2, 0 requested from 3 workflows)" ,
org : "test" ,
repos : [ ] string { "valid" } ,
labels : [ ] string { "custom2" } ,
min : intPtr ( 2 ) ,
max : intPtr ( 10 ) ,
workflowRuns : ` { "total_count": 4, "workflow_runs":[ { "id": 1, "status":"queued"}, { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowRuns_queued : ` { "total_count": 1, "workflow_runs":[ { "id": 1, "status":"queued"}]}" ` ,
workflowRuns_in_progress : ` { "total_count": 2, "workflow_runs":[ { "id": 2, "status":"in_progress"}, { "id": 3, "status":"in_progress"}, { "status":"completed"}]}" ` ,
workflowJobs : map [ int ] string {
1 : ` { "jobs": [ { "status":"queued", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
2 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"completed", "labels":["self-hosted", "custom"]}]} ` ,
3 : ` { "jobs": [ { "status": "in_progress", "labels":["self-hosted", "custom"]}, { "status":"queued", "labels":["self-hosted", "custom"]}]} ` ,
} ,
want : 2 ,
} ,
2020-06-27 17:26:46 +09:00
}
for i := range testcases {
tc := testcases [ i ]
log := zap . New ( func ( o * zap . Options ) {
o . Development = true
} )
scheme := runtime . NewScheme ( )
_ = clientgoscheme . AddToScheme ( scheme )
_ = v1alpha1 . AddToScheme ( scheme )
2022-04-24 14:41:34 +09:00
testName := fmt . Sprintf ( "case %d" , i )
if tc . description != "" {
testName = tc . description
}
t . Run ( testName , func ( t * testing . T ) {
2021-03-19 12:58:02 +09:00
t . Helper ( )
2021-02-07 17:37:27 +09:00
server := fake . NewServer (
2021-02-16 18:55:55 +09:00
fake . WithListRepositoryWorkflowRunsResponse ( 200 , tc . workflowRuns , tc . workflowRuns_queued , tc . workflowRuns_in_progress ) ,
2021-02-07 17:37:27 +09:00
fake . WithListWorkflowJobsResponse ( 200 , tc . workflowJobs ) ,
fake . WithListRunnersResponse ( 200 , fake . RunnersListBody ) ,
)
2020-06-27 17:26:46 +09:00
defer server . Close ( )
client := newGithubClient ( server )
2020-07-19 18:42:06 +09:00
h := & HorizontalRunnerAutoscalerReconciler {
2022-04-20 03:09:09 +01:00
Log : log ,
Scheme : scheme ,
DefaultScaleDownDelay : DefaultScaleDownDelay ,
2020-06-27 17:26:46 +09:00
}
rd := v1alpha1 . RunnerDeployment {
2020-07-19 18:42:06 +09:00
ObjectMeta : metav1 . ObjectMeta {
Name : "testrd" ,
} ,
2020-06-27 17:26:46 +09:00
Spec : v1alpha1 . RunnerDeploymentSpec {
2021-03-05 10:15:39 +09:00
Selector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"foo" : "bar" ,
} ,
} ,
2020-06-27 17:26:46 +09:00
Template : v1alpha1 . RunnerTemplate {
2021-03-05 10:15:39 +09:00
ObjectMeta : metav1 . ObjectMeta {
Labels : map [ string ] string {
"foo" : "bar" ,
} ,
} ,
2020-06-27 17:26:46 +09:00
Spec : v1alpha1 . RunnerSpec {
2021-06-22 17:10:09 +09:00
RunnerConfig : v1alpha1 . RunnerConfig {
Organization : tc . org ,
2022-04-24 14:41:34 +09:00
Labels : tc . labels ,
2021-06-22 17:10:09 +09:00
} ,
2020-07-03 09:05:46 +09:00
} ,
} ,
2020-07-19 18:42:06 +09:00
Replicas : tc . fixed ,
} ,
Status : v1alpha1 . RunnerDeploymentStatus {
2021-05-22 08:29:53 +09:00
DesiredReplicas : tc . sReplicas ,
2020-07-19 18:42:06 +09:00
} ,
}
hra := v1alpha1 . HorizontalRunnerAutoscaler {
Spec : v1alpha1 . HorizontalRunnerAutoscalerSpec {
ScaleTargetRef : v1alpha1 . ScaleTargetRef {
Name : "testrd" ,
2020-06-27 17:26:46 +09:00
} ,
MaxReplicas : tc . max ,
MinReplicas : tc . min ,
2020-07-19 18:42:06 +09:00
Metrics : [ ] v1alpha1 . MetricSpec {
{
Type : v1alpha1 . AutoscalingMetricTypeTotalNumberOfQueuedAndInProgressWorkflowRuns ,
RepositoryNames : tc . repos ,
} ,
} ,
2020-06-27 17:26:46 +09:00
} ,
2020-07-19 18:42:06 +09:00
Status : v1alpha1 . HorizontalRunnerAutoscalerStatus {
DesiredReplicas : tc . sReplicas ,
2020-06-27 17:26:46 +09:00
LastSuccessfulScaleOutTime : tc . sTime ,
} ,
}
2021-05-22 08:29:53 +09:00
minReplicas , _ , _ , err := h . getMinReplicas ( log , metav1Now . Time , hra )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
2021-06-23 20:25:03 +09:00
st := h . scaleTargetFromRD ( context . Background ( ) , rd )
2022-07-12 09:45:00 +09:00
got , err := h . computeReplicasWithCache ( client , log , metav1Now . Time , st , hra , minReplicas )
2020-06-27 17:26:46 +09:00
if err != nil {
if tc . err == "" {
t . Fatalf ( "unexpected error: expected none, got %v" , err )
} else if err . Error ( ) != tc . err {
t . Fatalf ( "unexpected error: expected %v, got %v" , tc . err , err )
}
return
}
2021-03-19 12:58:02 +09:00
if got != tc . want {
t . Errorf ( "%d: incorrect desired replicas: want %d, got %d" , i , tc . want , got )
2020-06-27 17:26:46 +09:00
}
} )
}
}