Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
c340d664
Commit
c340d664
authored
Sep 24, 2015
by
Eric Tune
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14046 from soltysh/job_controller_reaper_scaler
Reaper and scaler for jobs
parents
33c4c50c
48775319
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
215 additions
and
48 deletions
+215
-48
conditions.go
pkg/client/unversioned/conditions.go
+21
-0
factory.go
pkg/kubectl/cmd/util/factory.go
+1
-1
rolling_updater.go
pkg/kubectl/rolling_updater.go
+2
-4
scale.go
pkg/kubectl/scale.go
+81
-40
scale_test.go
pkg/kubectl/scale_test.go
+0
-0
stop.go
pkg/kubectl/stop.go
+35
-1
stop_test.go
pkg/kubectl/stop_test.go
+73
-0
util.go
test/e2e/util.go
+1
-1
master_utils.go
test/integration/framework/master_utils.go
+1
-1
No files found.
pkg/client/unversioned/conditions.go
View file @
c340d664
...
@@ -18,6 +18,7 @@ package unversioned
...
@@ -18,6 +18,7 @@ package unversioned
import
(
import
(
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/experimental"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/util/wait"
)
)
...
@@ -41,3 +42,23 @@ func ControllerHasDesiredReplicas(c Interface, controller *api.ReplicationContro
...
@@ -41,3 +42,23 @@ func ControllerHasDesiredReplicas(c Interface, controller *api.ReplicationContro
return
ctrl
.
Status
.
ObservedGeneration
>=
desiredGeneration
&&
ctrl
.
Status
.
Replicas
==
ctrl
.
Spec
.
Replicas
,
nil
return
ctrl
.
Status
.
ObservedGeneration
>=
desiredGeneration
&&
ctrl
.
Status
.
Replicas
==
ctrl
.
Spec
.
Replicas
,
nil
}
}
}
}
// 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
*
experimental
.
Job
)
wait
.
ConditionFunc
{
return
func
()
(
bool
,
error
)
{
job
,
err
:=
c
.
Experimental
()
.
Jobs
(
job
.
Namespace
)
.
Get
(
job
.
Name
)
if
err
!=
nil
{
return
false
,
err
}
// desired parallelism can be either the exact number, in which case return immediately
if
job
.
Status
.
Active
==
*
job
.
Spec
.
Parallelism
{
return
true
,
nil
}
// otherwise count successful
progress
:=
*
job
.
Spec
.
Completions
-
job
.
Status
.
Active
-
job
.
Status
.
Successful
return
progress
==
0
,
nil
}
}
pkg/kubectl/cmd/util/factory.go
View file @
c340d664
...
@@ -212,7 +212,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
...
@@ -212,7 +212,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
kubectl
.
ScalerFor
(
mapping
.
Kind
,
kubectl
.
NewScalerClient
(
client
)
)
return
kubectl
.
ScalerFor
(
mapping
.
Kind
,
client
)
},
},
Reaper
:
func
(
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Reaper
,
error
)
{
Reaper
:
func
(
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Reaper
,
error
)
{
client
,
err
:=
clients
.
ClientForVersion
(
mapping
.
APIVersion
)
client
,
err
:=
clients
.
ClientForVersion
(
mapping
.
APIVersion
)
...
...
pkg/kubectl/rolling_updater.go
View file @
c340d664
...
@@ -340,8 +340,7 @@ func (r *RollingUpdater) scaleDown(newRc, oldRc *api.ReplicationController, desi
...
@@ -340,8 +340,7 @@ func (r *RollingUpdater) scaleDown(newRc, oldRc *api.ReplicationController, desi
// scalerScaleAndWait scales a controller using a Scaler and a real client.
// scalerScaleAndWait scales a controller using a Scaler and a real client.
func
(
r
*
RollingUpdater
)
scaleAndWaitWithScaler
(
rc
*
api
.
ReplicationController
,
retry
*
RetryParams
,
wait
*
RetryParams
)
(
*
api
.
ReplicationController
,
error
)
{
func
(
r
*
RollingUpdater
)
scaleAndWaitWithScaler
(
rc
*
api
.
ReplicationController
,
retry
*
RetryParams
,
wait
*
RetryParams
)
(
*
api
.
ReplicationController
,
error
)
{
scalerClient
:=
NewScalerClient
(
r
.
c
)
scaler
,
err
:=
ScalerFor
(
"ReplicationController"
,
r
.
c
)
scaler
,
err
:=
ScalerFor
(
"ReplicationController"
,
scalerClient
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Couldn't make scaler: %s"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Couldn't make scaler: %s"
,
err
)
}
}
...
@@ -452,8 +451,7 @@ func (r *RollingUpdater) cleanupWithClients(oldRc, newRc *api.ReplicationControl
...
@@ -452,8 +451,7 @@ func (r *RollingUpdater) cleanupWithClients(oldRc, newRc *api.ReplicationControl
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
scalerClient
:=
NewScalerClient
(
r
.
c
)
if
err
=
wait
.
Poll
(
config
.
Interval
,
config
.
Timeout
,
client
.
ControllerHasDesiredReplicas
(
r
.
c
,
newRc
));
err
!=
nil
{
if
err
=
wait
.
Poll
(
config
.
Interval
,
config
.
Timeout
,
scalerClient
.
ControllerHasDesiredReplicas
(
newRc
));
err
!=
nil
{
return
err
return
err
}
}
newRc
,
err
=
r
.
c
.
ReplicationControllers
(
r
.
ns
)
.
Get
(
newRc
.
Name
)
newRc
,
err
=
r
.
c
.
ReplicationControllers
(
r
.
ns
)
.
Get
(
newRc
.
Name
)
...
...
pkg/kubectl/scale.go
View file @
c340d664
...
@@ -23,6 +23,7 @@ import (
...
@@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/apis/experimental"
client
"k8s.io/kubernetes/pkg/client/unversioned"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/util/wait"
)
)
...
@@ -70,8 +71,8 @@ func (c ControllerScaleError) Error() string {
...
@@ -70,8 +71,8 @@ func (c ControllerScaleError) Error() string {
c
.
ActualError
,
c
.
ResourceVersion
)
c
.
ActualError
,
c
.
ResourceVersion
)
}
}
// Validate ensures that the preconditions match. Returns nil if they are valid, an error otherwise
// Validate
ReplicationController
ensures that the preconditions match. Returns nil if they are valid, an error otherwise
func
(
precondition
*
ScalePrecondition
)
Validate
(
controller
*
api
.
ReplicationController
)
error
{
func
(
precondition
*
ScalePrecondition
)
Validate
ReplicationController
(
controller
*
api
.
ReplicationController
)
error
{
if
precondition
.
Size
!=
-
1
&&
controller
.
Spec
.
Replicas
!=
precondition
.
Size
{
if
precondition
.
Size
!=
-
1
&&
controller
.
Spec
.
Replicas
!=
precondition
.
Size
{
return
PreconditionError
{
"replicas"
,
strconv
.
Itoa
(
precondition
.
Size
),
strconv
.
Itoa
(
controller
.
Spec
.
Replicas
)}
return
PreconditionError
{
"replicas"
,
strconv
.
Itoa
(
precondition
.
Size
),
strconv
.
Itoa
(
controller
.
Spec
.
Replicas
)}
}
}
...
@@ -81,6 +82,20 @@ func (precondition *ScalePrecondition) Validate(controller *api.ReplicationContr
...
@@ -81,6 +82,20 @@ func (precondition *ScalePrecondition) Validate(controller *api.ReplicationContr
return
nil
return
nil
}
}
// ValidateJob ensures that the preconditions match. Returns nil if they are valid, an error otherwise
func
(
precondition
*
ScalePrecondition
)
ValidateJob
(
job
*
experimental
.
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
}
type
Scaler
interface
{
type
Scaler
interface
{
// Scale scales the named resource after checking preconditions. It optionally
// Scale scales the named resource after checking preconditions. It optionally
// retries in the event of resource version mismatch (if retry is not nil),
// retries in the event of resource version mismatch (if retry is not nil),
...
@@ -88,19 +103,24 @@ type Scaler interface {
...
@@ -88,19 +103,24 @@ type Scaler interface {
Scale
(
namespace
,
name
string
,
newSize
uint
,
preconditions
*
ScalePrecondition
,
retry
,
wait
*
RetryParams
)
error
Scale
(
namespace
,
name
string
,
newSize
uint
,
preconditions
*
ScalePrecondition
,
retry
,
wait
*
RetryParams
)
error
// ScaleSimple does a simple one-shot attempt at scaling - not useful on it's own, but
// ScaleSimple does a simple one-shot attempt at scaling - not useful on it's own, but
// a necessary building block for Scale
// a necessary building block for Scale
ScaleSimple
(
namespace
,
name
string
,
preconditions
*
ScalePrecondition
,
newSize
uint
)
(
string
,
error
)
ScaleSimple
(
namespace
,
name
string
,
preconditions
*
ScalePrecondition
,
newSize
uint
)
error
}
}
func
ScalerFor
(
kind
string
,
c
ScalerClient
)
(
Scaler
,
error
)
{
func
ScalerFor
(
kind
string
,
c
client
.
Interface
)
(
Scaler
,
error
)
{
switch
kind
{
switch
kind
{
case
"ReplicationController"
:
case
"ReplicationController"
:
return
&
ReplicationControllerScaler
{
c
},
nil
return
&
ReplicationControllerScaler
{
c
},
nil
case
"Job"
:
return
&
JobScaler
{
c
},
nil
}
}
return
nil
,
fmt
.
Errorf
(
"no scaler has been implemented for %q"
,
kind
)
return
nil
,
fmt
.
Errorf
(
"no scaler has been implemented for %q"
,
kind
)
}
}
type
ReplicationControllerScaler
struct
{
type
ReplicationControllerScaler
struct
{
c
ScalerClient
c
client
.
Interface
}
type
JobScaler
struct
{
c
client
.
Interface
}
}
// RetryParams encapsulates the retry parameters used by kubectl's scaler.
// RetryParams encapsulates the retry parameters used by kubectl's scaler.
...
@@ -115,7 +135,7 @@ func NewRetryParams(interval, timeout time.Duration) *RetryParams {
...
@@ -115,7 +135,7 @@ func NewRetryParams(interval, timeout time.Duration) *RetryParams {
// ScaleCondition is a closure around Scale that facilitates retries via util.wait
// ScaleCondition is a closure around Scale that facilitates retries via util.wait
func
ScaleCondition
(
r
Scaler
,
precondition
*
ScalePrecondition
,
namespace
,
name
string
,
count
uint
)
wait
.
ConditionFunc
{
func
ScaleCondition
(
r
Scaler
,
precondition
*
ScalePrecondition
,
namespace
,
name
string
,
count
uint
)
wait
.
ConditionFunc
{
return
func
()
(
bool
,
error
)
{
return
func
()
(
bool
,
error
)
{
_
,
err
:=
r
.
ScaleSimple
(
namespace
,
name
,
precondition
,
count
)
err
:=
r
.
ScaleSimple
(
namespace
,
name
,
precondition
,
count
)
switch
e
,
_
:=
err
.
(
ControllerScaleError
);
err
.
(
type
)
{
switch
e
,
_
:=
err
.
(
ControllerScaleError
);
err
.
(
type
)
{
case
nil
:
case
nil
:
return
true
,
nil
return
true
,
nil
...
@@ -132,26 +152,26 @@ func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name s
...
@@ -132,26 +152,26 @@ func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name s
}
}
}
}
func
(
scaler
*
ReplicationControllerScaler
)
ScaleSimple
(
namespace
,
name
string
,
preconditions
*
ScalePrecondition
,
newSize
uint
)
(
string
,
error
)
{
func
(
scaler
*
ReplicationControllerScaler
)
ScaleSimple
(
namespace
,
name
string
,
preconditions
*
ScalePrecondition
,
newSize
uint
)
error
{
controller
,
err
:=
scaler
.
c
.
GetReplicationController
(
namespace
,
name
)
controller
,
err
:=
scaler
.
c
.
ReplicationControllers
(
namespace
)
.
Get
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
ControllerScaleError
{
ControllerScaleGetFailure
,
"Unknown"
,
err
}
return
ControllerScaleError
{
ControllerScaleGetFailure
,
"Unknown"
,
err
}
}
}
if
preconditions
!=
nil
{
if
preconditions
!=
nil
{
if
err
:=
preconditions
.
Validate
(
controller
);
err
!=
nil
{
if
err
:=
preconditions
.
Validate
ReplicationController
(
controller
);
err
!=
nil
{
return
""
,
err
return
err
}
}
}
}
controller
.
Spec
.
Replicas
=
int
(
newSize
)
controller
.
Spec
.
Replicas
=
int
(
newSize
)
// TODO: do retry on 409 errors here?
// TODO: do retry on 409 errors here?
if
_
,
err
:=
scaler
.
c
.
UpdateReplicationController
(
namespace
,
controller
);
err
!=
nil
{
if
_
,
err
:=
scaler
.
c
.
ReplicationControllers
(
namespace
)
.
Update
(
controller
);
err
!=
nil
{
if
errors
.
IsInvalid
(
err
)
{
if
errors
.
IsInvalid
(
err
)
{
return
""
,
ControllerScaleError
{
ControllerScaleUpdateInvalidFailure
,
controller
.
ResourceVersion
,
err
}
return
ControllerScaleError
{
ControllerScaleUpdateInvalidFailure
,
controller
.
ResourceVersion
,
err
}
}
}
return
""
,
ControllerScaleError
{
ControllerScaleUpdateFailure
,
controller
.
ResourceVersion
,
err
}
return
ControllerScaleError
{
ControllerScaleUpdateFailure
,
controller
.
ResourceVersion
,
err
}
}
}
// TODO: do a better job of printing objects here.
// TODO: do a better job of printing objects here.
return
"scaled"
,
nil
return
nil
}
}
// Scale updates a ReplicationController to a new size, with optional precondition check (if preconditions is not nil),
// Scale updates a ReplicationController to a new size, with optional precondition check (if preconditions is not nil),
...
@@ -170,40 +190,61 @@ func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize
...
@@ -170,40 +190,61 @@ func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize
return
err
return
err
}
}
if
waitForReplicas
!=
nil
{
if
waitForReplicas
!=
nil
{
rc
,
err
:=
scaler
.
c
.
GetReplicationController
(
namespace
,
name
)
rc
,
err
:=
scaler
.
c
.
ReplicationControllers
(
namespace
)
.
Get
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
return
wait
.
Poll
(
waitForReplicas
.
Interval
,
waitForReplicas
.
Timeout
,
return
wait
.
Poll
(
waitForReplicas
.
Interval
,
waitForReplicas
.
Timeout
,
scaler
.
c
.
ControllerHasDesiredReplicas
(
rc
))
client
.
ControllerHasDesiredReplicas
(
scaler
.
c
,
rc
))
}
}
return
nil
return
nil
}
}
// ScalerClient abstracts access to ReplicationControllers.
// ScaleSimple is responsible for updating job's parallelism.
type
ScalerClient
interface
{
func
(
scaler
*
JobScaler
)
ScaleSimple
(
namespace
,
name
string
,
preconditions
*
ScalePrecondition
,
newSize
uint
)
error
{
GetReplicationController
(
namespace
,
name
string
)
(
*
api
.
ReplicationController
,
error
)
job
,
err
:=
scaler
.
c
.
Experimental
()
.
Jobs
(
namespace
)
.
Get
(
name
)
UpdateReplicationController
(
namespace
string
,
rc
*
api
.
ReplicationController
)
(
*
api
.
ReplicationController
,
error
)
if
err
!=
nil
{
ControllerHasDesiredReplicas
(
rc
*
api
.
ReplicationController
)
wait
.
ConditionFunc
return
ControllerScaleError
{
ControllerScaleGetFailure
,
"Unknown"
,
err
}
}
}
if
preconditions
!=
nil
{
func
NewScalerClient
(
c
client
.
Interface
)
ScalerClient
{
if
err
:=
preconditions
.
ValidateJob
(
job
);
err
!=
nil
{
return
&
realScalerClient
{
c
}
return
err
}
}
}
// realScalerClient is a ScalerClient which uses a Kube client.
parallelism
:=
int
(
newSize
)
type
realScalerClient
struct
{
job
.
Spec
.
Parallelism
=
&
parallelism
client
client
.
Interface
if
_
,
err
:=
scaler
.
c
.
Experimental
()
.
Jobs
(
namespace
)
.
Update
(
job
);
err
!=
nil
{
}
if
errors
.
IsInvalid
(
err
)
{
return
ControllerScaleError
{
ControllerScaleUpdateInvalidFailure
,
job
.
ResourceVersion
,
err
}
func
(
c
*
realScalerClient
)
GetReplicationController
(
namespace
,
name
string
)
(
*
api
.
ReplicationController
,
error
)
{
}
return
c
.
client
.
ReplicationControllers
(
namespace
)
.
Get
(
name
)
return
ControllerScaleError
{
ControllerScaleUpdateFailure
,
job
.
ResourceVersion
,
err
}
}
func
(
c
*
realScalerClient
)
UpdateReplicationController
(
namespace
string
,
rc
*
api
.
ReplicationController
)
(
*
api
.
ReplicationController
,
error
)
{
}
return
c
.
client
.
ReplicationControllers
(
namespace
)
.
Update
(
rc
)
return
nil
}
}
func
(
c
*
realScalerClient
)
ControllerHasDesiredReplicas
(
rc
*
api
.
ReplicationController
)
wait
.
ConditionFunc
{
// Scale updates a Job to a new size, with optional precondition check (if preconditions is not nil),
return
client
.
ControllerHasDesiredReplicas
(
c
.
client
,
rc
)
// optional retries (if retry is not nil), and then optionally waits for parallelism to reach desired
// number, which can be less than requested based on job's current progress.
func
(
scaler
*
JobScaler
)
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
{
job
,
err
:=
scaler
.
c
.
Experimental
()
.
Jobs
(
namespace
)
.
Get
(
name
)
if
err
!=
nil
{
return
err
}
return
wait
.
Poll
(
waitForReplicas
.
Interval
,
waitForReplicas
.
Timeout
,
client
.
JobHasDesiredParallelism
(
scaler
.
c
,
job
))
}
return
nil
}
}
pkg/kubectl/scale_test.go
View file @
c340d664
This diff is collapsed.
Click to expand it.
pkg/kubectl/stop.go
View file @
c340d664
...
@@ -65,6 +65,8 @@ func ReaperFor(kind string, c client.Interface) (Reaper, error) {
...
@@ -65,6 +65,8 @@ func ReaperFor(kind string, c client.Interface) (Reaper, error) {
return
&
PodReaper
{
c
},
nil
return
&
PodReaper
{
c
},
nil
case
"Service"
:
case
"Service"
:
return
&
ServiceReaper
{
c
},
nil
return
&
ServiceReaper
{
c
},
nil
case
"Job"
:
return
&
JobReaper
{
c
,
Interval
,
Timeout
},
nil
}
}
return
nil
,
&
NoSuchReaperError
{
kind
}
return
nil
,
&
NoSuchReaperError
{
kind
}
}
}
...
@@ -81,6 +83,10 @@ type DaemonSetReaper struct {
...
@@ -81,6 +83,10 @@ type DaemonSetReaper struct {
client
.
Interface
client
.
Interface
pollInterval
,
timeout
time
.
Duration
pollInterval
,
timeout
time
.
Duration
}
}
type
JobReaper
struct
{
client
.
Interface
pollInterval
,
timeout
time
.
Duration
}
type
PodReaper
struct
{
type
PodReaper
struct
{
client
.
Interface
client
.
Interface
}
}
...
@@ -112,7 +118,7 @@ func getOverlappingControllers(c client.ReplicationControllerInterface, rc *api.
...
@@ -112,7 +118,7 @@ func getOverlappingControllers(c client.ReplicationControllerInterface, rc *api.
func
(
reaper
*
ReplicationControllerReaper
)
Stop
(
namespace
,
name
string
,
timeout
time
.
Duration
,
gracePeriod
*
api
.
DeleteOptions
)
(
string
,
error
)
{
func
(
reaper
*
ReplicationControllerReaper
)
Stop
(
namespace
,
name
string
,
timeout
time
.
Duration
,
gracePeriod
*
api
.
DeleteOptions
)
(
string
,
error
)
{
rc
:=
reaper
.
ReplicationControllers
(
namespace
)
rc
:=
reaper
.
ReplicationControllers
(
namespace
)
scaler
,
err
:=
ScalerFor
(
"ReplicationController"
,
NewScalerClient
(
*
reaper
)
)
scaler
,
err
:=
ScalerFor
(
"ReplicationController"
,
*
reaper
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
...
@@ -223,6 +229,34 @@ func (reaper *DaemonSetReaper) Stop(namespace, name string, timeout time.Duratio
...
@@ -223,6 +229,34 @@ func (reaper *DaemonSetReaper) Stop(namespace, name string, timeout time.Duratio
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
}
}
func
(
reaper
*
JobReaper
)
Stop
(
namespace
,
name
string
,
timeout
time
.
Duration
,
gracePeriod
*
api
.
DeleteOptions
)
(
string
,
error
)
{
jobs
:=
reaper
.
Experimental
()
.
Jobs
(
namespace
)
scaler
,
err
:=
ScalerFor
(
"Job"
,
*
reaper
)
if
err
!=
nil
{
return
""
,
err
}
job
,
err
:=
jobs
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
if
timeout
==
0
{
// we will never have more active pods than job.Spec.Parallelism
parallelism
:=
*
job
.
Spec
.
Parallelism
timeout
=
Timeout
+
time
.
Duration
(
10
*
parallelism
)
*
time
.
Second
}
// TODO: handle overlapping jobs
retry
:=
NewRetryParams
(
reaper
.
pollInterval
,
reaper
.
timeout
)
waitForJobs
:=
NewRetryParams
(
reaper
.
pollInterval
,
timeout
)
if
err
=
scaler
.
Scale
(
namespace
,
name
,
0
,
nil
,
retry
,
waitForJobs
);
err
!=
nil
{
return
""
,
err
}
if
err
:=
jobs
.
Delete
(
name
,
gracePeriod
);
err
!=
nil
{
return
""
,
err
}
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
}
func
(
reaper
*
PodReaper
)
Stop
(
namespace
,
name
string
,
timeout
time
.
Duration
,
gracePeriod
*
api
.
DeleteOptions
)
(
string
,
error
)
{
func
(
reaper
*
PodReaper
)
Stop
(
namespace
,
name
string
,
timeout
time
.
Duration
,
gracePeriod
*
api
.
DeleteOptions
)
(
string
,
error
)
{
pods
:=
reaper
.
Pods
(
namespace
)
pods
:=
reaper
.
Pods
(
namespace
)
_
,
err
:=
pods
.
Get
(
name
)
_
,
err
:=
pods
.
Get
(
name
)
...
...
pkg/kubectl/stop_test.go
View file @
c340d664
...
@@ -23,6 +23,7 @@ import (
...
@@ -23,6 +23,7 @@ import (
"time"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/experimental"
client
"k8s.io/kubernetes/pkg/client/unversioned"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
...
@@ -271,6 +272,78 @@ func TestReplicationControllerStop(t *testing.T) {
...
@@ -271,6 +272,78 @@ func TestReplicationControllerStop(t *testing.T) {
}
}
}
}
func
TestJobStop
(
t
*
testing
.
T
)
{
name
:=
"foo"
ns
:=
"default"
zero
:=
0
tests
:=
[]
struct
{
Name
string
Objs
[]
runtime
.
Object
StopError
error
StopMessage
string
ExpectedActions
[]
string
}{
{
Name
:
"OnlyOneJob"
,
Objs
:
[]
runtime
.
Object
{
&
experimental
.
Job
{
// GET
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
name
,
Namespace
:
ns
,
},
Spec
:
experimental
.
JobSpec
{
Parallelism
:
&
zero
,
Selector
:
map
[
string
]
string
{
"k1"
:
"v1"
}},
},
&
experimental
.
JobList
{
// LIST
Items
:
[]
experimental
.
Job
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
name
,
Namespace
:
ns
,
},
Spec
:
experimental
.
JobSpec
{
Parallelism
:
&
zero
,
Selector
:
map
[
string
]
string
{
"k1"
:
"v1"
}},
},
},
},
},
StopError
:
nil
,
StopMessage
:
"foo stopped"
,
ExpectedActions
:
[]
string
{
"get"
,
"get"
,
"update"
,
"get"
,
"get"
,
"delete"
},
},
}
for
_
,
test
:=
range
tests
{
fake
:=
testclient
.
NewSimpleFake
(
test
.
Objs
...
)
reaper
:=
JobReaper
{
fake
,
time
.
Millisecond
,
time
.
Millisecond
}
s
,
err
:=
reaper
.
Stop
(
ns
,
name
,
0
,
nil
)
if
!
reflect
.
DeepEqual
(
err
,
test
.
StopError
)
{
t
.
Errorf
(
"%s unexpected error: %v"
,
test
.
Name
,
err
)
continue
}
if
s
!=
test
.
StopMessage
{
t
.
Errorf
(
"%s expected '%s', got '%s'"
,
test
.
Name
,
test
.
StopMessage
,
s
)
continue
}
actions
:=
fake
.
Actions
()
if
len
(
actions
)
!=
len
(
test
.
ExpectedActions
)
{
t
.
Errorf
(
"%s unexpected actions: %v, expected %d actions got %d"
,
test
.
Name
,
actions
,
len
(
test
.
ExpectedActions
),
len
(
actions
))
continue
}
for
i
,
verb
:=
range
test
.
ExpectedActions
{
if
actions
[
i
]
.
GetResource
()
!=
"jobs"
{
t
.
Errorf
(
"%s unexpected action: %+v, expected %s-job"
,
test
.
Name
,
actions
[
i
],
verb
)
}
if
actions
[
i
]
.
GetVerb
()
!=
verb
{
t
.
Errorf
(
"%s unexpected action: %+v, expected %s-job"
,
test
.
Name
,
actions
[
i
],
verb
)
}
}
}
}
type
noSuchPod
struct
{
type
noSuchPod
struct
{
*
testclient
.
FakePods
*
testclient
.
FakePods
}
}
...
...
test/e2e/util.go
View file @
c340d664
...
@@ -1427,7 +1427,7 @@ func getNodeEvents(c *client.Client, nodeName string) []api.Event {
...
@@ -1427,7 +1427,7 @@ func getNodeEvents(c *client.Client, nodeName string) []api.Event {
func
ScaleRC
(
c
*
client
.
Client
,
ns
,
name
string
,
size
uint
,
wait
bool
)
error
{
func
ScaleRC
(
c
*
client
.
Client
,
ns
,
name
string
,
size
uint
,
wait
bool
)
error
{
By
(
fmt
.
Sprintf
(
"%v Scaling replication controller %s in namespace %s to %d"
,
time
.
Now
(),
name
,
ns
,
size
))
By
(
fmt
.
Sprintf
(
"%v Scaling replication controller %s in namespace %s to %d"
,
time
.
Now
(),
name
,
ns
,
size
))
scaler
,
err
:=
kubectl
.
ScalerFor
(
"ReplicationController"
,
kubectl
.
NewScalerClient
(
c
)
)
scaler
,
err
:=
kubectl
.
ScalerFor
(
"ReplicationController"
,
c
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
test/integration/framework/master_utils.go
View file @
c340d664
...
@@ -208,7 +208,7 @@ func StopRC(rc *api.ReplicationController, restClient *client.Client) error {
...
@@ -208,7 +208,7 @@ func StopRC(rc *api.ReplicationController, restClient *client.Client) error {
// ScaleRC scales the given rc to the given replicas.
// ScaleRC scales the given rc to the given replicas.
func
ScaleRC
(
name
,
ns
string
,
replicas
int
,
restClient
*
client
.
Client
)
(
*
api
.
ReplicationController
,
error
)
{
func
ScaleRC
(
name
,
ns
string
,
replicas
int
,
restClient
*
client
.
Client
)
(
*
api
.
ReplicationController
,
error
)
{
scaler
,
err
:=
kubectl
.
ScalerFor
(
"ReplicationController"
,
kubectl
.
NewScalerClient
(
restClient
)
)
scaler
,
err
:=
kubectl
.
ScalerFor
(
"ReplicationController"
,
restClient
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment