Add optional arguments to kubectl run ...
This commit is contained in:
parent
a6148e79c3
commit
586931fe16
@ -630,6 +630,7 @@ _kubectl_run()
|
|||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
flags+=("--attach")
|
flags+=("--attach")
|
||||||
|
flags+=("--command")
|
||||||
flags+=("--dry-run")
|
flags+=("--dry-run")
|
||||||
flags+=("--generator=")
|
flags+=("--generator=")
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
|
@ -22,6 +22,10 @@ Creates a replication controller to manage the created container(s).
|
|||||||
\fB\-\-attach\fP=false
|
\fB\-\-attach\fP=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.
|
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.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fB\-\-command\fP=false
|
||||||
|
If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-dry\-run\fP=false
|
\fB\-\-dry\-run\fP=false
|
||||||
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.
|
||||||
@ -207,6 +211,15 @@ $ kubectl run nginx \-\-image=nginx \-\-dry\-run
|
|||||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||||
$ kubectl run nginx \-\-image=nginx \-\-overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
$ kubectl run nginx \-\-image=nginx \-\-overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||||
|
|
||||||
|
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||||
|
$ kubectl run \-i \-tty nginx \-\-image=nginx \-\-restart=Never
|
||||||
|
|
||||||
|
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||||
|
$ kubectl run nginx \-\-image=nginx \-\- <arg1> <arg2> ... <argN>
|
||||||
|
|
||||||
|
# Start the nginx container using a different command and custom arguments
|
||||||
|
$ kubectl run nginx \-\-image=nginx \-\-command \-\- <cmd> <arg1> ... <argN>
|
||||||
|
|
||||||
.fi
|
.fi
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
@ -59,12 +59,22 @@ $ kubectl run nginx --image=nginx --dry-run
|
|||||||
|
|
||||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||||
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||||
|
|
||||||
|
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||||
|
$ kubectl run -i -tty nginx --image=nginx --restart=Never
|
||||||
|
|
||||||
|
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||||
|
$ kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN>
|
||||||
|
|
||||||
|
# Start the nginx container using a different command and custom arguments
|
||||||
|
$ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
--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.
|
||||||
|
--command[=false]: If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.
|
||||||
--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="": The name of the API generator to use. Default is 'run/v1' if --restart=Always, otherwise the default is 'run-pod/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
|
||||||
@ -117,7 +127,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-12 23:41:01.307766241 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-08-13 16:41:44.465440991 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[]()
|
[]()
|
||||||
|
@ -127,8 +127,8 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
|
|||||||
names := generator.ParamNames()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
params["default-name"] = info.Name
|
params["default-name"] = info.Name
|
||||||
if s, found := params["selector"]; !found || len(s) == 0 || cmdutil.GetFlagInt(cmd, "port") < 1 {
|
if s, found := params["selector"]; !found || kubectl.IsZero(s) || cmdutil.GetFlagInt(cmd, "port") < 1 {
|
||||||
if len(s) == 0 {
|
if kubectl.IsZero(s) {
|
||||||
s, err := f.PodSelectorForObject(inputObject)
|
s, err := f.PodSelectorForObject(inputObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find selectors via --selector flag or introspection: %s", err))
|
return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find selectors via --selector flag or introspection: %s", err))
|
||||||
@ -160,7 +160,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
|
|||||||
if cmdutil.GetFlagBool(cmd, "create-external-load-balancer") {
|
if cmdutil.GetFlagBool(cmd, "create-external-load-balancer") {
|
||||||
params["create-external-load-balancer"] = "true"
|
params["create-external-load-balancer"] = "true"
|
||||||
}
|
}
|
||||||
if len(params["labels"]) == 0 {
|
if kubectl.IsZero(params["labels"]) {
|
||||||
labels, err := f.LabelsForObject(inputObject)
|
labels, err := f.LabelsForObject(inputObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,16 +30,50 @@ import (
|
|||||||
|
|
||||||
func TestRunExposeService(t *testing.T) {
|
func TestRunExposeService(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
ns string
|
ns string
|
||||||
calls map[string]string
|
calls map[string]string
|
||||||
input runtime.Object
|
input runtime.Object
|
||||||
flags map[string]string
|
flags map[string]string
|
||||||
output runtime.Object
|
output runtime.Object
|
||||||
expected string
|
expected string
|
||||||
status int
|
status int
|
||||||
|
podSelector string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
name: "expose-service-from-service-no-selector",
|
||||||
|
args: []string{"service", "baz"},
|
||||||
|
ns: "test",
|
||||||
|
calls: map[string]string{
|
||||||
|
"GET": "/namespaces/test/services/baz",
|
||||||
|
"POST": "/namespaces/test/services",
|
||||||
|
},
|
||||||
|
input: &api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
|
||||||
|
TypeMeta: api.TypeMeta{Kind: "Service", APIVersion: "v1"},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Selector: map[string]string{"app": "go"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
podSelector: "app=go",
|
||||||
|
flags: map[string]string{"protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test"},
|
||||||
|
output: &api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "12", Labels: map[string]string{"svc": "test"}},
|
||||||
|
TypeMeta: api.TypeMeta{Kind: "Service", APIVersion: "v1"},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Ports: []api.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "default",
|
||||||
|
Protocol: api.Protocol("UDP"),
|
||||||
|
Port: 14,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"app": "go"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "expose-service-from-service",
|
name: "expose-service-from-service",
|
||||||
args: []string{"service", "baz"},
|
args: []string{"service", "baz"},
|
||||||
@ -194,6 +228,8 @@ func TestRunExposeService(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.Namespace = test.ns
|
tf.Namespace = test.ns
|
||||||
|
f.PodSelectorForObject = func(obj runtime.Object) (string, error) { return test.podSelector, nil }
|
||||||
|
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := NewCmdExposeService(f, buf)
|
cmd := NewCmdExposeService(f, buf)
|
||||||
|
@ -44,7 +44,16 @@ $ kubectl run nginx --image=nginx --replicas=5
|
|||||||
$ kubectl run nginx --image=nginx --dry-run
|
$ kubectl run nginx --image=nginx --dry-run
|
||||||
|
|
||||||
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
# Start a single instance of nginx, but overload the spec of the replication controller with a partial set of values parsed from JSON.
|
||||||
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'`
|
$ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
|
||||||
|
|
||||||
|
# Start a single instance of nginx and keep it in the foreground, don't restart it if it exits.
|
||||||
|
$ kubectl run -i -tty nginx --image=nginx --restart=Never
|
||||||
|
|
||||||
|
# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.
|
||||||
|
$ kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN>
|
||||||
|
|
||||||
|
# Start the nginx container using a different command and custom arguments
|
||||||
|
$ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>`
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
|
func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
|
||||||
@ -74,6 +83,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
|
|||||||
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'")
|
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'")
|
||||||
|
cmd.Flags().Bool("command", false, "If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +92,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
|||||||
printDeprecationWarning("run", "run-container")
|
printDeprecationWarning("run", "run-container")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) == 0 {
|
||||||
return cmdutil.UsageError(cmd, "NAME is required for run")
|
return cmdutil.UsageError(cmd, "NAME is required for run")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +138,9 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob
|
|||||||
names := generator.ParamNames()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
params["name"] = args[0]
|
params["name"] = args[0]
|
||||||
|
if len(args) > 1 {
|
||||||
|
params["args"] = args[1:]
|
||||||
|
}
|
||||||
err = kubectl.ValidateParams(names, params)
|
err = kubectl.ValidateParams(names, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -18,6 +18,7 @@ package kubectl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -35,17 +36,24 @@ type GeneratorParam struct {
|
|||||||
// Generator is an interface for things that can generate API objects from input parameters.
|
// Generator is an interface for things that can generate API objects from input parameters.
|
||||||
type Generator interface {
|
type Generator interface {
|
||||||
// Generate creates an API object given a set of parameters
|
// Generate creates an API object given a set of parameters
|
||||||
Generate(params map[string]string) (runtime.Object, error)
|
Generate(params map[string]interface{}) (runtime.Object, error)
|
||||||
// ParamNames returns the list of parameters that this generator uses
|
// ParamNames returns the list of parameters that this generator uses
|
||||||
ParamNames() []GeneratorParam
|
ParamNames() []GeneratorParam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsZero(i interface{}) bool {
|
||||||
|
if i == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface())
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateParams ensures that all required params are present in the params map
|
// ValidateParams ensures that all required params are present in the params map
|
||||||
func ValidateParams(paramSpec []GeneratorParam, params map[string]string) error {
|
func ValidateParams(paramSpec []GeneratorParam, params map[string]interface{}) error {
|
||||||
for ix := range paramSpec {
|
for ix := range paramSpec {
|
||||||
if paramSpec[ix].Required {
|
if paramSpec[ix].Required {
|
||||||
value, found := params[paramSpec[ix].Name]
|
value, found := params[paramSpec[ix].Name]
|
||||||
if !found || len(value) == 0 {
|
if !found || IsZero(value) {
|
||||||
return fmt.Errorf("Parameter: %s is required", paramSpec[ix].Name)
|
return fmt.Errorf("Parameter: %s is required", paramSpec[ix].Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,8 +62,8 @@ func ValidateParams(paramSpec []GeneratorParam, params map[string]string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MakeParams is a utility that creates generator parameters from a command line
|
// MakeParams is a utility that creates generator parameters from a command line
|
||||||
func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]string {
|
func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]interface{} {
|
||||||
result := map[string]string{}
|
result := map[string]interface{}{}
|
||||||
for ix := range params {
|
for ix := range params {
|
||||||
f := cmd.Flags().Lookup(params[ix].Name)
|
f := cmd.Flags().Lookup(params[ix].Name)
|
||||||
if f != nil {
|
if f != nil {
|
||||||
@ -74,7 +82,11 @@ func MakeLabels(labels map[string]string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ParseLabels turns a string representation of a label set into a map[string]string
|
// ParseLabels turns a string representation of a label set into a map[string]string
|
||||||
func ParseLabels(labelString string) (map[string]string, error) {
|
func ParseLabels(labelSpec interface{}) (map[string]string, error) {
|
||||||
|
labelString, isString := labelSpec.(string)
|
||||||
|
if !isString {
|
||||||
|
return nil, fmt.Errorf("expected string, found %v", labelSpec)
|
||||||
|
}
|
||||||
if len(labelString) == 0 {
|
if len(labelString) == 0 {
|
||||||
return nil, fmt.Errorf("no label spec passed")
|
return nil, fmt.Errorf("no label spec passed")
|
||||||
}
|
}
|
||||||
|
@ -23,29 +23,55 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TestStruct struct {
|
||||||
|
val int
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsZero(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
val interface{}
|
||||||
|
expectZero bool
|
||||||
|
}{
|
||||||
|
{"", true},
|
||||||
|
{nil, true},
|
||||||
|
{0, true},
|
||||||
|
{TestStruct{}, true},
|
||||||
|
{"foo", false},
|
||||||
|
{1, false},
|
||||||
|
{TestStruct{val: 2}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
output := IsZero(test.val)
|
||||||
|
if output != test.expectZero {
|
||||||
|
t.Errorf("expected: %v, saw %v", test.expectZero, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateParams(t *testing.T) {
|
func TestValidateParams(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
paramSpec []GeneratorParam
|
paramSpec []GeneratorParam
|
||||||
params map[string]string
|
params map[string]interface{}
|
||||||
valid bool
|
valid bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
paramSpec: []GeneratorParam{},
|
paramSpec: []GeneratorParam{},
|
||||||
params: map[string]string{},
|
params: map[string]interface{}{},
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
paramSpec: []GeneratorParam{
|
paramSpec: []GeneratorParam{
|
||||||
{Name: "foo"},
|
{Name: "foo"},
|
||||||
},
|
},
|
||||||
params: map[string]string{},
|
params: map[string]interface{}{},
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
paramSpec: []GeneratorParam{
|
paramSpec: []GeneratorParam{
|
||||||
{Name: "foo", Required: true},
|
{Name: "foo", Required: true},
|
||||||
},
|
},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
valid: true,
|
valid: true,
|
||||||
@ -54,7 +80,7 @@ func TestValidateParams(t *testing.T) {
|
|||||||
paramSpec: []GeneratorParam{
|
paramSpec: []GeneratorParam{
|
||||||
{Name: "foo", Required: true},
|
{Name: "foo", Required: true},
|
||||||
},
|
},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"baz": "blah",
|
"baz": "blah",
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
@ -65,7 +91,7 @@ func TestValidateParams(t *testing.T) {
|
|||||||
{Name: "foo", Required: true},
|
{Name: "foo", Required: true},
|
||||||
{Name: "baz", Required: true},
|
{Name: "baz", Required: true},
|
||||||
},
|
},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"baz": "blah",
|
"baz": "blah",
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
@ -76,7 +102,7 @@ func TestValidateParams(t *testing.T) {
|
|||||||
{Name: "foo", Required: true},
|
{Name: "foo", Required: true},
|
||||||
{Name: "baz", Required: true},
|
{Name: "baz", Required: true},
|
||||||
},
|
},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
valid: false,
|
valid: false,
|
||||||
@ -103,7 +129,7 @@ func TestMakeParams(t *testing.T) {
|
|||||||
{Name: "foo", Required: true},
|
{Name: "foo", Required: true},
|
||||||
{Name: "baz", Required: true},
|
{Name: "baz", Required: true},
|
||||||
}
|
}
|
||||||
expected := map[string]string{
|
expected := map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
"baz": "blah",
|
"baz": "blah",
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
|
|||||||
{"hostport", false},
|
{"hostport", false},
|
||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
{"tty", false},
|
{"tty", false},
|
||||||
|
{"command", false},
|
||||||
|
{"args", false},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +66,25 @@ func makePodSpec(params map[string]string, name string) (*api.PodSpec, error) {
|
|||||||
return &spec, nil
|
return &spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (BasicReplicationController) Generate(params map[string]string) (runtime.Object, error) {
|
func (BasicReplicationController) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||||
|
args := []string{}
|
||||||
|
val, found := genericParams["args"]
|
||||||
|
if found {
|
||||||
|
var isArray bool
|
||||||
|
args, isArray = val.([]string)
|
||||||
|
if !isArray {
|
||||||
|
return nil, fmt.Errorf("expected []string, found: %v", val)
|
||||||
|
}
|
||||||
|
delete(genericParams, "args")
|
||||||
|
}
|
||||||
|
params := map[string]string{}
|
||||||
|
for key, value := range genericParams {
|
||||||
|
strVal, isString := value.(string)
|
||||||
|
if !isString {
|
||||||
|
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
|
||||||
|
}
|
||||||
|
params[key] = strVal
|
||||||
|
}
|
||||||
name, found := params["name"]
|
name, found := params["name"]
|
||||||
if !found || len(name) == 0 {
|
if !found || len(name) == 0 {
|
||||||
name, found = params["default-name"]
|
name, found = params["default-name"]
|
||||||
@ -95,6 +115,18 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(args) > 0 {
|
||||||
|
command, err := GetBool(params, "command", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if command {
|
||||||
|
podSpec.Containers[0].Command = args
|
||||||
|
} else {
|
||||||
|
podSpec.Containers[0].Args = args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
controller := api.ReplicationController{
|
controller := api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -164,10 +196,30 @@ func (BasicPod) ParamNames() []GeneratorParam {
|
|||||||
{"stdin", false},
|
{"stdin", false},
|
||||||
{"tty", false},
|
{"tty", false},
|
||||||
{"restart", false},
|
{"restart", false},
|
||||||
|
{"command", false},
|
||||||
|
{"args", false},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (BasicPod) Generate(params map[string]string) (runtime.Object, error) {
|
func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||||
|
args := []string{}
|
||||||
|
val, found := genericParams["args"]
|
||||||
|
if found {
|
||||||
|
var isArray bool
|
||||||
|
args, isArray = val.([]string)
|
||||||
|
if !isArray {
|
||||||
|
return nil, fmt.Errorf("expected []string, found: %v", val)
|
||||||
|
}
|
||||||
|
delete(genericParams, "args")
|
||||||
|
}
|
||||||
|
params := map[string]string{}
|
||||||
|
for key, value := range genericParams {
|
||||||
|
strVal, isString := value.(string)
|
||||||
|
if !isString {
|
||||||
|
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
|
||||||
|
}
|
||||||
|
params[key] = strVal
|
||||||
|
}
|
||||||
name, found := params["name"]
|
name, found := params["name"]
|
||||||
if !found || len(name) == 0 {
|
if !found || len(name) == 0 {
|
||||||
name, found = params["default-name"]
|
name, found = params["default-name"]
|
||||||
@ -218,6 +270,17 @@ func (BasicPod) Generate(params map[string]string) (runtime.Object, error) {
|
|||||||
RestartPolicy: restartPolicy,
|
RestartPolicy: restartPolicy,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if len(args) > 0 {
|
||||||
|
command, err := GetBool(params, "command", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if command {
|
||||||
|
pod.Spec.Containers[0].Command = args
|
||||||
|
} else {
|
||||||
|
pod.Spec.Containers[0].Args = args
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := updatePodPorts(params, &pod.Spec); err != nil {
|
if err := updatePodPorts(params, &pod.Spec); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@ import (
|
|||||||
|
|
||||||
func TestGenerate(t *testing.T) {
|
func TestGenerate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
params map[string]string
|
params map[string]interface{}
|
||||||
expected *api.ReplicationController
|
expected *api.ReplicationController
|
||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
@ -61,7 +61,74 @@ func TestGenerate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"replicas": "1",
|
||||||
|
"port": "-1",
|
||||||
|
"args": []string{"bar", "baz", "blah"},
|
||||||
|
},
|
||||||
|
expected: &api.ReplicationController{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"run": "foo"},
|
||||||
|
},
|
||||||
|
Spec: api.ReplicationControllerSpec{
|
||||||
|
Replicas: 1,
|
||||||
|
Selector: map[string]string{"run": "foo"},
|
||||||
|
Template: &api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"run": "foo"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
Args: []string{"bar", "baz", "blah"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]interface{}{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "someimage",
|
||||||
|
"replicas": "1",
|
||||||
|
"port": "-1",
|
||||||
|
"args": []string{"bar", "baz", "blah"},
|
||||||
|
"command": "true",
|
||||||
|
},
|
||||||
|
expected: &api.ReplicationController{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Labels: map[string]string{"run": "foo"},
|
||||||
|
},
|
||||||
|
Spec: api.ReplicationControllerSpec{
|
||||||
|
Replicas: 1,
|
||||||
|
Selector: map[string]string{"run": "foo"},
|
||||||
|
Template: &api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"run": "foo"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "someimage",
|
||||||
|
Command: []string{"bar", "baz", "blah"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
@ -97,7 +164,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
@ -135,7 +202,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
@ -145,7 +212,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
@ -193,12 +260,12 @@ func TestGenerate(t *testing.T) {
|
|||||||
|
|
||||||
func TestGeneratePod(t *testing.T) {
|
func TestGeneratePod(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
params map[string]string
|
params map[string]interface{}
|
||||||
expected *api.Pod
|
expected *api.Pod
|
||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"port": "-1",
|
"port": "-1",
|
||||||
@ -221,7 +288,7 @@ func TestGeneratePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -249,7 +316,7 @@ func TestGeneratePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -279,7 +346,7 @@ func TestGeneratePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"hostport": "80",
|
"hostport": "80",
|
||||||
@ -288,7 +355,7 @@ func TestGeneratePod(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"name": "foo",
|
"name": "foo",
|
||||||
"image": "someimage",
|
"image": "someimage",
|
||||||
"replicas": "1",
|
"replicas": "1",
|
||||||
|
@ -32,7 +32,7 @@ func (ServiceGeneratorV1) ParamNames() []GeneratorParam {
|
|||||||
return paramNames()
|
return paramNames()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ServiceGeneratorV1) Generate(params map[string]string) (runtime.Object, error) {
|
func (ServiceGeneratorV1) Generate(params map[string]interface{}) (runtime.Object, error) {
|
||||||
params["port-name"] = "default"
|
params["port-name"] = "default"
|
||||||
return generate(params)
|
return generate(params)
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ func (ServiceGeneratorV2) ParamNames() []GeneratorParam {
|
|||||||
return paramNames()
|
return paramNames()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ServiceGeneratorV2) Generate(params map[string]string) (runtime.Object, error) {
|
func (ServiceGeneratorV2) Generate(params map[string]interface{}) (runtime.Object, error) {
|
||||||
return generate(params)
|
return generate(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,15 @@ func paramNames() []GeneratorParam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generate(params map[string]string) (runtime.Object, error) {
|
func generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
||||||
|
params := map[string]string{}
|
||||||
|
for key, value := range genericParams {
|
||||||
|
strVal, isString := value.(string)
|
||||||
|
if !isString {
|
||||||
|
return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
|
||||||
|
}
|
||||||
|
params[key] = strVal
|
||||||
|
}
|
||||||
selectorString, found := params["selector"]
|
selectorString, found := params["selector"]
|
||||||
if !found || len(selectorString) == 0 {
|
if !found || len(selectorString) == 0 {
|
||||||
return nil, fmt.Errorf("'selector' is a required parameter.")
|
return nil, fmt.Errorf("'selector' is a required parameter.")
|
||||||
|
@ -27,12 +27,12 @@ import (
|
|||||||
func TestGenerateService(t *testing.T) {
|
func TestGenerateService(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
generator Generator
|
generator Generator
|
||||||
params map[string]string
|
params map[string]interface{}
|
||||||
expected api.Service
|
expected api.Service
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -61,7 +61,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
{
|
{
|
||||||
|
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -89,7 +89,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"labels": "key1=value1,key2=value2",
|
"labels": "key1=value1,key2=value2",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -122,7 +122,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -152,7 +152,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -184,7 +184,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -214,7 +214,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV2{},
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -245,7 +245,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV1{},
|
generator: ServiceGeneratorV1{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
@ -274,7 +274,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
generator: ServiceGeneratorV1{},
|
generator: ServiceGeneratorV1{},
|
||||||
params: map[string]string{
|
params: map[string]interface{}{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"port": "80",
|
"port": "80",
|
||||||
|
Loading…
Reference in New Issue
Block a user