mirror of https://github.com/k3s-io/k3s
commit
e27787c9d3
|
@ -639,6 +639,7 @@ _kubectl_run()
|
||||||
flags+=("--port=")
|
flags+=("--port=")
|
||||||
flags+=("--replicas=")
|
flags+=("--replicas=")
|
||||||
two_word_flags+=("-r")
|
two_word_flags+=("-r")
|
||||||
|
flags+=("--restart=")
|
||||||
flags+=("--stdin")
|
flags+=("--stdin")
|
||||||
flags+=("-i")
|
flags+=("-i")
|
||||||
flags+=("--template=")
|
flags+=("--template=")
|
||||||
|
|
|
@ -27,8 +27,8 @@ Creates a replication controller to manage the created container(s).
|
||||||
If true, only print the object that would be sent, without sending it.
|
If true, only print the object that would be sent, without sending it.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-generator\fP="run/v1"
|
\fB\-\-generator\fP=""
|
||||||
The name of the API generator to use. Default is 'run\-controller/v1'.
|
The name of the API generator to use. Default is 'run/v1' if \-\-restart=Always, otherwise the default is 'run\-pod/v1'.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-h\fP, \fB\-\-help\fP=false
|
\fB\-h\fP, \fB\-\-help\fP=false
|
||||||
|
@ -70,6 +70,10 @@ Creates a replication controller to manage the created container(s).
|
||||||
\fB\-r\fP, \fB\-\-replicas\fP=1
|
\fB\-r\fP, \fB\-\-replicas\fP=1
|
||||||
Number of replicas to create for this container. Default is 1.
|
Number of replicas to create for this container. Default is 1.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fB\-\-restart\fP="Always"
|
||||||
|
The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and \-\-replicas must be 1. Default 'Always'
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-i\fP, \fB\-\-stdin\fP=false
|
\fB\-i\fP, \fB\-\-stdin\fP=false
|
||||||
Keep stdin open on the container(s) in the pod, even if nothing is attached.
|
Keep stdin open on the container(s) in the pod, even if nothing is attached.
|
||||||
|
|
|
@ -121,7 +121,7 @@ $ kubectl annotate pods foo description-
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.183633333 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:02.005112262 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_annotate.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_annotate.md?pixel)]()
|
||||||
|
|
|
@ -103,7 +103,7 @@ $ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2
|
||||||
|
|
||||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.184001914 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:02.005424182 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_config_view.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_config_view.md?pixel)]()
|
||||||
|
|
|
@ -118,7 +118,7 @@ $ kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.182748201 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:02.004335817 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_expose.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_expose.md?pixel)]()
|
||||||
|
|
|
@ -125,7 +125,7 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.175798628 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:01.995301464 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_get.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_get.md?pixel)]()
|
||||||
|
|
|
@ -115,7 +115,7 @@ $ kubectl label pods foo bar-
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.183216488 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:02.004743482 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_label.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_label.md?pixel)]()
|
||||||
|
|
|
@ -117,7 +117,7 @@ $ kubectl rolling-update frontend --image=image:v2
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.179537741 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:01.999165947 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rolling-update.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rolling-update.md?pixel)]()
|
||||||
|
|
|
@ -66,7 +66,7 @@ $ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { .
|
||||||
```
|
```
|
||||||
--attach[=false]: If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.
|
--attach[=false]: If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.
|
||||||
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
|
--dry-run[=false]: If true, only print the object that would be sent, without sending it.
|
||||||
--generator="run/v1": The name of the API generator to use. Default is 'run-controller/v1'.
|
--generator="": The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/v1'.
|
||||||
-h, --help[=false]: help for run
|
-h, --help[=false]: help for run
|
||||||
--hostport=-1: The host port mapping for the container port. To demonstrate a single-machine container.
|
--hostport=-1: The host port mapping for the container port. To demonstrate a single-machine container.
|
||||||
--image="": The image for the container to run.
|
--image="": The image for the container to run.
|
||||||
|
@ -77,6 +77,7 @@ $ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { .
|
||||||
--overrides="": An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.
|
--overrides="": An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.
|
||||||
--port=-1: The port that this container exposes.
|
--port=-1: The port that this container exposes.
|
||||||
-r, --replicas=1: Number of replicas to create for this container. Default is 1.
|
-r, --replicas=1: Number of replicas to create for this container. Default is 1.
|
||||||
|
--restart="Always": The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and --replicas must be 1. Default 'Always'
|
||||||
-i, --stdin[=false]: Keep stdin open on the container(s) in the pod, even if nothing is attached.
|
-i, --stdin[=false]: Keep stdin open on the container(s) in the pod, even if nothing is attached.
|
||||||
-t, --template="": Template string or path to template file to use when -o=template or -o=templatefile. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]
|
-t, --template="": Template string or path to template file to use when -o=template or -o=templatefile. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]
|
||||||
--tty[=false]: Allocated a TTY for each container in the pod. Because -t is currently shorthand for --template, -t is not supported for --tty. This shorthand is deprecated and we expect to adopt -t for --tty soon.
|
--tty[=false]: Allocated a TTY for each container in the pod. Because -t is currently shorthand for --template, -t is not supported for --tty. This shorthand is deprecated and we expect to adopt -t for --tty soon.
|
||||||
|
@ -115,7 +116,7 @@ $ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { .
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-08-07 03:15:49.181215106 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-07 19:25:02.003600767 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_run.md?pixel)]()
|
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_run.md?pixel)]()
|
||||||
|
|
|
@ -61,7 +61,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmdutil.AddPrinterFlags(cmd)
|
cmdutil.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().String("generator", "run/v1", "The name of the API generator to use. Default is 'run-controller/v1'.")
|
cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/v1'.")
|
||||||
cmd.Flags().String("image", "", "The image for the container to run.")
|
cmd.Flags().String("image", "", "The image for the container to run.")
|
||||||
cmd.MarkFlagRequired("image")
|
cmd.MarkFlagRequired("image")
|
||||||
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
|
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
|
||||||
|
@ -73,6 +73,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
||||||
cmd.Flags().BoolP("stdin", "i", false, "Keep stdin open on the container(s) in the pod, even if nothing is attached.")
|
cmd.Flags().BoolP("stdin", "i", false, "Keep stdin open on the container(s) in the pod, even if nothing is attached.")
|
||||||
cmd.Flags().Bool("tty", false, "Allocated a TTY for each container in the pod. Because -t is currently shorthand for --template, -t is not supported for --tty. This shorthand is deprecated and we expect to adopt -t for --tty soon.")
|
cmd.Flags().Bool("tty", false, "Allocated a TTY for each container in the pod. Because -t is currently shorthand for --template, -t is not supported for --tty. This shorthand is deprecated and we expect to adopt -t for --tty soon.")
|
||||||
cmd.Flags().Bool("attach", false, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.")
|
cmd.Flags().Bool("attach", false, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.")
|
||||||
|
cmd.Flags().String("restart", "Always", "The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and --replicas must be 1. Default 'Always'")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +106,24 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restartPolicy, err := getRestartPolicy(cmd, interactive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if restartPolicy != api.RestartPolicyAlways && replicas != 1 {
|
||||||
|
return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --repliacs=1, found %d", restartPolicy, replicas))
|
||||||
|
}
|
||||||
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||||
|
if len(generatorName) == 0 {
|
||||||
|
if restartPolicy == api.RestartPolicyAlways {
|
||||||
|
generatorName = "run/v1"
|
||||||
|
} else {
|
||||||
|
generatorName = "run-pod/v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
generator, found := f.Generator(generatorName)
|
generator, found := f.Generator(generatorName)
|
||||||
if !found {
|
if !found {
|
||||||
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generatorName))
|
||||||
}
|
}
|
||||||
names := generator.ParamNames()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
|
@ -119,14 +134,20 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
controller, err := generator.Generate(params)
|
obj, err := generator.Generate(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
inline := cmdutil.GetFlagString(cmd, "overrides")
|
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||||
if len(inline) > 0 {
|
if len(inline) > 0 {
|
||||||
controller, err = cmdutil.Merge(controller, inline, "ReplicationController")
|
var objType string
|
||||||
|
if restartPolicy == api.RestartPolicyAlways {
|
||||||
|
objType = "ReplicationController"
|
||||||
|
} else {
|
||||||
|
objType = "Pod"
|
||||||
|
}
|
||||||
|
obj, err = cmdutil.Merge(obj, inline, objType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -134,7 +155,11 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||||
|
|
||||||
// TODO: extract this flag to a central location, when such a location exists.
|
// TODO: extract this flag to a central location, when such a location exists.
|
||||||
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
||||||
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
if restartPolicy == api.RestartPolicyAlways {
|
||||||
|
obj, err = client.ReplicationControllers(namespace).Create(obj.(*api.ReplicationController))
|
||||||
|
} else {
|
||||||
|
obj, err = client.Pods(namespace).Create(obj.(*api.Pod))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -168,9 +193,13 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.Client = client
|
opts.Client = client
|
||||||
return handleAttach(client, controller.(*api.ReplicationController), opts)
|
if restartPolicy == api.RestartPolicyAlways {
|
||||||
|
return handleAttachReplicationController(client, obj.(*api.ReplicationController), opts)
|
||||||
|
} else {
|
||||||
|
return handleAttachPod(client, obj.(*api.Pod), opts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return f.PrintObject(cmd, controller, cmdOut)
|
return f.PrintObject(cmd, obj, cmdOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForPodRunning(c *client.Client, pod *api.Pod, out io.Writer) error {
|
func waitForPodRunning(c *client.Client, pod *api.Pod, out io.Writer) error {
|
||||||
|
@ -197,7 +226,7 @@ func waitForPodRunning(c *client.Client, pod *api.Pod, out io.Writer) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAttach(c *client.Client, controller *api.ReplicationController, opts *AttachOptions) error {
|
func handleAttachReplicationController(c *client.Client, controller *api.ReplicationController, opts *AttachOptions) error {
|
||||||
var pods *api.PodList
|
var pods *api.PodList
|
||||||
for pods == nil || len(pods.Items) == 0 {
|
for pods == nil || len(pods.Items) == 0 {
|
||||||
var err error
|
var err error
|
||||||
|
@ -210,7 +239,10 @@ func handleAttach(c *client.Client, controller *api.ReplicationController, opts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pod := &pods.Items[0]
|
pod := &pods.Items[0]
|
||||||
|
return handleAttachPod(c, pod, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleAttachPod(c *client.Client, pod *api.Pod, opts *AttachOptions) error {
|
||||||
if err := waitForPodRunning(c, pod, opts.Out); err != nil {
|
if err := waitForPodRunning(c, pod, opts.Out); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -219,3 +251,24 @@ func handleAttach(c *client.Client, controller *api.ReplicationController, opts
|
||||||
opts.Namespace = pod.Namespace
|
opts.Namespace = pod.Namespace
|
||||||
return opts.Run()
|
return opts.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRestartPolicy(cmd *cobra.Command, interactive bool) (api.RestartPolicy, error) {
|
||||||
|
restart := cmdutil.GetFlagString(cmd, "restart")
|
||||||
|
if len(restart) == 0 {
|
||||||
|
if interactive {
|
||||||
|
return api.RestartPolicyOnFailure, nil
|
||||||
|
} else {
|
||||||
|
return api.RestartPolicyAlways, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch api.RestartPolicy(restart) {
|
||||||
|
case api.RestartPolicyAlways:
|
||||||
|
return api.RestartPolicyAlways, nil
|
||||||
|
case api.RestartPolicyOnFailure:
|
||||||
|
return api.RestartPolicyOnFailure, nil
|
||||||
|
case api.RestartPolicyNever:
|
||||||
|
return api.RestartPolicyNever, nil
|
||||||
|
default:
|
||||||
|
return "", cmdutil.UsageError(cmd, fmt.Sprintf("invalid restart policy: %s", restart))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 The Kubernetes Authors 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 (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetRestartPolicy(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
interactive bool
|
||||||
|
expected api.RestartPolicy
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
expected: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
interactive: true,
|
||||||
|
expected: api.RestartPolicyOnFailure,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: string(api.RestartPolicyAlways),
|
||||||
|
interactive: true,
|
||||||
|
expected: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: string(api.RestartPolicyNever),
|
||||||
|
interactive: true,
|
||||||
|
expected: api.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: string(api.RestartPolicyAlways),
|
||||||
|
expected: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: string(api.RestartPolicyNever),
|
||||||
|
expected: api.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "foo",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
cmd := &cobra.Command{}
|
||||||
|
cmd.Flags().String("restart", "", "dummy restart flag")
|
||||||
|
cmd.Flags().Lookup("restart").Value.Set(test.input)
|
||||||
|
policy, err := getRestartPolicy(cmd, test.interactive)
|
||||||
|
if test.expectErr && err == nil {
|
||||||
|
t.Error("unexpected non-error")
|
||||||
|
}
|
||||||
|
if !test.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if !test.expectErr && policy != test.expected {
|
||||||
|
t.Errorf("expected: %s, saw: %s (%s:%v)", test.expected, policy, test.input, test.interactive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,6 +97,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||||
|
|
||||||
generators := map[string]kubectl.Generator{
|
generators := map[string]kubectl.Generator{
|
||||||
"run/v1": kubectl.BasicReplicationController{},
|
"run/v1": kubectl.BasicReplicationController{},
|
||||||
|
"run-pod/v1": kubectl.BasicPod{},
|
||||||
"service/v1": kubectl.ServiceGeneratorV1{},
|
"service/v1": kubectl.ServiceGeneratorV1{},
|
||||||
"service/v2": kubectl.ServiceGeneratorV2{},
|
"service/v2": kubectl.ServiceGeneratorV2{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,30 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makePodSpec(params map[string]string, name string) (*api.PodSpec, error) {
|
||||||
|
stdin, err := GetBool(params, "stdin", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tty, err := GetBool(params, "tty", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spec := api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: name,
|
||||||
|
Image: params["image"],
|
||||||
|
Stdin: stdin,
|
||||||
|
TTY: tty,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (BasicReplicationController) Generate(params map[string]string) (runtime.Object, error) {
|
func (BasicReplicationController) Generate(params map[string]string) (runtime.Object, error) {
|
||||||
name, found := params["name"]
|
name, found := params["name"]
|
||||||
if !found || len(name) == 0 {
|
if !found || len(name) == 0 {
|
||||||
|
@ -66,16 +90,11 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
stdin, err := GetBool(params, "stdin", false)
|
|
||||||
|
podSpec, err := makePodSpec(params, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tty, err := GetBool(params, "tty", false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
controller := api.ReplicationController{
|
controller := api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -88,49 +107,119 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: *podSpec,
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: name,
|
|
||||||
Image: params["image"],
|
|
||||||
Stdin: stdin,
|
|
||||||
TTY: tty,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if err := updatePodPorts(params, &controller.Spec.Template.Spec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &controller, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePodPorts(params map[string]string, podSpec *api.PodSpec) (err error) {
|
||||||
port := -1
|
port := -1
|
||||||
hostPort := -1
|
hostPort := -1
|
||||||
if len(params["port"]) > 0 {
|
if len(params["port"]) > 0 {
|
||||||
port, err = strconv.Atoi(params["port"])
|
port, err = strconv.Atoi(params["port"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(params["hostport"]) > 0 {
|
if len(params["hostport"]) > 0 {
|
||||||
hostPort, err = strconv.Atoi(params["hostport"])
|
hostPort, err = strconv.Atoi(params["hostport"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if hostPort > 0 && port < 0 {
|
if hostPort > 0 && port < 0 {
|
||||||
return nil, fmt.Errorf("--hostport requires --port to be specified")
|
return fmt.Errorf("--hostport requires --port to be specified")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't include the port if it was not specified.
|
// Don't include the port if it was not specified.
|
||||||
if port > 0 {
|
if port > 0 {
|
||||||
controller.Spec.Template.Spec.Containers[0].Ports = []api.ContainerPort{
|
podSpec.Containers[0].Ports = []api.ContainerPort{
|
||||||
{
|
{
|
||||||
ContainerPort: port,
|
ContainerPort: port,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if hostPort > 0 {
|
if hostPort > 0 {
|
||||||
controller.Spec.Template.Spec.Containers[0].Ports[0].HostPort = hostPort
|
podSpec.Containers[0].Ports[0].HostPort = hostPort
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &controller, nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicPod struct{}
|
||||||
|
|
||||||
|
func (BasicPod) ParamNames() []GeneratorParam {
|
||||||
|
return []GeneratorParam{
|
||||||
|
{"labels", false},
|
||||||
|
{"default-name", false},
|
||||||
|
{"name", true},
|
||||||
|
{"image", true},
|
||||||
|
{"port", false},
|
||||||
|
{"hostport", false},
|
||||||
|
{"stdin", false},
|
||||||
|
{"tty", false},
|
||||||
|
{"restart", false},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (BasicPod) Generate(params map[string]string) (runtime.Object, error) {
|
||||||
|
name, found := params["name"]
|
||||||
|
if !found || len(name) == 0 {
|
||||||
|
name, found = params["default-name"]
|
||||||
|
if !found || len(name) == 0 {
|
||||||
|
return nil, fmt.Errorf("'name' is a required parameter.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: extract this flag to a central location.
|
||||||
|
labelString, found := params["labels"]
|
||||||
|
var labels map[string]string
|
||||||
|
var err error
|
||||||
|
if found && len(labelString) > 0 {
|
||||||
|
labels, err = ParseLabels(labelString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stdin, err := GetBool(params, "stdin", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tty, err := GetBool(params, "tty", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
restartPolicy := api.RestartPolicy(params["restart"])
|
||||||
|
if len(restartPolicy) == 0 {
|
||||||
|
restartPolicy = api.RestartPolicyAlways
|
||||||
|
}
|
||||||
|
pod := api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Labels: labels,
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: name,
|
||||||
|
Image: params["image"],
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
|
Stdin: stdin,
|
||||||
|
TTY: tty,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
RestartPolicy: restartPolicy,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := updatePodPorts(params, &pod.Spec); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pod, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,3 +190,140 @@ func TestGenerate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGeneratePod(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
params map[string]string
|
||||||
|
expected *api.Pod
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
params: map[string]string{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"port": "-1",
|
||||||
|
},
|
||||||
|
expected: &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]string{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"port": "80",
|
||||||
|
},
|
||||||
|
expected: &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
|
Ports: []api.ContainerPort{
|
||||||
|
{
|
||||||
|
ContainerPort: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]string{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"port": "80",
|
||||||
|
"hostport": "80",
|
||||||
|
},
|
||||||
|
expected: &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
|
Ports: []api.ContainerPort{
|
||||||
|
{
|
||||||
|
ContainerPort: 80,
|
||||||
|
HostPort: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]string{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"hostport": "80",
|
||||||
|
},
|
||||||
|
expected: nil,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]string{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"replicas": "1",
|
||||||
|
"labels": "foo=bar,baz=blah",
|
||||||
|
},
|
||||||
|
expected: &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"foo": "bar", "baz": "blah"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
ImagePullPolicy: api.PullIfNotPresent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
generator := BasicPod{}
|
||||||
|
for _, test := range tests {
|
||||||
|
obj, err := generator.Generate(test.params)
|
||||||
|
if !test.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if test.expectErr && err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(obj.(*api.Pod), test.expected) {
|
||||||
|
t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Pod))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -485,7 +485,7 @@ var _ = Describe("Kubectl client", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Kubectl run", func() {
|
Describe("Kubectl run rc", func() {
|
||||||
var nsFlag string
|
var nsFlag string
|
||||||
var rcName string
|
var rcName string
|
||||||
|
|
||||||
|
@ -528,6 +528,59 @@ var _ = Describe("Kubectl client", func() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("Kubectl run pod", func() {
|
||||||
|
var nsFlag string
|
||||||
|
var podName string
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
nsFlag = fmt.Sprintf("--namespace=%v", ns)
|
||||||
|
podName = "e2e-test-nginx-pod"
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
runKubectl("stop", "pods", podName, nsFlag)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should create a pod from an image when restart is OnFailure", func() {
|
||||||
|
image := "nginx"
|
||||||
|
|
||||||
|
By("running the image " + image)
|
||||||
|
runKubectl("run", podName, "--restart=OnFailure", "--image="+image, nsFlag)
|
||||||
|
By("verifying the pod " + podName + " was created")
|
||||||
|
pod, err := c.Pods(ns).Get(podName)
|
||||||
|
if err != nil {
|
||||||
|
Failf("Failed getting pod %s: %v", podName, err)
|
||||||
|
}
|
||||||
|
containers := pod.Spec.Containers
|
||||||
|
if containers == nil || len(containers) != 1 || containers[0].Image != image {
|
||||||
|
Failf("Failed creating pod %s for 1 pod with expected image %s", podName, image)
|
||||||
|
}
|
||||||
|
if pod.Spec.RestartPolicy != api.RestartPolicyOnFailure {
|
||||||
|
Failf("Failed creating a pod with correct restart policy for --restart=OnFailure")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should create a pod from an image when restart is Never", func() {
|
||||||
|
image := "nginx"
|
||||||
|
|
||||||
|
By("running the image " + image)
|
||||||
|
runKubectl("run", podName, "--restart=Never", "--image="+image, nsFlag)
|
||||||
|
By("verifying the pod " + podName + " was created")
|
||||||
|
pod, err := c.Pods(ns).Get(podName)
|
||||||
|
if err != nil {
|
||||||
|
Failf("Failed getting pod %s: %v", podName, err)
|
||||||
|
}
|
||||||
|
containers := pod.Spec.Containers
|
||||||
|
if containers == nil || len(containers) != 1 || containers[0].Image != image {
|
||||||
|
Failf("Failed creating pod %s for 1 pod with expected image %s", podName, image)
|
||||||
|
}
|
||||||
|
if pod.Spec.RestartPolicy != api.RestartPolicyNever {
|
||||||
|
Failf("Failed creating a pod with correct restart policy for --restart=OnFailure")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
Describe("Proxy server", func() {
|
Describe("Proxy server", func() {
|
||||||
// TODO: test proxy options (static, prefix, etc)
|
// TODO: test proxy options (static, prefix, etc)
|
||||||
It("should support proxy with --port 0", func() {
|
It("should support proxy with --port 0", func() {
|
||||||
|
|
Loading…
Reference in New Issue