Merge pull request #55376 from yuexiao-wang/add-validate

Automatic merge from submit-queue (batch tested with PRs 55900, 55995, 55913, 55467, 55376). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Improve unit test coverage of scale

**What this PR does / why we need it**:
1. Add unit test of ReplicaSet and StatefulSet to improve coverage of scale
2. Fix variable "fake" collideds with imported package name
3. Use Error with no value format and fix typo error messages

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2017-12-14 00:45:25 -08:00 committed by GitHub
commit 2a70dc8746
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 531 additions and 4 deletions

View File

@ -41,11 +41,13 @@ go_test(
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",

View File

@ -23,10 +23,12 @@ import (
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testcore "k8s.io/client-go/testing"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
appsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion"
batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
@ -321,7 +323,7 @@ func TestJobScaleRetry(t *testing.T) {
scaleFunc = ScaleCondition(&scaler, &preconditions, namespace, name, count, nil)
pass, err = scaleFunc()
if err == nil {
t.Errorf("Expected error on precondition failure")
t.Error("Expected error on precondition failure")
}
}
@ -347,7 +349,7 @@ func TestJobScale(t *testing.T) {
t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name)
}
if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != batch.Resource("jobs") || *action.GetObject().(*batch.Job).Spec.Parallelism != int32(count) {
t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count)
@ -583,7 +585,7 @@ func TestDeploymentScaleRetry(t *testing.T) {
scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil)
pass, err = scaleFunc()
if err == nil {
t.Errorf("Expected error on precondition failure")
t.Error("Expected error on precondition failure")
}
}
@ -609,7 +611,7 @@ func TestDeploymentScale(t *testing.T) {
t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("deployments") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
}
if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != extensions.Resource("deployments") || action.GetObject().(*extensions.Deployment).Spec.Replicas != int32(count) {
t.Errorf("unexpected action %v, expected update-deployment with replicas = %d", actions[1], count)
@ -785,3 +787,526 @@ func TestValidateDeployment(t *testing.T) {
}
}
}
type ErrorStatefulSets struct {
appsclient.StatefulSetInterface
conflict bool
invalid bool
}
func (c *ErrorStatefulSets) Update(statefulSet *apps.StatefulSet) (*apps.StatefulSet, error) {
switch {
case c.invalid:
return nil, kerrors.NewInvalid(api.Kind(statefulSet.Kind), statefulSet.Name, nil)
case c.conflict:
return nil, kerrors.NewConflict(api.Resource(statefulSet.Kind), statefulSet.Name, nil)
}
return nil, errors.New("statefulSet update failure")
}
func (c *ErrorStatefulSets) Get(name string, options metav1.GetOptions) (*apps.StatefulSet, error) {
return &apps.StatefulSet{
Spec: apps.StatefulSetSpec{
Replicas: 0,
},
}, nil
}
type ErrorStatefulSetClient struct {
appsclient.StatefulSetsGetter
conflict bool
invalid bool
}
func (c *ErrorStatefulSetClient) StatefulSets(namespace string) appsclient.StatefulSetInterface {
return &ErrorStatefulSets{
StatefulSetInterface: c.StatefulSetsGetter.StatefulSets(namespace),
invalid: c.invalid,
conflict: c.conflict,
}
}
func statefulSet() *apps.StatefulSet {
return &apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Name: "foo",
},
}
}
func TestStatefulSetScale(t *testing.T) {
fake := fake.NewSimpleClientset(statefulSet())
scaler := StatefulSetScaler{fake.Apps()}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
actions := fake.Actions()
if len(actions) != 2 {
t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-statefulsets %s", actions[0], name)
}
if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetObject().(*apps.StatefulSet).Spec.Replicas != int32(count) {
t.Errorf("unexpected action %v, expected update-statefulset with replicas = %d", actions[1], count)
}
}
func TestStatefulSetScaleRetry(t *testing.T) {
fake := &ErrorStatefulSetClient{StatefulSetsGetter: fake.NewSimpleClientset().Apps(), conflict: true}
scaler := &StatefulSetScaler{fake}
preconditions := &ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil)
pass, err := scaleFunc()
if pass != false {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
if err != nil {
t.Errorf("Did not expect an error on update failure, got %v", err)
}
preconditions = &ScalePrecondition{3, ""}
scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil)
pass, err = scaleFunc()
if err == nil {
t.Error("Expected error on precondition failure")
}
}
func TestStatefulSetScaleInvalid(t *testing.T) {
fake := &ErrorStatefulSetClient{StatefulSetsGetter: fake.NewSimpleClientset().Apps(), invalid: true}
scaler := StatefulSetScaler{fake}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil)
pass, err := scaleFunc()
if pass {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
e, ok := err.(ScaleError)
if err == nil || !ok || e.FailureType != ScaleUpdateFailure {
t.Errorf("Expected error on invalid update failure, got %v", err)
}
}
func TestStatefulSetScaleFailsPreconditions(t *testing.T) {
fake := fake.NewSimpleClientset(&apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Name: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: 10,
},
})
scaler := StatefulSetScaler{fake.Apps()}
preconditions := ScalePrecondition{2, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
actions := fake.Actions()
if len(actions) != 1 {
t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != apps.Resource("statefulsets") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-statefulset %s", actions[0], name)
}
}
func TestValidateStatefulSet(t *testing.T) {
zero, ten, twenty := int32(0), int32(10), int32(20)
tests := []struct {
preconditions ScalePrecondition
statefulset apps.StatefulSet
expectError bool
test string
}{
{
preconditions: ScalePrecondition{-1, ""},
expectError: false,
test: "defaults",
},
{
preconditions: ScalePrecondition{-1, ""},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "defaults 2",
},
{
preconditions: ScalePrecondition{0, ""},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: zero,
},
},
expectError: false,
test: "size matches",
},
{
preconditions: ScalePrecondition{-1, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "resource version matches",
},
{
preconditions: ScalePrecondition{10, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "both match",
},
{
preconditions: ScalePrecondition{10, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: twenty,
},
},
expectError: true,
test: "size different",
},
{
preconditions: ScalePrecondition{10, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
},
expectError: true,
test: "no replicas",
},
{
preconditions: ScalePrecondition{10, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "bar",
},
Spec: apps.StatefulSetSpec{
Replicas: ten,
},
},
expectError: true,
test: "version different",
},
{
preconditions: ScalePrecondition{10, "foo"},
statefulset: apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "bar",
},
Spec: apps.StatefulSetSpec{
Replicas: twenty,
},
},
expectError: true,
test: "both different",
},
}
for _, test := range tests {
err := test.preconditions.ValidateStatefulSet(&test.statefulset)
if err != nil && !test.expectError {
t.Errorf("unexpected error: %v (%s)", err, test.test)
}
if err == nil && test.expectError {
t.Errorf("expected an error: %v (%s)", err, test.test)
}
}
}
type ErrorReplicaSets struct {
extensionsclient.ReplicaSetInterface
conflict bool
invalid bool
}
func (c *ErrorReplicaSets) Update(replicaSets *extensions.ReplicaSet) (*extensions.ReplicaSet, error) {
switch {
case c.invalid:
return nil, kerrors.NewInvalid(api.Kind(replicaSets.Kind), replicaSets.Name, nil)
case c.conflict:
return nil, kerrors.NewConflict(api.Resource(replicaSets.Kind), replicaSets.Name, nil)
}
return nil, errors.New("replicaSets update failure")
}
func (c *ErrorReplicaSets) Get(name string, options metav1.GetOptions) (*extensions.ReplicaSet, error) {
return &extensions.ReplicaSet{
Spec: extensions.ReplicaSetSpec{
Replicas: 0,
},
}, nil
}
type ErrorReplicaSetClient struct {
extensionsclient.ReplicaSetsGetter
conflict bool
invalid bool
}
func (c *ErrorReplicaSetClient) ReplicaSets(namespace string) extensionsclient.ReplicaSetInterface {
return &ErrorReplicaSets{
ReplicaSetInterface: c.ReplicaSetsGetter.ReplicaSets(namespace),
invalid: c.invalid,
conflict: c.conflict,
}
}
func replicaSet() *extensions.ReplicaSet {
return &extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Name: "foo",
},
}
}
func TestReplicaSetScale(t *testing.T) {
fake := fake.NewSimpleClientset(replicaSet())
scaler := ReplicaSetScaler{fake.Extensions()}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
actions := fake.Actions()
if len(actions) != 2 {
t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-replicationSet %s", actions[0], name)
}
if action, ok := actions[1].(testcore.UpdateAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetObject().(*extensions.ReplicaSet).Spec.Replicas != int32(count) {
t.Errorf("unexpected action %v, expected update-replicaSet with replicas = %d", actions[1], count)
}
}
func TestReplicaSetScaleRetry(t *testing.T) {
fake := &ErrorReplicaSetClient{ReplicaSetsGetter: fake.NewSimpleClientset().Extensions(), conflict: true}
scaler := &ReplicaSetScaler{fake}
preconditions := &ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count, nil)
pass, err := scaleFunc()
if pass != false {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
if err != nil {
t.Errorf("Did not expect an error on update failure, got %v", err)
}
preconditions = &ScalePrecondition{3, ""}
scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil)
pass, err = scaleFunc()
if err == nil {
t.Error("Expected error on precondition failure")
}
}
func TestReplicaSetScaleInvalid(t *testing.T) {
fake := &ErrorReplicaSetClient{ReplicaSetsGetter: fake.NewSimpleClientset().Extensions(), invalid: true}
scaler := ReplicaSetScaler{fake}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count, nil)
pass, err := scaleFunc()
if pass {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
e, ok := err.(ScaleError)
if err == nil || !ok || e.FailureType != ScaleUpdateFailure {
t.Errorf("Expected error on invalid update failure, got %v", err)
}
}
func TestReplicaSetsGetterFailsPreconditions(t *testing.T) {
fake := fake.NewSimpleClientset(&extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: metav1.NamespaceDefault,
Name: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: 10,
},
})
scaler := ReplicaSetScaler{fake.Extensions()}
preconditions := ScalePrecondition{2, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
actions := fake.Actions()
if len(actions) != 1 {
t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions)
}
if action, ok := actions[0].(testcore.GetAction); !ok || action.GetResource().GroupResource() != extensions.Resource("replicasets") || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-replicaSets %s", actions[0], name)
}
}
func TestValidateReplicaSets(t *testing.T) {
zero, ten, twenty := int32(0), int32(10), int32(20)
tests := []struct {
preconditions ScalePrecondition
replicaSets extensions.ReplicaSet
expectError bool
test string
}{
{
preconditions: ScalePrecondition{-1, ""},
expectError: false,
test: "defaults",
},
{
preconditions: ScalePrecondition{-1, ""},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "defaults 2",
},
{
preconditions: ScalePrecondition{0, ""},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: zero,
},
},
expectError: false,
test: "size matches",
},
{
preconditions: ScalePrecondition{-1, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "resource version matches",
},
{
preconditions: ScalePrecondition{10, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: ten,
},
},
expectError: false,
test: "both match",
},
{
preconditions: ScalePrecondition{10, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
Spec: extensions.ReplicaSetSpec{
Replicas: twenty,
},
},
expectError: true,
test: "size different",
},
{
preconditions: ScalePrecondition{10, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "foo",
},
},
expectError: true,
test: "no replicas",
},
{
preconditions: ScalePrecondition{10, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "bar",
},
Spec: extensions.ReplicaSetSpec{
Replicas: ten,
},
},
expectError: true,
test: "version different",
},
{
preconditions: ScalePrecondition{10, "foo"},
replicaSets: extensions.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "bar",
},
Spec: extensions.ReplicaSetSpec{
Replicas: twenty,
},
},
expectError: true,
test: "both different",
},
}
for _, test := range tests {
err := test.preconditions.ValidateReplicaSet(&test.replicaSets)
if err != nil && !test.expectError {
t.Errorf("unexpected error: %v (%s)", err, test.test)
}
if err == nil && test.expectError {
t.Errorf("expected an error: %v (%s)", err, test.test)
}
}
}