kubectl: Support scaling deployments
This commit adds support for using kubectl scale to scale deployments. Makes use of the deployments/scale endpoint instead of updating deployment.spec.replicas directly.
This commit is contained in:
parent
a7425bf070
commit
99fc35880b
@ -3,7 +3,7 @@
|
||||
|
||||
.SH NAME
|
||||
.PP
|
||||
kubectl scale \- Set a new size for a Replication Controller.
|
||||
kubectl scale \- Set a new size for a Replication Controller, Job, or Deployment.
|
||||
|
||||
|
||||
.SH SYNOPSIS
|
||||
@ -13,7 +13,7 @@ kubectl scale \- Set a new size for a Replication Controller.
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Set a new size for a Replication Controller.
|
||||
Set a new size for a Replication Controller, Job, or Deployment.
|
||||
|
||||
.PP
|
||||
Scale also allows users to specify one or more preconditions for the scale action.
|
||||
@ -25,11 +25,11 @@ scale is sent to the server.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\fB\-\-current\-replicas\fP=\-1
|
||||
Precondition for current size. Requires that the current size of the replication controller match this value in order to scale.
|
||||
Precondition for current size. Requires that the current size of the resource match this value in order to scale.
|
||||
|
||||
.PP
|
||||
\fB\-f\fP, \fB\-\-filename\fP=[]
|
||||
Filename, directory, or URL to a file identifying the replication controller to set a new size
|
||||
Filename, directory, or URL to a file identifying the resource to set a new size
|
||||
|
||||
.PP
|
||||
\fB\-o\fP, \fB\-\-output\fP=""
|
||||
@ -148,16 +148,19 @@ scale is sent to the server.
|
||||
|
||||
.nf
|
||||
# Scale replication controller named 'foo' to 3.
|
||||
$ kubectl scale \-\-replicas=3 replicationcontrollers foo
|
||||
$ kubectl scale \-\-replicas=3 rc/foo
|
||||
|
||||
# Scale a replication controller identified by type and name specified in "foo\-controller.yaml" to 3.
|
||||
$ kubectl scale \-\-replicas=3 \-f foo\-controller.yaml
|
||||
# Scale a resource identified by type and name specified in "foo.yaml" to 3.
|
||||
$ kubectl scale \-\-replicas=3 \-f foo.yaml
|
||||
|
||||
# If the replication controller named foo's current size is 2, scale foo to 3.
|
||||
$ kubectl scale \-\-current\-replicas=2 \-\-replicas=3 replicationcontrollers foo
|
||||
# If the deployment named mysql's current size is 2, scale mysql to 3.
|
||||
$ kubectl scale \-\-current\-replicas=2 \-\-replicas=3 deployment/mysql
|
||||
|
||||
# Scale multiple replication controllers.
|
||||
$ kubectl scale \-\-replicas=5 rc/foo rc/bar
|
||||
$ kubectl scale \-\-replicas=5 rc/foo rc/bar rc/baz
|
||||
|
||||
# Scale job named 'cron' to 3.
|
||||
$ kubectl scale \-\-replicas=3 job/cron
|
||||
|
||||
.fi
|
||||
.RE
|
||||
|
@ -101,10 +101,10 @@ kubectl
|
||||
* [kubectl replace](kubectl_replace.md) - Replace a resource by filename or stdin.
|
||||
* [kubectl rolling-update](kubectl_rolling-update.md) - Perform a rolling update of the given ReplicationController.
|
||||
* [kubectl run](kubectl_run.md) - Run a particular image on the cluster.
|
||||
* [kubectl scale](kubectl_scale.md) - Set a new size for a Replication Controller.
|
||||
* [kubectl scale](kubectl_scale.md) - Set a new size for a Replication Controller, Job, or Deployment.
|
||||
* [kubectl version](kubectl_version.md) - Print the client and server version information.
|
||||
|
||||
###### Auto generated by spf13/cobra on 24-Nov-2015
|
||||
###### Auto generated by spf13/cobra on 25-Nov-2015
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[]()
|
||||
|
@ -33,12 +33,12 @@ Documentation for other releases can be found at
|
||||
|
||||
## kubectl scale
|
||||
|
||||
Set a new size for a Replication Controller.
|
||||
Set a new size for a Replication Controller, Job, or Deployment.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Set a new size for a Replication Controller.
|
||||
Set a new size for a Replication Controller, Job, or Deployment.
|
||||
|
||||
Scale also allows users to specify one or more preconditions for the scale action.
|
||||
If --current-replicas or --resource-version is specified, it is validated before the
|
||||
@ -53,23 +53,26 @@ kubectl scale [--resource-version=version] [--current-replicas=count] --replicas
|
||||
|
||||
```
|
||||
# Scale replication controller named 'foo' to 3.
|
||||
$ kubectl scale --replicas=3 replicationcontrollers foo
|
||||
$ kubectl scale --replicas=3 rc/foo
|
||||
|
||||
# Scale a replication controller identified by type and name specified in "foo-controller.yaml" to 3.
|
||||
$ kubectl scale --replicas=3 -f foo-controller.yaml
|
||||
# Scale a resource identified by type and name specified in "foo.yaml" to 3.
|
||||
$ kubectl scale --replicas=3 -f foo.yaml
|
||||
|
||||
# If the replication controller named foo's current size is 2, scale foo to 3.
|
||||
$ kubectl scale --current-replicas=2 --replicas=3 replicationcontrollers foo
|
||||
# If the deployment named mysql's current size is 2, scale mysql to 3.
|
||||
$ kubectl scale --current-replicas=2 --replicas=3 deployment/mysql
|
||||
|
||||
# Scale multiple replication controllers.
|
||||
$ kubectl scale --replicas=5 rc/foo rc/bar
|
||||
$ kubectl scale --replicas=5 rc/foo rc/bar rc/baz
|
||||
|
||||
# Scale job named 'cron' to 3.
|
||||
$ kubectl scale --replicas=3 job/cron
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--current-replicas=-1: Precondition for current size. Requires that the current size of the replication controller match this value in order to scale.
|
||||
-f, --filename=[]: Filename, directory, or URL to a file identifying the replication controller to set a new size
|
||||
--current-replicas=-1: Precondition for current size. Requires that the current size of the resource match this value in order to scale.
|
||||
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to set a new size
|
||||
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
||||
--replicas=-1: The new desired number of replicas. Required.
|
||||
--resource-version="": Precondition for resource version. Requires that the current resource version match this value in order to scale.
|
||||
|
@ -219,6 +219,8 @@ runTests() {
|
||||
hpa_min_field=".spec.minReplicas"
|
||||
hpa_max_field=".spec.maxReplicas"
|
||||
hpa_cpu_field=".spec.cpuUtilization.targetPercentage"
|
||||
job_parallelism_field=".spec.parallelism"
|
||||
deployment_replicas=".spec.replicas"
|
||||
|
||||
# Passing no arguments to create is an error
|
||||
! kubectl create
|
||||
@ -873,6 +875,23 @@ __EOF__
|
||||
# Clean-up
|
||||
kubectl delete rc redis-{master,slave} "${kube_flags[@]}"
|
||||
|
||||
### Scale a job
|
||||
kubectl create -f docs/user-guide/job.yaml "${kube_flags[@]}"
|
||||
# Command
|
||||
kubectl scale --replicas=2 job/pi
|
||||
# Post-condition: 2 replicas for pi
|
||||
kube::test::get_object_assert 'job pi' "{{$job_parallelism_field}}" '2'
|
||||
# Clean-up
|
||||
kubectl delete job/pi "${kube_flags[@]}"
|
||||
### Scale a deployment
|
||||
kubectl create -f examples/extensions/deployment.yaml "${kube_flags[@]}"
|
||||
# Command
|
||||
kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment
|
||||
# Post-condition: 1 replica for nginx-deployment
|
||||
kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '1'
|
||||
# Clean-up
|
||||
kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
|
||||
|
||||
### Expose replication controller as service
|
||||
# Pre-condition: 2 replicas
|
||||
kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
|
||||
|
@ -18,9 +18,9 @@ package extensions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sort"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
@ -65,3 +65,21 @@ func PodSelectorAsSelector(ps *PodSelector) (labels.Selector, error) {
|
||||
sort.Sort(labels.ByKey(selector))
|
||||
return selector, nil
|
||||
}
|
||||
|
||||
// ScaleFromDeployment returns a scale subresource for a deployment.
|
||||
func ScaleFromDeployment(deployment *Deployment) *Scale {
|
||||
return &Scale{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: deployment.Name,
|
||||
Namespace: deployment.Namespace,
|
||||
CreationTimestamp: deployment.CreationTimestamp,
|
||||
},
|
||||
Spec: ScaleSpec{
|
||||
Replicas: deployment.Spec.Replicas,
|
||||
},
|
||||
Status: ScaleStatus{
|
||||
Replicas: deployment.Status.Replicas,
|
||||
Selector: deployment.Spec.Selector,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ func ControllerHasDesiredReplicas(c Interface, controller *api.ReplicationContro
|
||||
|
||||
// JobHasDesiredParallelism returns a condition that will be true if the desired parallelism count
|
||||
// for a job equals the current active counts or is less by an appropriate successful/unsuccessful count.
|
||||
func JobHasDesiredParallelism(c Interface, job *extensions.Job) wait.ConditionFunc {
|
||||
func JobHasDesiredParallelism(c ExtensionsInterface, job *extensions.Job) wait.ConditionFunc {
|
||||
|
||||
return func() (bool, error) {
|
||||
job, err := c.Extensions().Jobs(job.Namespace).Get(job.Name)
|
||||
job, err := c.Jobs(job.Namespace).Get(job.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -62,3 +62,17 @@ func JobHasDesiredParallelism(c Interface, job *extensions.Job) wait.ConditionFu
|
||||
return progress == 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
// DeploymentHasDesiredReplicas returns a condition that will be true if and only if
|
||||
// the desired replica count for a deployment equals its updated replicas count.
|
||||
// (non-terminated pods that have the desired template spec).
|
||||
func DeploymentHasDesiredReplicas(c ExtensionsInterface, deployment *extensions.Deployment) wait.ConditionFunc {
|
||||
|
||||
return func() (bool, error) {
|
||||
deployment, err := c.Deployments(deployment.Namespace).Get(deployment.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return deployment.Status.UpdatedReplicas == deployment.Spec.Replicas, nil
|
||||
}
|
||||
}
|
||||
|
@ -315,6 +315,11 @@ func (c *Fake) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) {
|
||||
return &swagger.ApiDeclaration{}, nil
|
||||
}
|
||||
|
||||
// NewSimpleFakeExp returns a client that will respond with the provided objects
|
||||
func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental {
|
||||
return &FakeExperimental{Fake: NewSimpleFake(objects...)}
|
||||
}
|
||||
|
||||
type FakeExperimental struct {
|
||||
*Fake
|
||||
}
|
||||
|
@ -36,23 +36,26 @@ type ScaleOptions struct {
|
||||
}
|
||||
|
||||
const (
|
||||
scale_long = `Set a new size for a Replication Controller.
|
||||
scale_long = `Set a new size for a Replication Controller, Job, or Deployment.
|
||||
|
||||
Scale also allows users to specify one or more preconditions for the scale action.
|
||||
If --current-replicas or --resource-version is specified, it is validated before the
|
||||
scale is attempted, and it is guaranteed that the precondition holds true when the
|
||||
scale is sent to the server.`
|
||||
scale_example = `# Scale replication controller named 'foo' to 3.
|
||||
$ kubectl scale --replicas=3 replicationcontrollers foo
|
||||
$ kubectl scale --replicas=3 rc/foo
|
||||
|
||||
# Scale a replication controller identified by type and name specified in "foo-controller.yaml" to 3.
|
||||
$ kubectl scale --replicas=3 -f foo-controller.yaml
|
||||
# Scale a resource identified by type and name specified in "foo.yaml" to 3.
|
||||
$ kubectl scale --replicas=3 -f foo.yaml
|
||||
|
||||
# If the replication controller named foo's current size is 2, scale foo to 3.
|
||||
$ kubectl scale --current-replicas=2 --replicas=3 replicationcontrollers foo
|
||||
# If the deployment named mysql's current size is 2, scale mysql to 3.
|
||||
$ kubectl scale --current-replicas=2 --replicas=3 deployment/mysql
|
||||
|
||||
# Scale multiple replication controllers.
|
||||
$ kubectl scale --replicas=5 rc/foo rc/bar`
|
||||
$ kubectl scale --replicas=5 rc/foo rc/bar rc/baz
|
||||
|
||||
# Scale job named 'cron' to 3.
|
||||
$ kubectl scale --replicas=3 job/cron`
|
||||
)
|
||||
|
||||
// NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale
|
||||
@ -63,7 +66,7 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
Use: "scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)",
|
||||
// resize is deprecated
|
||||
Aliases: []string{"resize"},
|
||||
Short: "Set a new size for a Replication Controller.",
|
||||
Short: "Set a new size for a Replication Controller, Job, or Deployment.",
|
||||
Long: scale_long,
|
||||
Example: scale_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -74,13 +77,13 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
},
|
||||
}
|
||||
cmd.Flags().String("resource-version", "", "Precondition for resource version. Requires that the current resource version match this value in order to scale.")
|
||||
cmd.Flags().Int("current-replicas", -1, "Precondition for current size. Requires that the current size of the replication controller match this value in order to scale.")
|
||||
cmd.Flags().Int("current-replicas", -1, "Precondition for current size. Requires that the current size of the resource match this value in order to scale.")
|
||||
cmd.Flags().Int("replicas", -1, "The new desired number of replicas. Required.")
|
||||
cmd.MarkFlagRequired("replicas")
|
||||
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait.")
|
||||
cmdutil.AddOutputFlagsForMutation(cmd)
|
||||
|
||||
usage := "Filename, directory, or URL to a file identifying the replication controller to set a new size"
|
||||
usage := "Filename, directory, or URL to a file identifying the resource to set a new size"
|
||||
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||
return cmd
|
||||
}
|
||||
@ -127,11 +130,11 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
||||
|
||||
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
|
||||
if len(resourceVersion) != 0 && len(infos) > 1 {
|
||||
return fmt.Errorf("cannot use --resource-version with multiple controllers")
|
||||
return fmt.Errorf("cannot use --resource-version with multiple resources")
|
||||
}
|
||||
currentSize := cmdutil.GetFlagInt(cmd, "current-replicas")
|
||||
if currentSize != -1 && len(infos) > 1 {
|
||||
return fmt.Errorf("cannot use --current-replicas with multiple controllers")
|
||||
return fmt.Errorf("cannot use --current-replicas with multiple resources")
|
||||
}
|
||||
precondition := &kubectl.ScalePrecondition{Size: currentSize, ResourceVersion: resourceVersion}
|
||||
retry := kubectl.NewRetryParams(kubectl.Interval, kubectl.Timeout)
|
||||
|
@ -28,74 +28,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
// ScalePrecondition describes a condition that must be true for the scale to take place
|
||||
// If CurrentSize == -1, it is ignored.
|
||||
// If CurrentResourceVersion is the empty string, it is ignored.
|
||||
// Otherwise they must equal the values in the replication controller for it to be valid.
|
||||
type ScalePrecondition struct {
|
||||
Size int
|
||||
ResourceVersion string
|
||||
}
|
||||
|
||||
// A PreconditionError is returned when a replication controller fails to match
|
||||
// the scale preconditions passed to kubectl.
|
||||
type PreconditionError struct {
|
||||
Precondition string
|
||||
ExpectedValue string
|
||||
ActualValue string
|
||||
}
|
||||
|
||||
func (pe PreconditionError) Error() string {
|
||||
return fmt.Sprintf("Expected %s to be %s, was %s", pe.Precondition, pe.ExpectedValue, pe.ActualValue)
|
||||
}
|
||||
|
||||
type ControllerScaleErrorType int
|
||||
|
||||
const (
|
||||
ControllerScaleGetFailure ControllerScaleErrorType = iota
|
||||
ControllerScaleUpdateFailure
|
||||
ControllerScaleUpdateInvalidFailure
|
||||
)
|
||||
|
||||
// A ControllerScaleError is returned when a scale request passes
|
||||
// preconditions but fails to actually scale the controller.
|
||||
type ControllerScaleError struct {
|
||||
FailureType ControllerScaleErrorType
|
||||
ResourceVersion string
|
||||
ActualError error
|
||||
}
|
||||
|
||||
func (c ControllerScaleError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"Scaling the controller failed with: %s; Current resource version %s",
|
||||
c.ActualError, c.ResourceVersion)
|
||||
}
|
||||
|
||||
// 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 && controller.Spec.Replicas != precondition.Size {
|
||||
return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(controller.Spec.Replicas)}
|
||||
}
|
||||
if precondition.ResourceVersion != "" && controller.ResourceVersion != precondition.ResourceVersion {
|
||||
return PreconditionError{"resource version", precondition.ResourceVersion, controller.ResourceVersion}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise
|
||||
func (precondition *ScalePrecondition) ValidateJob(job *extensions.Job) error {
|
||||
if precondition.Size != -1 && job.Spec.Parallelism == nil {
|
||||
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"}
|
||||
}
|
||||
if precondition.Size != -1 && *job.Spec.Parallelism != precondition.Size {
|
||||
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), strconv.Itoa(*job.Spec.Parallelism)}
|
||||
}
|
||||
if precondition.ResourceVersion != "" && job.ResourceVersion != precondition.ResourceVersion {
|
||||
return PreconditionError{"resource version", precondition.ResourceVersion, job.ResourceVersion}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scaler provides an interface for resources that can be scaled.
|
||||
type Scaler interface {
|
||||
// Scale scales the named resource after checking preconditions. It optionally
|
||||
// retries in the event of resource version mismatch (if retry is not nil),
|
||||
@ -111,16 +44,54 @@ func ScalerFor(kind string, c client.Interface) (Scaler, error) {
|
||||
case "ReplicationController":
|
||||
return &ReplicationControllerScaler{c}, nil
|
||||
case "Job":
|
||||
return &JobScaler{c}, nil
|
||||
return &JobScaler{c.Extensions()}, nil
|
||||
case "Deployment":
|
||||
return &DeploymentScaler{c.Extensions()}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no scaler has been implemented for %q", kind)
|
||||
}
|
||||
|
||||
type ReplicationControllerScaler struct {
|
||||
c client.Interface
|
||||
// ScalePrecondition describes a condition that must be true for the scale to take place
|
||||
// If CurrentSize == -1, it is ignored.
|
||||
// If CurrentResourceVersion is the empty string, it is ignored.
|
||||
// Otherwise they must equal the values in the resource for it to be valid.
|
||||
type ScalePrecondition struct {
|
||||
Size int
|
||||
ResourceVersion string
|
||||
}
|
||||
type JobScaler struct {
|
||||
c client.Interface
|
||||
|
||||
// A PreconditionError is returned when a resource fails to match
|
||||
// the scale preconditions passed to kubectl.
|
||||
type PreconditionError struct {
|
||||
Precondition string
|
||||
ExpectedValue string
|
||||
ActualValue string
|
||||
}
|
||||
|
||||
func (pe PreconditionError) Error() string {
|
||||
return fmt.Sprintf("Expected %s to be %s, was %s", pe.Precondition, pe.ExpectedValue, pe.ActualValue)
|
||||
}
|
||||
|
||||
type ScaleErrorType int
|
||||
|
||||
const (
|
||||
ScaleGetFailure ScaleErrorType = iota
|
||||
ScaleUpdateFailure
|
||||
ScaleUpdateInvalidFailure
|
||||
)
|
||||
|
||||
// A ScaleError is returned when a scale request passes
|
||||
// preconditions but fails to actually scale the controller.
|
||||
type ScaleError struct {
|
||||
FailureType ScaleErrorType
|
||||
ResourceVersion string
|
||||
ActualError error
|
||||
}
|
||||
|
||||
func (c ScaleError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"Scaling the resource failed with: %v; Current resource version %s",
|
||||
c.ActualError, c.ResourceVersion)
|
||||
}
|
||||
|
||||
// RetryParams encapsulates the retry parameters used by kubectl's scaler.
|
||||
@ -136,15 +107,15 @@ func NewRetryParams(interval, timeout time.Duration) *RetryParams {
|
||||
func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name string, count uint) wait.ConditionFunc {
|
||||
return func() (bool, error) {
|
||||
err := r.ScaleSimple(namespace, name, precondition, count)
|
||||
switch e, _ := err.(ControllerScaleError); err.(type) {
|
||||
switch e, _ := err.(ScaleError); err.(type) {
|
||||
case nil:
|
||||
return true, nil
|
||||
case ControllerScaleError:
|
||||
case ScaleError:
|
||||
// if it's invalid we shouldn't keep waiting
|
||||
if e.FailureType == ControllerScaleUpdateInvalidFailure {
|
||||
if e.FailureType == ScaleUpdateInvalidFailure {
|
||||
return false, err
|
||||
}
|
||||
if e.FailureType == ControllerScaleUpdateFailure {
|
||||
if e.FailureType == ScaleUpdateFailure {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
@ -152,10 +123,25 @@ func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name s
|
||||
}
|
||||
}
|
||||
|
||||
// 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 && controller.Spec.Replicas != precondition.Size {
|
||||
return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(controller.Spec.Replicas)}
|
||||
}
|
||||
if len(precondition.ResourceVersion) != 0 && controller.ResourceVersion != precondition.ResourceVersion {
|
||||
return PreconditionError{"resource version", precondition.ResourceVersion, controller.ResourceVersion}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ReplicationControllerScaler struct {
|
||||
c client.Interface
|
||||
}
|
||||
|
||||
func (scaler *ReplicationControllerScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) error {
|
||||
controller, err := scaler.c.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return ControllerScaleError{ControllerScaleGetFailure, "Unknown", err}
|
||||
return ScaleError{ScaleGetFailure, "Unknown", err}
|
||||
}
|
||||
if preconditions != nil {
|
||||
if err := preconditions.ValidateReplicationController(controller); err != nil {
|
||||
@ -166,11 +152,10 @@ func (scaler *ReplicationControllerScaler) ScaleSimple(namespace, name string, p
|
||||
// TODO: do retry on 409 errors here?
|
||||
if _, err := scaler.c.ReplicationControllers(namespace).Update(controller); err != nil {
|
||||
if errors.IsInvalid(err) {
|
||||
return ControllerScaleError{ControllerScaleUpdateInvalidFailure, controller.ResourceVersion, err}
|
||||
return ScaleError{ScaleUpdateInvalidFailure, controller.ResourceVersion, err}
|
||||
}
|
||||
return ControllerScaleError{ControllerScaleUpdateFailure, controller.ResourceVersion, err}
|
||||
return ScaleError{ScaleUpdateFailure, controller.ResourceVersion, err}
|
||||
}
|
||||
// TODO: do a better job of printing objects here.
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -200,11 +185,29 @@ func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise.
|
||||
func (precondition *ScalePrecondition) ValidateJob(job *extensions.Job) error {
|
||||
if precondition.Size != -1 && job.Spec.Parallelism == nil {
|
||||
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), "nil"}
|
||||
}
|
||||
if precondition.Size != -1 && *job.Spec.Parallelism != precondition.Size {
|
||||
return PreconditionError{"parallelism", strconv.Itoa(precondition.Size), strconv.Itoa(*job.Spec.Parallelism)}
|
||||
}
|
||||
if len(precondition.ResourceVersion) != 0 && job.ResourceVersion != precondition.ResourceVersion {
|
||||
return PreconditionError{"resource version", precondition.ResourceVersion, job.ResourceVersion}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type JobScaler struct {
|
||||
c client.ExtensionsInterface
|
||||
}
|
||||
|
||||
// ScaleSimple is responsible for updating job's parallelism.
|
||||
func (scaler *JobScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) error {
|
||||
job, err := scaler.c.Extensions().Jobs(namespace).Get(name)
|
||||
job, err := scaler.c.Jobs(namespace).Get(name)
|
||||
if err != nil {
|
||||
return ControllerScaleError{ControllerScaleGetFailure, "Unknown", err}
|
||||
return ScaleError{ScaleGetFailure, "Unknown", err}
|
||||
}
|
||||
if preconditions != nil {
|
||||
if err := preconditions.ValidateJob(job); err != nil {
|
||||
@ -213,12 +216,11 @@ func (scaler *JobScaler) ScaleSimple(namespace, name string, preconditions *Scal
|
||||
}
|
||||
parallelism := int(newSize)
|
||||
job.Spec.Parallelism = ¶llelism
|
||||
if _, err := scaler.c.Extensions().Jobs(namespace).Update(job); err != nil {
|
||||
if _, err := scaler.c.Jobs(namespace).Update(job); err != nil {
|
||||
if errors.IsInvalid(err) {
|
||||
return ControllerScaleError{ControllerScaleUpdateInvalidFailure, job.ResourceVersion, err}
|
||||
return ScaleError{ScaleUpdateInvalidFailure, job.ResourceVersion, err}
|
||||
}
|
||||
return ControllerScaleError{ControllerScaleUpdateFailure, job.ResourceVersion, err}
|
||||
|
||||
return ScaleError{ScaleUpdateFailure, job.ResourceVersion, err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -239,7 +241,7 @@ func (scaler *JobScaler) Scale(namespace, name string, newSize uint, preconditio
|
||||
return err
|
||||
}
|
||||
if waitForReplicas != nil {
|
||||
job, err := scaler.c.Extensions().Jobs(namespace).Get(name)
|
||||
job, err := scaler.c.Jobs(namespace).Get(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -248,3 +250,65 @@ 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 && deployment.Spec.Replicas != precondition.Size {
|
||||
return PreconditionError{"replicas", strconv.Itoa(precondition.Size), strconv.Itoa(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
|
||||
}
|
||||
|
||||
// ScaleSimple is responsible for updating a deployment's desired replicas count.
|
||||
func (scaler *DeploymentScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) error {
|
||||
deployment, err := scaler.c.Deployments(namespace).Get(name)
|
||||
if err != nil {
|
||||
return ScaleError{ScaleGetFailure, "Unknown", err}
|
||||
}
|
||||
if preconditions != nil {
|
||||
if err := preconditions.ValidateDeployment(deployment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
scale := extensions.ScaleFromDeployment(deployment)
|
||||
scale.Spec.Replicas = int(newSize)
|
||||
if _, err := scaler.c.Scales(namespace).Update("Deployment", scale); err != nil {
|
||||
if errors.IsInvalid(err) {
|
||||
return ScaleError{ScaleUpdateInvalidFailure, deployment.ResourceVersion, err}
|
||||
}
|
||||
return ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scale updates a deployment to a new size, with optional precondition check (if preconditions is not nil),
|
||||
// optional retries (if retry is not nil), and then optionally waits for the status to reach desired count.
|
||||
func (scaler *DeploymentScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error {
|
||||
if preconditions == nil {
|
||||
preconditions = &ScalePrecondition{-1, ""}
|
||||
}
|
||||
if retry == nil {
|
||||
// Make it try only once, immediately
|
||||
retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond}
|
||||
}
|
||||
cond := ScaleCondition(scaler, preconditions, namespace, name, newSize)
|
||||
if err := wait.Poll(retry.Interval, retry.Timeout, cond); err != nil {
|
||||
return err
|
||||
}
|
||||
if waitForReplicas != nil {
|
||||
deployment, err := scaler.c.Deployments(namespace).Get(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return wait.Poll(waitForReplicas.Interval, waitForReplicas.Timeout,
|
||||
client.DeploymentHasDesiredReplicas(scaler.c, deployment))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -48,45 +48,6 @@ func (c *ErrorReplicationControllerClient) ReplicationControllers(namespace stri
|
||||
return &ErrorReplicationControllers{testclient.FakeReplicationControllers{Fake: &c.Fake, Namespace: namespace}, c.invalid}
|
||||
}
|
||||
|
||||
type ErrorJobs struct {
|
||||
testclient.FakeJobs
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
||||
if c.invalid {
|
||||
return nil, kerrors.NewInvalid(job.Kind, job.Name, nil)
|
||||
}
|
||||
return nil, errors.New("Job update failure")
|
||||
}
|
||||
|
||||
func (c *ErrorJobs) Get(name string) (*extensions.Job, error) {
|
||||
zero := 0
|
||||
return &extensions.Job{
|
||||
Spec: extensions.JobSpec{
|
||||
Parallelism: &zero,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ErrorJobClient struct {
|
||||
testclient.FakeExperimental
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorJobClient) Jobs(namespace string) client.JobInterface {
|
||||
return &ErrorJobs{testclient.FakeJobs{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
|
||||
}
|
||||
|
||||
type ErrorExtensionsClient struct {
|
||||
testclient.Fake
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorExtensionsClient) Extensions() client.ExtensionsInterface {
|
||||
return &ErrorJobClient{testclient.FakeExperimental{&c.Fake}, c.invalid}
|
||||
}
|
||||
|
||||
func TestReplicationControllerScaleRetry(t *testing.T) {
|
||||
fake := &ErrorReplicationControllerClient{Fake: testclient.Fake{}, invalid: false}
|
||||
scaler := ReplicationControllerScaler{fake}
|
||||
@ -124,8 +85,8 @@ func TestReplicationControllerScaleInvalid(t *testing.T) {
|
||||
if pass {
|
||||
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
|
||||
}
|
||||
e, ok := err.(ControllerScaleError)
|
||||
if err == nil || !ok || e.FailureType != ControllerScaleUpdateInvalidFailure {
|
||||
e, ok := err.(ScaleError)
|
||||
if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure {
|
||||
t.Errorf("Expected error on invalid update failure, got %v", err)
|
||||
}
|
||||
}
|
||||
@ -286,8 +247,38 @@ func TestValidateReplicationController(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type ErrorJobs struct {
|
||||
testclient.FakeJobs
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
||||
if c.invalid {
|
||||
return nil, kerrors.NewInvalid(job.Kind, job.Name, nil)
|
||||
}
|
||||
return nil, errors.New("Job update failure")
|
||||
}
|
||||
|
||||
func (c *ErrorJobs) Get(name string) (*extensions.Job, error) {
|
||||
zero := 0
|
||||
return &extensions.Job{
|
||||
Spec: extensions.JobSpec{
|
||||
Parallelism: &zero,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ErrorJobClient struct {
|
||||
testclient.FakeExperimental
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorJobClient) Jobs(namespace string) client.JobInterface {
|
||||
return &ErrorJobs{testclient.FakeJobs{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
|
||||
}
|
||||
|
||||
func TestJobScaleRetry(t *testing.T) {
|
||||
fake := &ErrorExtensionsClient{Fake: testclient.Fake{}, invalid: false}
|
||||
fake := &ErrorJobClient{FakeExperimental: testclient.FakeExperimental{}, invalid: false}
|
||||
scaler := JobScaler{fake}
|
||||
preconditions := ScalePrecondition{-1, ""}
|
||||
count := uint(3)
|
||||
@ -311,7 +302,7 @@ func TestJobScaleRetry(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestJobScale(t *testing.T) {
|
||||
fake := &testclient.Fake{}
|
||||
fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}}
|
||||
scaler := JobScaler{fake}
|
||||
preconditions := ScalePrecondition{-1, ""}
|
||||
count := uint(3)
|
||||
@ -331,7 +322,7 @@ func TestJobScale(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestJobScaleInvalid(t *testing.T) {
|
||||
fake := &ErrorExtensionsClient{Fake: testclient.Fake{}, invalid: true}
|
||||
fake := &ErrorJobClient{FakeExperimental: testclient.FakeExperimental{}, invalid: true}
|
||||
scaler := JobScaler{fake}
|
||||
preconditions := ScalePrecondition{-1, ""}
|
||||
count := uint(3)
|
||||
@ -343,8 +334,8 @@ func TestJobScaleInvalid(t *testing.T) {
|
||||
if pass {
|
||||
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
|
||||
}
|
||||
e, ok := err.(ControllerScaleError)
|
||||
if err == nil || !ok || e.FailureType != ControllerScaleUpdateInvalidFailure {
|
||||
e, ok := err.(ScaleError)
|
||||
if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure {
|
||||
t.Errorf("Expected error on invalid update failure, got %v", err)
|
||||
}
|
||||
}
|
||||
@ -356,7 +347,7 @@ func TestJobScaleFailsPreconditions(t *testing.T) {
|
||||
Parallelism: &ten,
|
||||
},
|
||||
})
|
||||
scaler := JobScaler{fake}
|
||||
scaler := JobScaler{&testclient.FakeExperimental{fake}}
|
||||
preconditions := ScalePrecondition{2, ""}
|
||||
count := uint(3)
|
||||
name := "foo"
|
||||
@ -496,3 +487,267 @@ func TestValidateJob(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ErrorScales struct {
|
||||
testclient.FakeScales
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
|
||||
if c.invalid {
|
||||
return nil, kerrors.NewInvalid(scale.Kind, scale.Name, nil)
|
||||
}
|
||||
return nil, errors.New("scale update failure")
|
||||
}
|
||||
|
||||
func (c *ErrorScales) Get(kind, name string) (*extensions.Scale, error) {
|
||||
return &extensions.Scale{
|
||||
Spec: extensions.ScaleSpec{
|
||||
Replicas: 0,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ErrorDeployments struct {
|
||||
testclient.FakeDeployments
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
|
||||
if c.invalid {
|
||||
return nil, kerrors.NewInvalid(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
|
||||
invalid bool
|
||||
}
|
||||
|
||||
func (c *ErrorDeploymentClient) Deployments(namespace string) client.DeploymentInterface {
|
||||
return &ErrorDeployments{testclient.FakeDeployments{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
|
||||
}
|
||||
|
||||
func (c *ErrorDeploymentClient) Scales(namespace string) client.ScaleInterface {
|
||||
return &ErrorScales{testclient.FakeScales{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
|
||||
}
|
||||
|
||||
func TestDeploymentScaleRetry(t *testing.T) {
|
||||
fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: false}
|
||||
scaler := &DeploymentScaler{fake}
|
||||
preconditions := &ScalePrecondition{-1, ""}
|
||||
count := uint(3)
|
||||
name := "foo"
|
||||
namespace := "default"
|
||||
|
||||
scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count)
|
||||
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)
|
||||
pass, err = scaleFunc()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error on precondition failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeploymentScale(t *testing.T) {
|
||||
fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}}
|
||||
scaler := DeploymentScaler{fake}
|
||||
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].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
|
||||
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
|
||||
}
|
||||
// TODO: The testclient needs to support subresources
|
||||
if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "Deployment" || action.GetObject().(*extensions.Scale).Spec.Replicas != int(count) {
|
||||
t.Errorf("unexpected action %v, expected update-deployment-scale with replicas = %d", actions[1], count)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeploymentScaleInvalid(t *testing.T) {
|
||||
fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: true}
|
||||
scaler := DeploymentScaler{fake}
|
||||
preconditions := ScalePrecondition{-1, ""}
|
||||
count := uint(3)
|
||||
name := "foo"
|
||||
namespace := "default"
|
||||
|
||||
scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count)
|
||||
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 != ScaleUpdateInvalidFailure {
|
||||
t.Errorf("Expected error on invalid update failure, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeploymentScaleFailsPreconditions(t *testing.T) {
|
||||
fake := testclient.NewSimpleFake(&extensions.Deployment{
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: 10,
|
||||
},
|
||||
})
|
||||
scaler := DeploymentScaler{&testclient.FakeExperimental{fake}}
|
||||
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].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
|
||||
t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDeployment(t *testing.T) {
|
||||
zero, ten, twenty := 0, 10, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,20 +132,7 @@ func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
|
||||
if err != nil {
|
||||
return nil, errors.NewNotFound("scale", name)
|
||||
}
|
||||
return &extensions.Scale{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: deployment.Namespace,
|
||||
CreationTimestamp: deployment.CreationTimestamp,
|
||||
},
|
||||
Spec: extensions.ScaleSpec{
|
||||
Replicas: deployment.Spec.Replicas,
|
||||
},
|
||||
Status: extensions.ScaleStatus{
|
||||
Replicas: deployment.Status.Replicas,
|
||||
Selector: deployment.Spec.Selector,
|
||||
},
|
||||
}, nil
|
||||
return extensions.ScaleFromDeployment(deployment), nil
|
||||
}
|
||||
|
||||
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
||||
@ -170,18 +157,5 @@ func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object,
|
||||
if err != nil {
|
||||
return nil, false, errors.NewConflict("scale", scale.Name, err)
|
||||
}
|
||||
return &extensions.Scale{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: deployment.Name,
|
||||
Namespace: deployment.Namespace,
|
||||
CreationTimestamp: deployment.CreationTimestamp,
|
||||
},
|
||||
Spec: extensions.ScaleSpec{
|
||||
Replicas: deployment.Spec.Replicas,
|
||||
},
|
||||
Status: extensions.ScaleStatus{
|
||||
Replicas: deployment.Status.Replicas,
|
||||
Selector: deployment.Spec.Selector,
|
||||
},
|
||||
}, false, nil
|
||||
return extensions.ScaleFromDeployment(deployment), false, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user