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
201e99e0
Commit
201e99e0
authored
Jan 22, 2015
by
Jeff Lowdermilk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a kubectl stop command
parent
44aca6d9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
394 additions
and
10 deletions
+394
-10
kubectl.md
docs/kubectl.md
+44
-0
cmd.go
pkg/kubectl/cmd/cmd.go
+10
-4
stop.go
pkg/kubectl/cmd/stop.go
+56
-0
resize.go
pkg/kubectl/resize.go
+3
-3
rolling_updater_test.go
pkg/kubectl/rolling_updater_test.go
+3
-3
stop.go
pkg/kubectl/stop.go
+110
-0
stop_test.go
pkg/kubectl/stop_test.go
+168
-0
No files found.
docs/kubectl.md
View file @
201e99e0
...
@@ -394,6 +394,7 @@ Additional help topics:
...
@@ -394,6 +394,7 @@ Additional help topics:
kubectl rollingupdate Perform a rolling update of the given ReplicationController
kubectl rollingupdate Perform a rolling update of the given ReplicationController
kubectl resize Set a new size for a resizable resource (currently only Replication Controllers)
kubectl resize Set a new size for a resizable resource (currently only Replication Controllers)
kubectl run-container Run a particular image on the cluster.
kubectl run-container Run a particular image on the cluster.
kubectl stop Gracefully shutdown a resource
Use "kubectl help [command]" for more information about that command.
Use "kubectl help [command]" for more information about that command.
```
```
...
@@ -933,3 +934,46 @@ Usage:
...
@@ -933,3 +934,46 @@ Usage:
```
```
#### stop
Gracefully shutdown a resource
Attempts to shutdown and delete a resource that supports graceful termination.
If the resource is resizable it will be resized to 0 before deletion.
Examples:
$ kubectl stop replicationcontroller foo
foo stopped
Usage:
```
kubectl stop <resource> <id> [flags]
Available Flags:
--alsologtostderr=false: log to standard error as well as files
--api-version="": The API version to use when talking to the server
-a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https.
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client key file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
--log_dir=: If non-empty, write log files in this directory
--log_flush_frequency=5s: Maximum number of seconds between log flushes
--logtostderr=true: log to standard error instead of files
--match-server-version=false: Require server version to match client version
--namespace="": If present, the namespace scope for this CLI request.
--ns-path="": Path to the namespace info file that holds the namespace context to use for CLI requests.
-s, --server="": The address of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--v=0: log level for V logs
--validate=false: If true, use a schema to validate the input before sending it
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
pkg/kubectl/cmd/cmd.go
View file @
201e99e0
...
@@ -64,6 +64,8 @@ type Factory struct {
...
@@ -64,6 +64,8 @@ type Factory struct {
Printer
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
,
noHeaders
bool
)
(
kubectl
.
ResourcePrinter
,
error
)
Printer
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
,
noHeaders
bool
)
(
kubectl
.
ResourcePrinter
,
error
)
// Returns a Resizer for changing the size of the specified RESTMapping type or an error
// Returns a Resizer for changing the size of the specified RESTMapping type or an error
Resizer
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Resizer
,
error
)
Resizer
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Resizer
,
error
)
// Returns a Reaper for gracefully shutting down resources.
Reaper
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Reaper
,
error
)
// Returns a schema that can validate objects stored on disk.
// Returns a schema that can validate objects stored on disk.
Validator
func
(
*
cobra
.
Command
)
(
validation
.
Schema
,
error
)
Validator
func
(
*
cobra
.
Command
)
(
validation
.
Schema
,
error
)
// Returns the default namespace to use in cases where no other namespace is specified
// Returns the default namespace to use in cases where no other namespace is specified
...
@@ -131,11 +133,14 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
...
@@ -131,11 +133,14 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
resizer
,
ok
:=
kubectl
.
ResizerFor
(
mapping
.
Kind
,
client
)
return
kubectl
.
ResizerFor
(
mapping
.
Kind
,
client
)
if
!
ok
{
},
return
nil
,
fmt
.
Errorf
(
"no resizer has been implemented for %q"
,
mapping
.
Kind
)
Reaper
:
func
(
cmd
*
cobra
.
Command
,
mapping
*
meta
.
RESTMapping
)
(
kubectl
.
Reaper
,
error
)
{
client
,
err
:=
clients
.
ClientForVersion
(
mapping
.
APIVersion
)
if
err
!=
nil
{
return
nil
,
err
}
}
return
resizer
,
nil
return
kubectl
.
ReaperFor
(
mapping
.
Kind
,
client
)
},
},
Validator
:
func
(
cmd
*
cobra
.
Command
)
(
validation
.
Schema
,
error
)
{
Validator
:
func
(
cmd
*
cobra
.
Command
)
(
validation
.
Schema
,
error
)
{
if
GetFlagBool
(
cmd
,
"validate"
)
{
if
GetFlagBool
(
cmd
,
"validate"
)
{
...
@@ -206,6 +211,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
...
@@ -206,6 +211,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
cmds
.
AddCommand
(
f
.
NewCmdResize
(
out
))
cmds
.
AddCommand
(
f
.
NewCmdResize
(
out
))
cmds
.
AddCommand
(
f
.
NewCmdRunContainer
(
out
))
cmds
.
AddCommand
(
f
.
NewCmdRunContainer
(
out
))
cmds
.
AddCommand
(
f
.
NewCmdStop
(
out
))
return
cmds
return
cmds
}
}
...
...
pkg/kubectl/cmd/stop.go
0 → 100644
View file @
201e99e0
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
cmd
import
(
"fmt"
"io"
"github.com/spf13/cobra"
)
func
(
f
*
Factory
)
NewCmdStop
(
out
io
.
Writer
)
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"stop <resource> <id>"
,
Short
:
"Gracefully shutdown a resource"
,
Long
:
`Gracefully shutdown a resource
Attempts to shutdown and delete a resource that supports graceful termination.
If the resource is resizable it will be resized to 0 before deletion.
Examples:
$ kubectl stop replicationcontroller foo
foo stopped
`
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
if
len
(
args
)
!=
2
{
usageError
(
cmd
,
"<resource> <id>"
)
}
cmdNamespace
,
err
:=
f
.
DefaultNamespace
(
cmd
)
mapper
,
_
:=
f
.
Object
(
cmd
)
mapping
,
namespace
,
name
:=
ResourceFromArgs
(
cmd
,
args
,
mapper
,
cmdNamespace
)
reaper
,
err
:=
f
.
Reaper
(
cmd
,
mapping
)
checkErr
(
err
)
s
,
err
:=
reaper
.
Stop
(
namespace
,
name
)
checkErr
(
err
)
fmt
.
Fprintf
(
out
,
"%s
\n
"
,
s
)
},
}
return
cmd
}
pkg/kubectl/resize.go
View file @
201e99e0
...
@@ -58,12 +58,12 @@ type Resizer interface {
...
@@ -58,12 +58,12 @@ type Resizer interface {
Resize
(
namespace
,
name
string
,
preconditions
*
ResizePrecondition
,
newSize
uint
)
(
string
,
error
)
Resize
(
namespace
,
name
string
,
preconditions
*
ResizePrecondition
,
newSize
uint
)
(
string
,
error
)
}
}
func
ResizerFor
(
kind
string
,
c
*
client
.
Client
)
(
Resizer
,
bool
)
{
func
ResizerFor
(
kind
string
,
c
client
.
Interface
)
(
Resizer
,
error
)
{
switch
kind
{
switch
kind
{
case
"ReplicationController"
:
case
"ReplicationController"
:
return
&
ReplicationControllerResizer
{
c
},
true
return
&
ReplicationControllerResizer
{
c
},
nil
}
}
return
nil
,
f
alse
return
nil
,
f
mt
.
Errorf
(
"no resizer has been implemented for %q"
,
kind
)
}
}
type
ReplicationControllerResizer
struct
{
type
ReplicationControllerResizer
struct
{
...
...
pkg/kubectl/rolling_updater_test.go
View file @
201e99e0
...
@@ -26,18 +26,18 @@ import (
...
@@ -26,18 +26,18 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
)
)
type
custom
Fake
struct
{
type
updater
Fake
struct
{
*
client
.
Fake
*
client
.
Fake
ctrl
client
.
ReplicationControllerInterface
ctrl
client
.
ReplicationControllerInterface
}
}
func
(
c
*
custom
Fake
)
ReplicationControllers
(
namespace
string
)
client
.
ReplicationControllerInterface
{
func
(
c
*
updater
Fake
)
ReplicationControllers
(
namespace
string
)
client
.
ReplicationControllerInterface
{
return
c
.
ctrl
return
c
.
ctrl
}
}
func
fakeClientFor
(
namespace
string
,
responses
[]
fakeResponse
)
client
.
Interface
{
func
fakeClientFor
(
namespace
string
,
responses
[]
fakeResponse
)
client
.
Interface
{
fake
:=
client
.
Fake
{}
fake
:=
client
.
Fake
{}
return
&
custom
Fake
{
return
&
updater
Fake
{
&
fake
,
&
fake
,
&
fakeRc
{
&
fakeRc
{
&
client
.
FakeReplicationControllers
{
&
client
.
FakeReplicationControllers
{
...
...
pkg/kubectl/stop.go
0 → 100644
View file @
201e99e0
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
kubectl
import
(
"fmt"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait"
)
const
(
interval
=
time
.
Second
*
3
timeout
=
time
.
Minute
*
5
)
// A Reaper handles terminating an object as gracefully as possible.
type
Reaper
interface
{
Stop
(
namespace
,
name
string
)
(
string
,
error
)
}
func
ReaperFor
(
kind
string
,
c
client
.
Interface
)
(
Reaper
,
error
)
{
switch
kind
{
case
"ReplicationController"
:
return
&
ReplicationControllerReaper
{
c
,
interval
,
timeout
},
nil
case
"Pod"
:
return
&
PodReaper
{
c
},
nil
case
"Service"
:
return
&
ServiceReaper
{
c
},
nil
}
return
nil
,
fmt
.
Errorf
(
"no reaper has been implemented for %q"
,
kind
)
}
type
ReplicationControllerReaper
struct
{
client
.
Interface
pollInterval
,
timeout
time
.
Duration
}
type
PodReaper
struct
{
client
.
Interface
}
type
ServiceReaper
struct
{
client
.
Interface
}
type
objInterface
interface
{
Delete
(
name
string
)
error
Get
(
name
string
)
(
meta
.
Interface
,
error
)
}
func
(
reaper
*
ReplicationControllerReaper
)
Stop
(
namespace
,
name
string
)
(
string
,
error
)
{
rc
:=
reaper
.
ReplicationControllers
(
namespace
)
controller
,
err
:=
rc
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
controller
.
Spec
.
Replicas
=
0
// TODO: do retry on 409 errors here?
if
_
,
err
:=
rc
.
Update
(
controller
);
err
!=
nil
{
return
""
,
err
}
if
err
:=
wait
.
Poll
(
reaper
.
pollInterval
,
reaper
.
timeout
,
client
.
ControllerHasDesiredReplicas
(
reaper
,
controller
));
err
!=
nil
{
return
""
,
err
}
if
err
:=
rc
.
Delete
(
name
);
err
!=
nil
{
return
""
,
err
}
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
}
func
(
reaper
*
PodReaper
)
Stop
(
namespace
,
name
string
)
(
string
,
error
)
{
pods
:=
reaper
.
Pods
(
namespace
)
_
,
err
:=
pods
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
if
err
:=
pods
.
Delete
(
name
);
err
!=
nil
{
return
""
,
err
}
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
}
func
(
reaper
*
ServiceReaper
)
Stop
(
namespace
,
name
string
)
(
string
,
error
)
{
services
:=
reaper
.
Services
(
namespace
)
_
,
err
:=
services
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
if
err
:=
services
.
Delete
(
name
);
err
!=
nil
{
return
""
,
err
}
return
fmt
.
Sprintf
(
"%s stopped"
,
name
),
nil
}
pkg/kubectl/stop_test.go
0 → 100644
View file @
201e99e0
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
kubectl
import
(
"fmt"
"testing"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
)
func
TestReplicationControllerStop
(
t
*
testing
.
T
)
{
fake
:=
&
client
.
Fake
{
Ctrl
:
api
.
ReplicationController
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
0
,
},
},
}
reaper
:=
ReplicationControllerReaper
{
fake
,
time
.
Millisecond
,
time
.
Millisecond
}
name
:=
"foo"
s
,
err
:=
reaper
.
Stop
(
"default"
,
name
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
expected
:=
"foo stopped"
if
s
!=
expected
{
t
.
Errorf
(
"expected %s, got %s"
,
expected
,
s
)
}
if
len
(
fake
.
Actions
)
!=
4
{
t
.
Errorf
(
"unexpected actions: %v, expected 4 actions (get, update, get, delete)"
,
fake
.
Actions
)
}
for
i
,
action
:=
range
[]
string
{
"get"
,
"update"
,
"get"
,
"delete"
}
{
if
fake
.
Actions
[
i
]
.
Action
!=
action
+
"-controller"
{
t
.
Errorf
(
"unexpected action: %v, expected %s-controller"
,
fake
.
Actions
[
i
],
action
)
}
}
}
type
noSuchPod
struct
{
*
client
.
FakePods
}
func
(
c
*
noSuchPod
)
Get
(
name
string
)
(
*
api
.
Pod
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"%s does not exist"
,
name
)
}
type
noDeleteService
struct
{
*
client
.
FakeServices
}
func
(
c
*
noDeleteService
)
Delete
(
service
string
)
error
{
return
fmt
.
Errorf
(
"I'm afraid I can't do that, Dave"
)
}
type
reaperFake
struct
{
*
client
.
Fake
noSuchPod
,
noDeleteService
bool
}
func
(
c
*
reaperFake
)
Pods
(
namespace
string
)
client
.
PodInterface
{
pods
:=
&
client
.
FakePods
{
c
.
Fake
,
namespace
}
if
c
.
noSuchPod
{
return
&
noSuchPod
{
pods
}
}
return
pods
}
func
(
c
*
reaperFake
)
Services
(
namespace
string
)
client
.
ServiceInterface
{
services
:=
&
client
.
FakeServices
{
c
.
Fake
,
namespace
}
if
c
.
noDeleteService
{
return
&
noDeleteService
{
services
}
}
return
services
}
func
TestSimpleStop
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
fake
*
reaperFake
kind
string
actions
[]
string
expectError
bool
test
string
}{
{
fake
:
&
reaperFake
{
Fake
:
&
client
.
Fake
{},
},
kind
:
"Pod"
,
actions
:
[]
string
{
"get-pod"
,
"delete-pod"
},
expectError
:
false
,
test
:
"stop pod succeeds"
,
},
{
fake
:
&
reaperFake
{
Fake
:
&
client
.
Fake
{},
},
kind
:
"Service"
,
actions
:
[]
string
{
"get-service"
,
"delete-service"
},
expectError
:
false
,
test
:
"stop service succeeds"
,
},
{
fake
:
&
reaperFake
{
Fake
:
&
client
.
Fake
{},
noSuchPod
:
true
,
},
kind
:
"Pod"
,
actions
:
[]
string
{},
expectError
:
true
,
test
:
"stop pod fails, no pod"
,
},
{
fake
:
&
reaperFake
{
Fake
:
&
client
.
Fake
{},
noDeleteService
:
true
,
},
kind
:
"Service"
,
actions
:
[]
string
{
"get-service"
},
expectError
:
true
,
test
:
"stop service fails, can't delete"
,
},
}
for
_
,
test
:=
range
tests
{
fake
:=
test
.
fake
reaper
,
err
:=
ReaperFor
(
test
.
kind
,
fake
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v (%s)"
,
err
,
test
.
test
)
}
s
,
err
:=
reaper
.
Stop
(
"default"
,
"foo"
)
if
err
!=
nil
&&
!
test
.
expectError
{
t
.
Errorf
(
"unexpected error: %v (%s)"
,
err
,
test
.
test
)
}
if
err
==
nil
{
if
test
.
expectError
{
t
.
Errorf
(
"unexpected non-error: %v (%s)"
,
err
,
test
.
test
)
}
if
s
!=
"foo stopped"
{
t
.
Errorf
(
"unexpected return: %s (%s)"
,
s
,
test
.
test
)
}
}
if
len
(
test
.
actions
)
!=
len
(
fake
.
Actions
)
{
t
.
Errorf
(
"unexpected actions: %v; expected %v (%s)"
,
fake
.
Actions
,
test
.
actions
,
test
.
test
)
}
for
i
,
action
:=
range
fake
.
Actions
{
testAction
:=
test
.
actions
[
i
]
if
action
.
Action
!=
testAction
{
t
.
Errorf
(
"unexpected action: %v; expected %v (%s)"
,
action
,
testAction
,
test
.
test
)
}
}
}
}
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