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 {
2021-02-16 18:55:55 +09:00
repo string
org string
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
} ,
// 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
// Job-level autoscaling
// 5 requested 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"}]} ` ,
} ,
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 )
t . Run ( fmt . Sprintf ( "case %d" , i ) , 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 {
2020-07-03 09:05:46 +09:00
Log : log ,
GitHubClient : client ,
Scheme : scheme ,
}
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 ,
} ,
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 ,
} ,
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 )
got , _ , _ , err := h . computeReplicasWithCache ( 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
}
Do not delay min/maxReplicas propagation from HRA to RD due to caching (#406)
As part of #282, I have introduced some caching mechanism to avoid excessive GitHub API calls due to the autoscaling calculation involving GitHub API calls is executed on each Webhook event.
Apparently, it was saving the wrong value in the cache- The value was one after applying `HRA.Spec.{Max,Min}Replicas` so manual changes to {Max,Min}Replicas doesn't affect RunnerDeployment.Spec.Replicas until the cache expires. This isn't what I had wanted.
This patch fixes that, by changing the value being cached to one before applying {Min,Max}Replicas.
Additionally, I've also updated logging so that you observe which number was fetched from cache, and what number was suggested by either TotalNumberOfQueuedAndInProgressWorkflowRuns or PercentageRunnersBusy, and what was the final number used as the desired-replicas(after applying {Min,Max}Replicas).
Follow-up for #282
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 {
2021-02-16 18:55:55 +09:00
repos [ ] string
org string
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
// Job-level autoscaling
// 5 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"}]} ` ,
} ,
want : 5 ,
} ,
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 )
t . Run ( fmt . Sprintf ( "case %d" , i ) , func ( t * testing . T ) {
Do not delay min/maxReplicas propagation from HRA to RD due to caching (#406)
As part of #282, I have introduced some caching mechanism to avoid excessive GitHub API calls due to the autoscaling calculation involving GitHub API calls is executed on each Webhook event.
Apparently, it was saving the wrong value in the cache- The value was one after applying `HRA.Spec.{Max,Min}Replicas` so manual changes to {Max,Min}Replicas doesn't affect RunnerDeployment.Spec.Replicas until the cache expires. This isn't what I had wanted.
This patch fixes that, by changing the value being cached to one before applying {Min,Max}Replicas.
Additionally, I've also updated logging so that you observe which number was fetched from cache, and what number was suggested by either TotalNumberOfQueuedAndInProgressWorkflowRuns or PercentageRunnersBusy, and what was the final number used as the desired-replicas(after applying {Min,Max}Replicas).
Follow-up for #282
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 {
2020-06-27 17:26:46 +09:00
Log : log ,
Scheme : scheme ,
2020-07-19 18:42:06 +09:00
GitHubClient : client ,
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 ,
} ,
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 )
got , _ , _ , err := h . computeReplicasWithCache ( 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
}
Do not delay min/maxReplicas propagation from HRA to RD due to caching (#406)
As part of #282, I have introduced some caching mechanism to avoid excessive GitHub API calls due to the autoscaling calculation involving GitHub API calls is executed on each Webhook event.
Apparently, it was saving the wrong value in the cache- The value was one after applying `HRA.Spec.{Max,Min}Replicas` so manual changes to {Max,Min}Replicas doesn't affect RunnerDeployment.Spec.Replicas until the cache expires. This isn't what I had wanted.
This patch fixes that, by changing the value being cached to one before applying {Min,Max}Replicas.
Additionally, I've also updated logging so that you observe which number was fetched from cache, and what number was suggested by either TotalNumberOfQueuedAndInProgressWorkflowRuns or PercentageRunnersBusy, and what was the final number used as the desired-replicas(after applying {Min,Max}Replicas).
Follow-up for #282
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
}
} )
}
}