mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #31111 from fraenkel/scale_subresource
Automatic merge from submit-queue Use scale subresource Fixes #29698 Use scale subresource for ReplicationController, ReplicaSet and Deployment. Couldn't do Jobs and PetSet since they live in a different group.
This commit is contained in:
		@@ -54,14 +54,23 @@ type ObjectScheme interface {
 | 
			
		||||
// Object or error that matches the requested action. For instance, list-replicationControllers
 | 
			
		||||
// should attempt to return a list of replication controllers. This method delegates to the
 | 
			
		||||
// ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items.
 | 
			
		||||
// TODO: add support for sub resources
 | 
			
		||||
func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
 | 
			
		||||
 | 
			
		||||
	return func(action Action) (bool, runtime.Object, error) {
 | 
			
		||||
		kind, err := mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetResource()})
 | 
			
		||||
		var err error
 | 
			
		||||
		var kind unversioned.GroupVersionKind
 | 
			
		||||
 | 
			
		||||
		if action.GetSubresource() != "" {
 | 
			
		||||
			kind, err = mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetSubresource()})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false, nil, fmt.Errorf("unrecognized subresource action %s/%s: %v", action.GetResource(), action.GetSubresource(), err)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			kind, err = mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetResource()})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO: have mapper return a Kind for a subresource?
 | 
			
		||||
		switch castAction := action.(type) {
 | 
			
		||||
 
 | 
			
		||||
@@ -143,13 +143,13 @@ func (precondition *ScalePrecondition) ValidatePetSet(ps *apps.PetSet) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateReplicationController ensures that the preconditions match.  Returns nil if they are valid, an error otherwise
 | 
			
		||||
func (precondition *ScalePrecondition) ValidateReplicationController(controller *api.ReplicationController) error {
 | 
			
		||||
	if precondition.Size != -1 && int(controller.Spec.Replicas) != precondition.Size {
 | 
			
		||||
		return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(controller.Spec.Replicas))}
 | 
			
		||||
// ValidateScale ensures that the preconditions match.  Returns nil if they are valid, an error otherwise
 | 
			
		||||
func (precondition *ScalePrecondition) ValidateScale(scale *extensions.Scale) error {
 | 
			
		||||
	if precondition.Size != -1 && int(scale.Spec.Replicas) != precondition.Size {
 | 
			
		||||
		return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(scale.Spec.Replicas))}
 | 
			
		||||
	}
 | 
			
		||||
	if len(precondition.ResourceVersion) != 0 && controller.ResourceVersion != precondition.ResourceVersion {
 | 
			
		||||
		return PreconditionError{"resource version", precondition.ResourceVersion, controller.ResourceVersion}
 | 
			
		||||
	if len(precondition.ResourceVersion) != 0 && scale.ResourceVersion != precondition.ResourceVersion {
 | 
			
		||||
		return PreconditionError{"resource version", precondition.ResourceVersion, scale.ResourceVersion}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -161,24 +161,24 @@ type ReplicationControllerScaler struct {
 | 
			
		||||
// ScaleSimple does a simple one-shot attempt at scaling. It returns the
 | 
			
		||||
// resourceVersion of the replication controller if the update is successful.
 | 
			
		||||
func (scaler *ReplicationControllerScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) {
 | 
			
		||||
	controller, err := scaler.c.ReplicationControllers(namespace).Get(name)
 | 
			
		||||
	sc := scaler.c.Extensions().Scales(namespace)
 | 
			
		||||
	scale, err := sc.Get("ReplicationController", name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", ScaleError{ScaleGetFailure, "Unknown", err}
 | 
			
		||||
	}
 | 
			
		||||
	if preconditions != nil {
 | 
			
		||||
		if err := preconditions.ValidateReplicationController(controller); err != nil {
 | 
			
		||||
		if err := preconditions.ValidateScale(scale); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	controller.Spec.Replicas = int32(newSize)
 | 
			
		||||
	updatedRC, err := scaler.c.ReplicationControllers(namespace).Update(controller)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	scale.Spec.Replicas = int32(newSize)
 | 
			
		||||
	if _, err := sc.Update("ReplicationController", scale); err != nil {
 | 
			
		||||
		if errors.IsConflict(err) {
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, controller.ResourceVersion, err}
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, scale.ResourceVersion, err}
 | 
			
		||||
		}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, controller.ResourceVersion, err}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, scale.ResourceVersion, err}
 | 
			
		||||
	}
 | 
			
		||||
	return updatedRC.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
	return scale.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scale updates a ReplicationController to a new size, with optional precondition check (if preconditions is not nil),
 | 
			
		||||
@@ -241,17 +241,6 @@ func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateReplicaSet ensures that the preconditions match.  Returns nil if they are valid, an error otherwise
 | 
			
		||||
func (precondition *ScalePrecondition) ValidateReplicaSet(replicaSet *extensions.ReplicaSet) error {
 | 
			
		||||
	if precondition.Size != -1 && int(replicaSet.Spec.Replicas) != precondition.Size {
 | 
			
		||||
		return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(replicaSet.Spec.Replicas))}
 | 
			
		||||
	}
 | 
			
		||||
	if len(precondition.ResourceVersion) != 0 && replicaSet.ResourceVersion != precondition.ResourceVersion {
 | 
			
		||||
		return PreconditionError{"resource version", precondition.ResourceVersion, replicaSet.ResourceVersion}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ReplicaSetScaler struct {
 | 
			
		||||
	c client.ExtensionsInterface
 | 
			
		||||
}
 | 
			
		||||
@@ -259,24 +248,24 @@ type ReplicaSetScaler struct {
 | 
			
		||||
// ScaleSimple does a simple one-shot attempt at scaling. It returns the
 | 
			
		||||
// resourceVersion of the replicaset if the update is successful.
 | 
			
		||||
func (scaler *ReplicaSetScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) {
 | 
			
		||||
	rs, err := scaler.c.ReplicaSets(namespace).Get(name)
 | 
			
		||||
	sc := scaler.c.Scales(namespace)
 | 
			
		||||
	scale, err := sc.Get("ReplicaSet", name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", ScaleError{ScaleGetFailure, "Unknown", err}
 | 
			
		||||
	}
 | 
			
		||||
	if preconditions != nil {
 | 
			
		||||
		if err := preconditions.ValidateReplicaSet(rs); err != nil {
 | 
			
		||||
		if err := preconditions.ValidateScale(scale); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	rs.Spec.Replicas = int32(newSize)
 | 
			
		||||
	updatedRS, err := scaler.c.ReplicaSets(namespace).Update(rs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	scale.Spec.Replicas = int32(newSize)
 | 
			
		||||
	if _, err := sc.Update("ReplicaSet", scale); err != nil {
 | 
			
		||||
		if errors.IsConflict(err) {
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, rs.ResourceVersion, err}
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, scale.ResourceVersion, err}
 | 
			
		||||
		}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, rs.ResourceVersion, err}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, scale.ResourceVersion, err}
 | 
			
		||||
	}
 | 
			
		||||
	return updatedRS.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
	return scale.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scale updates a ReplicaSet to a new size, with optional precondition check (if preconditions is
 | 
			
		||||
@@ -433,17 +422,6 @@ func (scaler *JobScaler) Scale(namespace, name string, newSize uint, preconditio
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateDeployment ensures that the preconditions match.  Returns nil if they are valid, an error otherwise.
 | 
			
		||||
func (precondition *ScalePrecondition) ValidateDeployment(deployment *extensions.Deployment) error {
 | 
			
		||||
	if precondition.Size != -1 && int(deployment.Spec.Replicas) != precondition.Size {
 | 
			
		||||
		return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(int(deployment.Spec.Replicas))}
 | 
			
		||||
	}
 | 
			
		||||
	if len(precondition.ResourceVersion) != 0 && deployment.ResourceVersion != precondition.ResourceVersion {
 | 
			
		||||
		return PreconditionError{"resource version", precondition.ResourceVersion, deployment.ResourceVersion}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DeploymentScaler struct {
 | 
			
		||||
	c client.ExtensionsInterface
 | 
			
		||||
}
 | 
			
		||||
@@ -452,27 +430,25 @@ type DeploymentScaler struct {
 | 
			
		||||
// count. It returns the resourceVersion of the deployment if the update is
 | 
			
		||||
// successful.
 | 
			
		||||
func (scaler *DeploymentScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) (string, error) {
 | 
			
		||||
	deployment, err := scaler.c.Deployments(namespace).Get(name)
 | 
			
		||||
	sc := scaler.c.Scales(namespace)
 | 
			
		||||
	scale, err := sc.Get("Deployment", name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", ScaleError{ScaleGetFailure, "Unknown", err}
 | 
			
		||||
	}
 | 
			
		||||
	if preconditions != nil {
 | 
			
		||||
		if err := preconditions.ValidateDeployment(deployment); err != nil {
 | 
			
		||||
		if err := preconditions.ValidateScale(scale); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO(madhusudancs): Fix this when Scale group issues are resolved (see issue #18528).
 | 
			
		||||
	// For now I'm falling back to regular Deployment update operation.
 | 
			
		||||
	deployment.Spec.Replicas = int32(newSize)
 | 
			
		||||
	updatedDeployment, err := scaler.c.Deployments(namespace).Update(deployment)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	scale.Spec.Replicas = int32(newSize)
 | 
			
		||||
	if _, err := sc.Update("Deployment", scale); err != nil {
 | 
			
		||||
		if errors.IsConflict(err) {
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, deployment.ResourceVersion, err}
 | 
			
		||||
			return "", ScaleError{ScaleUpdateConflictFailure, scale.ResourceVersion, err}
 | 
			
		||||
		}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
 | 
			
		||||
		return "", ScaleError{ScaleUpdateFailure, scale.ResourceVersion, err}
 | 
			
		||||
	}
 | 
			
		||||
	return updatedDeployment.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
	return scale.ObjectMeta.ResourceVersion, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scale updates a deployment to a new size, with optional precondition check (if preconditions is not nil),
 | 
			
		||||
 
 | 
			
		||||
@@ -28,38 +28,52 @@ import (
 | 
			
		||||
	"k8s.io/kubernetes/pkg/client/unversioned/testclient"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ErrorReplicationControllers struct {
 | 
			
		||||
	testclient.FakeReplicationControllers
 | 
			
		||||
type ErrorScales struct {
 | 
			
		||||
	testclient.FakeScales
 | 
			
		||||
	conflict bool
 | 
			
		||||
	invalid  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) {
 | 
			
		||||
func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
 | 
			
		||||
	switch {
 | 
			
		||||
	case c.invalid:
 | 
			
		||||
		return nil, kerrors.NewInvalid(api.Kind(controller.Kind), controller.Name, nil)
 | 
			
		||||
		return nil, kerrors.NewInvalid(api.Kind(kind), scale.Name, nil)
 | 
			
		||||
	case c.conflict:
 | 
			
		||||
		return nil, kerrors.NewConflict(api.Resource(controller.Kind), controller.Name, nil)
 | 
			
		||||
		return nil, kerrors.NewConflict(api.Resource(kind), scale.Name, nil)
 | 
			
		||||
	}
 | 
			
		||||
	return nil, errors.New("Replication controller update failure")
 | 
			
		||||
	return nil, errors.New("Scale update failure")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorReplicationControllerClient struct {
 | 
			
		||||
type ErrorExtensions struct {
 | 
			
		||||
	testclient.FakeExperimental
 | 
			
		||||
	conflict bool
 | 
			
		||||
	invalid  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorExtensions) Scales(namespace string) client.ScaleInterface {
 | 
			
		||||
	return &ErrorScales{
 | 
			
		||||
		FakeScales: testclient.FakeScales{Fake: &c.FakeExperimental, Namespace: namespace},
 | 
			
		||||
		conflict:   c.conflict,
 | 
			
		||||
		invalid:    c.invalid,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorExtensionsClient struct {
 | 
			
		||||
	testclient.Fake
 | 
			
		||||
	conflict bool
 | 
			
		||||
	invalid  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorReplicationControllerClient) ReplicationControllers(namespace string) client.ReplicationControllerInterface {
 | 
			
		||||
	return &ErrorReplicationControllers{
 | 
			
		||||
		FakeReplicationControllers: testclient.FakeReplicationControllers{Fake: &c.Fake, Namespace: namespace},
 | 
			
		||||
func (c *ErrorExtensionsClient) Extensions() client.ExtensionsInterface {
 | 
			
		||||
	return &ErrorExtensions{
 | 
			
		||||
		FakeExperimental: testclient.FakeExperimental{Fake: &c.Fake},
 | 
			
		||||
		conflict:         c.conflict,
 | 
			
		||||
		invalid:          c.invalid,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReplicationControllerScaleRetry(t *testing.T) {
 | 
			
		||||
	fake := &ErrorReplicationControllerClient{Fake: testclient.Fake{}, conflict: true}
 | 
			
		||||
	fake := &ErrorExtensionsClient{Fake: testclient.Fake{}, conflict: true}
 | 
			
		||||
	scaler := ReplicationControllerScaler{fake}
 | 
			
		||||
	preconditions := ScalePrecondition{-1, ""}
 | 
			
		||||
	count := uint(3)
 | 
			
		||||
@@ -83,7 +97,7 @@ func TestReplicationControllerScaleRetry(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReplicationControllerScaleInvalid(t *testing.T) {
 | 
			
		||||
	fake := &ErrorReplicationControllerClient{Fake: testclient.Fake{}, invalid: true}
 | 
			
		||||
	fake := &ErrorExtensionsClient{Fake: testclient.Fake{}, invalid: true}
 | 
			
		||||
	scaler := ReplicationControllerScaler{fake}
 | 
			
		||||
	preconditions := ScalePrecondition{-1, ""}
 | 
			
		||||
	count := uint(3)
 | 
			
		||||
@@ -103,7 +117,7 @@ func TestReplicationControllerScaleInvalid(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestReplicationControllerScale(t *testing.T) {
 | 
			
		||||
	fake := &testclient.Fake{}
 | 
			
		||||
	scaler := ReplicationControllerScaler{fake}
 | 
			
		||||
	scaler := ReplicationControllerScaler{&testclient.FakeExperimental{fake}}
 | 
			
		||||
	preconditions := ScalePrecondition{-1, ""}
 | 
			
		||||
	count := uint(3)
 | 
			
		||||
	name := "foo"
 | 
			
		||||
@@ -113,17 +127,17 @@ func TestReplicationControllerScale(t *testing.T) {
 | 
			
		||||
	if len(actions) != 2 {
 | 
			
		||||
		t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetName() != name {
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "ReplicationController" || action.GetName() != name || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetObject().(*api.ReplicationController).Spec.Replicas != int32(count) {
 | 
			
		||||
	if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "ReplicationController" || action.GetObject().(*extensions.Scale).Spec.Replicas != int32(count) || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action %v, expected update-replicationController with replicas = %d", actions[1], count)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReplicationControllerScaleFailsPreconditions(t *testing.T) {
 | 
			
		||||
	fake := testclient.NewSimpleFake(&api.ReplicationController{
 | 
			
		||||
		Spec: api.ReplicationControllerSpec{
 | 
			
		||||
	fake := testclient.NewSimpleFake(&extensions.Scale{
 | 
			
		||||
		Spec: extensions.ScaleSpec{
 | 
			
		||||
			Replicas: 10,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
@@ -137,15 +151,15 @@ func TestReplicationControllerScaleFailsPreconditions(t *testing.T) {
 | 
			
		||||
	if len(actions) != 1 {
 | 
			
		||||
		t.Errorf("unexpected actions: %v, expected 1 action (get)", actions)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetName() != name {
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "ReplicationController" || action.GetName() != name || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
func TestValidateScale(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		preconditions ScalePrecondition
 | 
			
		||||
		controller    api.ReplicationController
 | 
			
		||||
		scale         extensions.Scale
 | 
			
		||||
		expectError   bool
 | 
			
		||||
		test          string
 | 
			
		||||
	}{
 | 
			
		||||
@@ -156,11 +170,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{-1, ""},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 10,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -169,11 +183,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{0, ""},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 0,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -182,11 +196,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{-1, "foo"},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 10,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -195,11 +209,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 10,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -208,11 +222,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 20,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -221,11 +235,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "bar",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 10,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -234,11 +248,11 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			controller: api.ReplicationController{
 | 
			
		||||
			scale: extensions.Scale{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "bar",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: api.ReplicationControllerSpec{
 | 
			
		||||
				Spec: extensions.ScaleSpec{
 | 
			
		||||
					Replicas: 20,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
@@ -247,7 +261,7 @@ func TestValidateReplicationController(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		err := test.preconditions.ValidateReplicationController(&test.controller)
 | 
			
		||||
		err := test.preconditions.ValidateScale(&test.scale)
 | 
			
		||||
		if err != nil && !test.expectError {
 | 
			
		||||
			t.Errorf("unexpected error: %v (%s)", err, test.test)
 | 
			
		||||
		}
 | 
			
		||||
@@ -507,46 +521,8 @@ func TestValidateJob(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorDeployments struct {
 | 
			
		||||
	testclient.FakeDeployments
 | 
			
		||||
	conflict bool
 | 
			
		||||
	invalid  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
 | 
			
		||||
	switch {
 | 
			
		||||
	case c.invalid:
 | 
			
		||||
		return nil, kerrors.NewInvalid(api.Kind(deployment.Kind), deployment.Name, nil)
 | 
			
		||||
	case c.conflict:
 | 
			
		||||
		return nil, kerrors.NewConflict(api.Resource(deployment.Kind), deployment.Name, nil)
 | 
			
		||||
	}
 | 
			
		||||
	return nil, errors.New("deployment update failure")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorDeployments) Get(name string) (*extensions.Deployment, error) {
 | 
			
		||||
	return &extensions.Deployment{
 | 
			
		||||
		Spec: extensions.DeploymentSpec{
 | 
			
		||||
			Replicas: 0,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ErrorDeploymentClient struct {
 | 
			
		||||
	testclient.FakeExperimental
 | 
			
		||||
	conflict bool
 | 
			
		||||
	invalid  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ErrorDeploymentClient) Deployments(namespace string) client.DeploymentInterface {
 | 
			
		||||
	return &ErrorDeployments{
 | 
			
		||||
		FakeDeployments: testclient.FakeDeployments{Fake: &c.FakeExperimental, Namespace: namespace},
 | 
			
		||||
		invalid:         c.invalid,
 | 
			
		||||
		conflict:        c.conflict,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeploymentScaleRetry(t *testing.T) {
 | 
			
		||||
	fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{}, conflict: true}
 | 
			
		||||
	fake := &ErrorExtensions{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, conflict: true}
 | 
			
		||||
	scaler := &DeploymentScaler{fake}
 | 
			
		||||
	preconditions := &ScalePrecondition{-1, ""}
 | 
			
		||||
	count := uint(3)
 | 
			
		||||
@@ -581,16 +557,16 @@ func TestDeploymentScale(t *testing.T) {
 | 
			
		||||
	if len(actions) != 2 {
 | 
			
		||||
		t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
 | 
			
		||||
		t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "Deployment" || action.GetName() != name || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "deployments" || action.GetObject().(*extensions.Deployment).Spec.Replicas != int32(count) {
 | 
			
		||||
	if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "Deployment" || action.GetObject().(*extensions.Scale).Spec.Replicas != int32(count) || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action %v, expected update-deployment with replicas = %d", actions[1], count)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeploymentScaleInvalid(t *testing.T) {
 | 
			
		||||
	fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{}, invalid: true}
 | 
			
		||||
	fake := &ErrorExtensions{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: true}
 | 
			
		||||
	scaler := DeploymentScaler{fake}
 | 
			
		||||
	preconditions := ScalePrecondition{-1, ""}
 | 
			
		||||
	count := uint(3)
 | 
			
		||||
@@ -609,8 +585,8 @@ func TestDeploymentScaleInvalid(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeploymentScaleFailsPreconditions(t *testing.T) {
 | 
			
		||||
	fake := testclient.NewSimpleFake(&extensions.Deployment{
 | 
			
		||||
		Spec: extensions.DeploymentSpec{
 | 
			
		||||
	fake := testclient.NewSimpleFake(&extensions.Scale{
 | 
			
		||||
		Spec: extensions.ScaleSpec{
 | 
			
		||||
			Replicas: 10,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
@@ -624,133 +600,7 @@ func TestDeploymentScaleFailsPreconditions(t *testing.T) {
 | 
			
		||||
	if len(actions) != 1 {
 | 
			
		||||
		t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions)
 | 
			
		||||
	}
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
 | 
			
		||||
	if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "Deployment" || action.GetName() != name || action.GetSubresource() != "scale" {
 | 
			
		||||
		t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestValidateDeployment(t *testing.T) {
 | 
			
		||||
	zero, ten, twenty := int32(0), int32(10), int32(20)
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		preconditions ScalePrecondition
 | 
			
		||||
		deployment    extensions.Deployment
 | 
			
		||||
		expectError   bool
 | 
			
		||||
		test          string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{-1, ""},
 | 
			
		||||
			expectError:   false,
 | 
			
		||||
			test:          "defaults",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{-1, ""},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: ten,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: false,
 | 
			
		||||
			test:        "defaults 2",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{0, ""},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: zero,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: false,
 | 
			
		||||
			test:        "size matches",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{-1, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: ten,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: false,
 | 
			
		||||
			test:        "resource version matches",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: ten,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: false,
 | 
			
		||||
			test:        "both match",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: twenty,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: true,
 | 
			
		||||
			test:        "size different",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: true,
 | 
			
		||||
			test:        "no replicas",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "bar",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: ten,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: true,
 | 
			
		||||
			test:        "version different",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			preconditions: ScalePrecondition{10, "foo"},
 | 
			
		||||
			deployment: extensions.Deployment{
 | 
			
		||||
				ObjectMeta: api.ObjectMeta{
 | 
			
		||||
					ResourceVersion: "bar",
 | 
			
		||||
				},
 | 
			
		||||
				Spec: extensions.DeploymentSpec{
 | 
			
		||||
					Replicas: twenty,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectError: true,
 | 
			
		||||
			test:        "both different",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		err := test.preconditions.ValidateDeployment(&test.deployment)
 | 
			
		||||
		if err != nil && !test.expectError {
 | 
			
		||||
			t.Errorf("unexpected error: %v (%s)", err, test.test)
 | 
			
		||||
		}
 | 
			
		||||
		if err == nil && test.expectError {
 | 
			
		||||
			t.Errorf("unexpected non-error: %v (%s)", err, test.test)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,11 @@ func TestReplicationControllerStop(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&extensions.Scale{
 | 
			
		||||
					Spec: extensions.ScaleSpec{
 | 
			
		||||
						Replicas: 0,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			StopError:       nil,
 | 
			
		||||
			ExpectedActions: []string{"get", "list", "get", "update", "get", "delete"},
 | 
			
		||||
@@ -107,6 +112,11 @@ func TestReplicationControllerStop(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&extensions.Scale{
 | 
			
		||||
					Spec: extensions.ScaleSpec{
 | 
			
		||||
						Replicas: 0,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			StopError:       nil,
 | 
			
		||||
			ExpectedActions: []string{"get", "list", "get", "update", "get", "delete"},
 | 
			
		||||
@@ -269,7 +279,7 @@ func TestReplicationControllerStop(t *testing.T) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		for i, verb := range test.ExpectedActions {
 | 
			
		||||
			if actions[i].GetResource() != "replicationcontrollers" {
 | 
			
		||||
			if actions[i].GetResource() != "replicationcontrollers" && actions[i].GetSubresource() != "scale" {
 | 
			
		||||
				t.Errorf("%s unexpected action: %+v, expected %s-replicationController", test.Name, actions[i], verb)
 | 
			
		||||
			}
 | 
			
		||||
			if actions[i].GetVerb() != verb {
 | 
			
		||||
@@ -315,6 +325,11 @@ func TestReplicaSetStop(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&extensions.Scale{
 | 
			
		||||
					Spec: extensions.ScaleSpec{
 | 
			
		||||
						Replicas: 0,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			StopError:       nil,
 | 
			
		||||
			ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"},
 | 
			
		||||
@@ -356,6 +371,11 @@ func TestReplicaSetStop(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&extensions.Scale{
 | 
			
		||||
					Spec: extensions.ScaleSpec{
 | 
			
		||||
						Replicas: 0,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			StopError:       nil,
 | 
			
		||||
			ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"},
 | 
			
		||||
@@ -379,7 +399,7 @@ func TestReplicaSetStop(t *testing.T) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		for i, verb := range test.ExpectedActions {
 | 
			
		||||
			if actions[i].GetResource() != "replicasets" {
 | 
			
		||||
			if actions[i].GetResource() != "replicasets" && actions[i].GetSubresource() != "scale" {
 | 
			
		||||
				t.Errorf("%s unexpected action: %+v, expected %s-replicaSet", test.Name, actions[i], verb)
 | 
			
		||||
			}
 | 
			
		||||
			if actions[i].GetVerb() != verb {
 | 
			
		||||
@@ -571,6 +591,11 @@ func TestDeploymentStop(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&extensions.Scale{
 | 
			
		||||
					Spec: extensions.ScaleSpec{
 | 
			
		||||
						Replicas: 0,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			StopError: nil,
 | 
			
		||||
			ExpectedActions: []string{"get:deployments", "update:deployments",
 | 
			
		||||
@@ -599,7 +624,7 @@ func TestDeploymentStop(t *testing.T) {
 | 
			
		||||
			if actions[i].GetVerb() != action[0] {
 | 
			
		||||
				t.Errorf("%s unexpected verb: %+v, expected %s", test.Name, actions[i], expAction)
 | 
			
		||||
			}
 | 
			
		||||
			if actions[i].GetResource() != action[1] {
 | 
			
		||||
			if actions[i].GetResource() != action[1] && actions[i].GetSubresource() != "scale" {
 | 
			
		||||
				t.Errorf("%s unexpected resource: %+v, expected %s", test.Name, actions[i], expAction)
 | 
			
		||||
			}
 | 
			
		||||
			if len(action) == 3 && actions[i].GetSubresource() != action[2] {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user