mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 01:06:27 +00:00
Merge pull request #24537 from mwielgus/fix-race-hpa
Automatic merge from submit-queue Add locks in HPA test Fixes #23361
This commit is contained in:
commit
f3f3a685ab
@ -20,6 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -66,10 +67,12 @@ type fakeResource struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
|
sync.Mutex
|
||||||
minReplicas int
|
minReplicas int
|
||||||
maxReplicas int
|
maxReplicas int
|
||||||
initialReplicas int
|
initialReplicas int
|
||||||
desiredReplicas int
|
desiredReplicas int
|
||||||
|
|
||||||
// CPU target utilization as a percentage of the requested resources.
|
// CPU target utilization as a percentage of the requested resources.
|
||||||
CPUTarget int
|
CPUTarget int
|
||||||
CPUCurrent int
|
CPUCurrent int
|
||||||
@ -88,6 +91,7 @@ type testCase struct {
|
|||||||
resource *fakeResource
|
resource *fakeResource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needs to be called under a lock.
|
||||||
func (tc *testCase) computeCPUCurrent() {
|
func (tc *testCase) computeCPUCurrent() {
|
||||||
if len(tc.reportedLevels) != len(tc.reportedCPURequests) || len(tc.reportedLevels) == 0 {
|
if len(tc.reportedLevels) != len(tc.reportedCPURequests) || len(tc.reportedLevels) == 0 {
|
||||||
return
|
return
|
||||||
@ -111,6 +115,8 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
MatchLabels: map[string]string{"name": podNamePrefix},
|
MatchLabels: map[string]string{"name": podNamePrefix},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tc.Lock()
|
||||||
|
|
||||||
tc.scaleUpdated = false
|
tc.scaleUpdated = false
|
||||||
tc.statusUpdated = false
|
tc.statusUpdated = false
|
||||||
tc.eventCreated = false
|
tc.eventCreated = false
|
||||||
@ -126,9 +132,13 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
kind: "replicationcontrollers",
|
kind: "replicationcontrollers",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tc.Unlock()
|
||||||
|
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := &extensions.HorizontalPodAutoscalerList{
|
obj := &extensions.HorizontalPodAutoscalerList{
|
||||||
Items: []extensions.HorizontalPodAutoscaler{
|
Items: []extensions.HorizontalPodAutoscaler{
|
||||||
{
|
{
|
||||||
@ -154,6 +164,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if tc.CPUTarget > 0.0 {
|
if tc.CPUTarget > 0.0 {
|
||||||
obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget}
|
obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget}
|
||||||
}
|
}
|
||||||
@ -169,6 +180,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("get", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("get", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := &extensions.Scale{
|
obj := &extensions.Scale{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: tc.resource.name,
|
Name: tc.resource.name,
|
||||||
@ -186,6 +200,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("get", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("get", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := &extensions.Scale{
|
obj := &extensions.Scale{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: tc.resource.name,
|
Name: tc.resource.name,
|
||||||
@ -203,6 +220,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := &extensions.Scale{
|
obj := &extensions.Scale{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: tc.resource.name,
|
Name: tc.resource.name,
|
||||||
@ -220,6 +240,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := &api.PodList{}
|
obj := &api.PodList{}
|
||||||
for i := 0; i < len(tc.reportedCPURequests); i++ {
|
for i := 0; i < len(tc.reportedCPURequests); i++ {
|
||||||
podName := fmt.Sprintf("%s-%d", podNamePrefix, i)
|
podName := fmt.Sprintf("%s-%d", podNamePrefix, i)
|
||||||
@ -252,6 +275,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) {
|
fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
timestamp := time.Now()
|
timestamp := time.Now()
|
||||||
metrics := heapster.MetricResultList{}
|
metrics := heapster.MetricResultList{}
|
||||||
for _, level := range tc.reportedLevels {
|
for _, level := range tc.reportedLevels {
|
||||||
@ -266,6 +292,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("update", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("update", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
||||||
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
||||||
assert.Equal(t, tc.desiredReplicas, replicas)
|
assert.Equal(t, tc.desiredReplicas, replicas)
|
||||||
@ -274,6 +303,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("update", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("update", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
||||||
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
||||||
assert.Equal(t, tc.desiredReplicas, replicas)
|
assert.Equal(t, tc.desiredReplicas, replicas)
|
||||||
@ -282,6 +314,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
obj := action.(testclient.UpdateAction).GetObject().(*extensions.Scale)
|
||||||
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
replicas := action.(testclient.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas
|
||||||
assert.Equal(t, tc.desiredReplicas, replicas)
|
assert.Equal(t, tc.desiredReplicas, replicas)
|
||||||
@ -290,6 +325,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := action.(testclient.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler)
|
obj := action.(testclient.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler)
|
||||||
assert.Equal(t, namespace, obj.Namespace)
|
assert.Equal(t, namespace, obj.Namespace)
|
||||||
assert.Equal(t, hpaName, obj.Name)
|
assert.Equal(t, hpaName, obj.Name)
|
||||||
@ -305,6 +343,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fakeClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
obj := action.(testclient.CreateAction).GetObject().(*api.Event)
|
obj := action.(testclient.CreateAction).GetObject().(*api.Event)
|
||||||
if tc.verifyEvents {
|
if tc.verifyEvents {
|
||||||
assert.Equal(t, "SuccessfulRescale", obj.Reason)
|
assert.Equal(t, "SuccessfulRescale", obj.Reason)
|
||||||
@ -321,6 +362,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testCase) verifyResults(t *testing.T) {
|
func (tc *testCase) verifyResults(t *testing.T) {
|
||||||
|
tc.Lock()
|
||||||
|
defer tc.Unlock()
|
||||||
|
|
||||||
assert.Equal(t, tc.initialReplicas != tc.desiredReplicas, tc.scaleUpdated)
|
assert.Equal(t, tc.initialReplicas != tc.desiredReplicas, tc.scaleUpdated)
|
||||||
assert.True(t, tc.statusUpdated)
|
assert.True(t, tc.statusUpdated)
|
||||||
if tc.verifyEvents {
|
if tc.verifyEvents {
|
||||||
@ -351,9 +395,13 @@ func (tc *testCase) runTest(t *testing.T) {
|
|||||||
defer close(stop)
|
defer close(stop)
|
||||||
go hpaController.Run(stop)
|
go hpaController.Run(stop)
|
||||||
|
|
||||||
|
tc.Lock()
|
||||||
if tc.verifyEvents {
|
if tc.verifyEvents {
|
||||||
|
tc.Unlock()
|
||||||
// We need to wait for events to be broadcasted (sleep for longer than record.sleepDuration).
|
// We need to wait for events to be broadcasted (sleep for longer than record.sleepDuration).
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
} else {
|
||||||
|
tc.Unlock()
|
||||||
}
|
}
|
||||||
// Wait for HPA to be processed.
|
// Wait for HPA to be processed.
|
||||||
<-tc.processed
|
<-tc.processed
|
||||||
|
Loading…
Reference in New Issue
Block a user