diff --git a/contrib/completions/bash/kubectl b/contrib/completions/bash/kubectl index e3a5cf7142b..6f1b405d85a 100644 --- a/contrib/completions/bash/kubectl +++ b/contrib/completions/bash/kubectl @@ -542,6 +542,7 @@ _kubectl_run-container() flags+=("--generator=") flags+=("--help") flags+=("-h") + flags+=("--hostport=") flags+=("--image=") flags+=("--labels=") two_word_flags+=("-l") diff --git a/docs/kubectl.md b/docs/kubectl.md index 0c0c2f56a85..5ffdc680699 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -66,4 +66,4 @@ kubectl * [kubectl update](kubectl_update.md) - Update a resource by filename or stdin. * [kubectl version](kubectl_version.md) - Print the client and server version information. -###### Auto generated by spf13/cobra at 2015-04-30 16:43:53.288271038 +0000 UTC +###### Auto generated by spf13/cobra at 2015-05-01 20:16:42.546735249 +0000 UTC diff --git a/docs/kubectl_run-container.md b/docs/kubectl_run-container.md index 2f3c783edd0..7188ca5cc31 100644 --- a/docs/kubectl_run-container.md +++ b/docs/kubectl_run-container.md @@ -34,6 +34,7 @@ $ kubectl run-container nginx --image=nginx --overrides='{ "apiVersion": "v1beta --dry-run=false: If true, only print the object that would be sent, without sending it. --generator="run-container/v1": The name of the API generator to use. Default is 'run-container-controller/v1'. -h, --help=false: help for run-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. -l, --labels="": Labels to apply to the pod(s) created by this call to run-container. --no-headers=false: When using the default output, don't print headers. @@ -78,4 +79,4 @@ $ kubectl run-container nginx --image=nginx --overrides='{ "apiVersion": "v1beta ### SEE ALSO * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager -###### Auto generated by spf13/cobra at 2015-04-29 15:25:11.0330734 +0000 UTC +###### Auto generated by spf13/cobra at 2015-04-29 23:46:39.503475144 +0000 UTC diff --git a/docs/man/man1/kubectl-run-container.1 b/docs/man/man1/kubectl-run-container.1 index ba51080f909..e59ae88e6fe 100644 --- a/docs/man/man1/kubectl-run-container.1 +++ b/docs/man/man1/kubectl-run-container.1 @@ -30,6 +30,10 @@ Creates a replication controller to manage the created container(s). \fB\-h\fP, \fB\-\-help\fP=false help for run\-container +.PP +\fB\-\-hostport\fP=\-1 + The host port mapping for the container port. To demonstrate a single\-machine container. + .PP \fB\-\-image\fP="" The image for the container to run. diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index b8d428cd2cf..78bc6e12a4c 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -61,6 +61,7 @@ func NewCmdRunContainer(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.") cmd.Flags().String("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.") cmd.Flags().Int("port", -1, "The port that this container exposes.") + cmd.Flags().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.") cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s) created by this call to run-container.") return cmd } diff --git a/pkg/kubectl/run.go b/pkg/kubectl/run.go index 18d0d074bca..1fe717781a0 100644 --- a/pkg/kubectl/run.go +++ b/pkg/kubectl/run.go @@ -17,6 +17,7 @@ limitations under the License. package kubectl import ( + "fmt" "strconv" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -32,6 +33,7 @@ func (BasicReplicationController) ParamNames() []GeneratorParam { {"replicas", true}, {"image", true}, {"port", false}, + {"hostport", false}, } } @@ -78,19 +80,34 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob }, } + port := -1 + hostPort := -1 if len(params["port"]) > 0 { - port, err := strconv.Atoi(params["port"]) + port, err = strconv.Atoi(params["port"]) if err != nil { return nil, err } + } - // Don't include the port if it was not specified. - if port > 0 { - controller.Spec.Template.Spec.Containers[0].Ports = []api.ContainerPort{ - { - ContainerPort: port, - }, - } + if len(params["hostport"]) > 0 { + hostPort, err = strconv.Atoi(params["hostport"]) + if err != nil { + return nil, err + } + if hostPort > 0 && port < 0 { + return nil, fmt.Errorf("--hostport requires --port to be specified") + } + } + + // Don't include the port if it was not specified. + if port > 0 { + controller.Spec.Template.Spec.Containers[0].Ports = []api.ContainerPort{ + { + ContainerPort: port, + }, + } + if hostPort > 0 { + controller.Spec.Template.Spec.Containers[0].Ports[0].HostPort = hostPort } } return &controller, nil diff --git a/pkg/kubectl/run_test.go b/pkg/kubectl/run_test.go index 2a4b3027bc4..763c6d5a084 100644 --- a/pkg/kubectl/run_test.go +++ b/pkg/kubectl/run_test.go @@ -96,6 +96,54 @@ func TestGenerate(t *testing.T) { }, }, }, + { + params: map[string]string{ + "name": "foo", + "image": "someimage", + "replicas": "1", + "port": "80", + "hostport": "80", + }, + expected: &api.ReplicationController{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"run-container": "foo"}, + }, + Spec: api.ReplicationControllerSpec{ + Replicas: 1, + Selector: map[string]string{"run-container": "foo"}, + Template: &api.PodTemplateSpec{ + ObjectMeta: api.ObjectMeta{ + Labels: map[string]string{"run-container": "foo"}, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "foo", + Image: "someimage", + Ports: []api.ContainerPort{ + { + ContainerPort: 80, + HostPort: 80, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + params: map[string]string{ + "name": "foo", + "image": "someimage", + "replicas": "1", + "hostport": "80", + }, + expected: nil, + expectErr: true, + }, { params: map[string]string{ "name": "foo", @@ -134,6 +182,9 @@ func TestGenerate(t *testing.T) { if !test.expectErr && err != nil { t.Errorf("unexpected error: %v", err) } + if test.expectErr && err != nil { + continue + } if !reflect.DeepEqual(obj.(*api.ReplicationController).Spec.Template, test.expected.Spec.Template) { t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected.Spec.Template, obj.(*api.ReplicationController).Spec.Template) }